2 * Libavformat API example: Output a media file in any supported
3 * libavformat format. The default codecs are used.
5 * Copyright (c) 2003 Fabrice Bellard
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 /* 5 seconds stream duration */
32 #define STREAM_DURATION 5.0
35 /**************************************************************/
40 uint8_t *audio_outbuf
;
41 int audio_outbuf_size
;
42 int audio_input_frame_size
;
45 * add an audio output stream
47 AVStream
*add_audio_stream(AVFormatContext
*oc
, int codec_id
)
53 st
= av_new_stream(oc
, 1);
55 fprintf(stderr
, "Could not alloc stream\n");
59 /* find the MP2 encoder */
60 codec
= avcodec_find_encoder(codec_id
);
62 fprintf(stderr
, "codec not found\n");
67 avcodec_get_context_defaults(c
);
69 c
->codec_type
= CODEC_TYPE_AUDIO
;
71 /* put sample parameters */
73 c
->sample_rate
= 44100;
77 if (avcodec_open(c
, codec
) < 0) {
78 fprintf(stderr
, "could not open codec\n");
82 /* init signal generator */
84 tincr
= 2 * M_PI
* 440.0 / c
->sample_rate
;
86 audio_outbuf_size
= 10000;
87 audio_outbuf
= malloc(audio_outbuf_size
);
89 /* ugly hack for PCM codecs (will be removed ASAP with new PCM
90 support to compute the input frame size in samples */
91 if (c
->frame_size
<= 1) {
92 audio_input_frame_size
= audio_outbuf_size
/ c
->channels
;
93 switch(st
->codec
.codec_id
) {
94 case CODEC_ID_PCM_S16LE
:
95 case CODEC_ID_PCM_S16BE
:
96 case CODEC_ID_PCM_U16LE
:
97 case CODEC_ID_PCM_U16BE
:
98 audio_input_frame_size
>>= 1;
104 audio_input_frame_size
= c
->frame_size
;
106 samples
= malloc(audio_input_frame_size
* 2 * c
->channels
);
111 void write_audio_frame(AVFormatContext
*oc
, AVStream
*st
)
119 for(j
=0;j
<audio_input_frame_size
;j
++) {
120 samples
[2*j
] = (int)(sin(t
) * 10000);
121 samples
[2*j
+1] = samples
[2*j
];
125 out_size
= avcodec_encode_audio(c
, audio_outbuf
, audio_outbuf_size
, samples
);
127 /* write the compressed frame in the media file */
128 if (av_write_frame(oc
, st
->index
, audio_outbuf
, out_size
) != 0) {
129 fprintf(stderr
, "Error while writing audio frame\n");
134 /**************************************************************/
138 uint8_t *video_outbuf
;
139 int frame_count
, video_outbuf_size
;
141 /* add a video output stream */
142 AVStream
*add_video_stream(AVFormatContext
*oc
, int codec_id
)
147 uint8_t *picture_buf
;
150 st
= av_new_stream(oc
, 0);
152 fprintf(stderr
, "Could not alloc stream\n");
156 /* find the mpeg1 video encoder */
157 codec
= avcodec_find_encoder(codec_id
);
159 fprintf(stderr
, "codec not found\n");
165 avcodec_get_context_defaults(c
);
167 c
->codec_type
= CODEC_TYPE_VIDEO
;
169 /* put sample parameters */
170 c
->bit_rate
= 400000;
171 /* resolution must be a multiple of two */
174 /* frames per second */
176 c
->frame_rate_base
= 1;
177 c
->gop_size
= 12; /* emit one intra frame every twelve frames */
180 if (avcodec_open(c
, codec
) < 0) {
181 fprintf(stderr
, "could not open codec\n");
185 /* alloc various buffers */
186 picture
= avcodec_alloc_frame();
187 video_outbuf_size
= 100000;
188 video_outbuf
= malloc(video_outbuf_size
);
190 size
= c
->width
* c
->height
;
191 picture_buf
= malloc((size
* 3) / 2); /* size for YUV 420 */
193 picture
->data
[0] = picture_buf
;
194 picture
->data
[1] = picture
->data
[0] + size
;
195 picture
->data
[2] = picture
->data
[1] + size
/ 4;
196 picture
->linesize
[0] = c
->width
;
197 picture
->linesize
[1] = c
->width
/ 2;
198 picture
->linesize
[2] = c
->width
/ 2;
203 void write_video_frame(AVFormatContext
*oc
, AVStream
*st
)
205 int x
, y
, i
, out_size
;
210 /* prepare a dummy image */
213 for(y
=0;y
<c
->height
;y
++) {
214 for(x
=0;x
<c
->width
;x
++) {
215 picture
->data
[0][y
* picture
->linesize
[0] + x
] = x
+ y
+ i
* 3;
220 for(y
=0;y
<c
->height
/2;y
++) {
221 for(x
=0;x
<c
->width
/2;x
++) {
222 picture
->data
[1][y
* picture
->linesize
[1] + x
] = 128 + y
+ i
* 2;
223 picture
->data
[2][y
* picture
->linesize
[2] + x
] = 64 + x
+ i
* 5;
227 /* encode the image */
228 out_size
= avcodec_encode_video(c
, video_outbuf
, video_outbuf_size
, picture
);
230 /* write the compressed frame in the media file */
231 if (av_write_frame(oc
, st
->index
, video_outbuf
, out_size
) != 0) {
232 fprintf(stderr
, "Error while writing video frame\n");
237 /**************************************************************/
238 /* media file output */
240 int main(int argc
, char **argv
)
242 const char *filename
;
245 AVStream
*st
, *audio_st
, *video_st
;
247 double audio_pts
, video_pts
;
249 /* initialize libavcodec, and register all codecs and formats */
253 printf("usage: %s output_file\n"
254 "API example program for to output media file with libavformat\n"
261 /* auto detect the output format from the name. default is
263 fmt
= guess_format(NULL
, filename
, NULL
);
265 printf("Could not deduce output format from file extension: using MPEG.\n");
266 fmt
= guess_format("mpeg", NULL
, NULL
);
269 fprintf(stderr
, "Could not find suitable output format\n");
273 /* allocate the output media context */
274 oc
= av_mallocz(sizeof(AVFormatContext
));
276 fprintf(stderr
, "Memory error\n");
281 /* add the audio and video streams using the default format codecs
282 and initialize the codecs */
285 if (fmt
->video_codec
!= CODEC_ID_NONE
) {
286 video_st
= add_video_stream(oc
, fmt
->video_codec
);
288 if (fmt
->audio_codec
!= CODEC_ID_NONE
) {
289 audio_st
= add_audio_stream(oc
, fmt
->audio_codec
);
292 dump_format(oc
, 0, filename
, 1);
294 /* open the output file, if needed */
295 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
296 if (url_fopen(&oc
->pb
, filename
, URL_WRONLY
) < 0) {
297 fprintf(stderr
, "Could not open '%s'\n", filename
);
302 /* set the output parameters (must be done even if no parameters) */
303 av_set_parameters(oc
, NULL
);
305 /* write the stream header, if any */
309 /* compute current audio and video time */
311 audio_pts
= (double)audio_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
316 video_pts
= (double)video_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
320 if ((!audio_st
|| audio_pts
>= STREAM_DURATION
) &&
321 (!video_st
|| video_pts
>= STREAM_DURATION
))
324 /* write interleaved audio and video frames */
325 if (!video_st
|| (video_st
&& audio_pts
< video_pts
)) {
326 write_audio_frame(oc
, audio_st
);
328 write_video_frame(oc
, video_st
);
332 /* close each codec */
333 for(i
= 0;i
< oc
->nb_streams
; i
++) {
335 avcodec_close(&st
->codec
);
338 /* write the trailer, if any */
339 av_write_trailer(oc
);
341 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
342 /* close the output file */
346 /* free the stream */