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 #define M_PI 3.1415926535897931
36 /* 5 seconds stream duration */
37 #define STREAM_DURATION 5.0
38 #define STREAM_FRAME_RATE 25 /* 25 images/s */
39 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
41 /**************************************************************/
44 float t
, tincr
, tincr2
;
46 uint8_t *audio_outbuf
;
47 int audio_outbuf_size
;
48 int audio_input_frame_size
;
51 * add an audio output stream
53 AVStream
*add_audio_stream(AVFormatContext
*oc
, int codec_id
)
58 st
= av_new_stream(oc
, 1);
60 fprintf(stderr
, "Could not alloc stream\n");
65 c
->codec_id
= codec_id
;
66 c
->codec_type
= CODEC_TYPE_AUDIO
;
68 /* put sample parameters */
70 c
->sample_rate
= 44100;
75 void open_audio(AVFormatContext
*oc
, AVStream
*st
)
82 /* find the audio encoder */
83 codec
= avcodec_find_encoder(c
->codec_id
);
85 fprintf(stderr
, "codec not found\n");
90 if (avcodec_open(c
, codec
) < 0) {
91 fprintf(stderr
, "could not open codec\n");
95 /* init signal generator */
97 tincr
= 2 * M_PI
* 110.0 / c
->sample_rate
;
98 /* increment frequency by 110 Hz per second */
99 tincr2
= 2 * M_PI
* 110.0 / c
->sample_rate
/ c
->sample_rate
;
101 audio_outbuf_size
= 10000;
102 audio_outbuf
= malloc(audio_outbuf_size
);
104 /* ugly hack for PCM codecs (will be removed ASAP with new PCM
105 support to compute the input frame size in samples */
106 if (c
->frame_size
<= 1) {
107 audio_input_frame_size
= audio_outbuf_size
/ c
->channels
;
108 switch(st
->codec
.codec_id
) {
109 case CODEC_ID_PCM_S16LE
:
110 case CODEC_ID_PCM_S16BE
:
111 case CODEC_ID_PCM_U16LE
:
112 case CODEC_ID_PCM_U16BE
:
113 audio_input_frame_size
>>= 1;
119 audio_input_frame_size
= c
->frame_size
;
121 samples
= malloc(audio_input_frame_size
* 2 * c
->channels
);
124 /* prepare a 16 bit dummy audio frame of 'frame_size' samples and
125 'nb_channels' channels */
126 void get_audio_frame(int16_t *samples
, int frame_size
, int nb_channels
)
132 for(j
=0;j
<frame_size
;j
++) {
133 v
= (int)(sin(t
) * 10000);
134 for(i
= 0; i
< nb_channels
; i
++)
141 void write_audio_frame(AVFormatContext
*oc
, AVStream
*st
)
149 get_audio_frame(samples
, audio_input_frame_size
, c
->channels
);
151 out_size
= avcodec_encode_audio(c
, audio_outbuf
, audio_outbuf_size
, samples
);
153 /* write the compressed frame in the media file */
154 if (av_write_frame(oc
, st
->index
, audio_outbuf
, out_size
) != 0) {
155 fprintf(stderr
, "Error while writing audio frame\n");
160 void close_audio(AVFormatContext
*oc
, AVStream
*st
)
162 avcodec_close(&st
->codec
);
165 av_free(audio_outbuf
);
168 /**************************************************************/
171 AVFrame
*picture
, *tmp_picture
;
172 uint8_t *video_outbuf
;
173 int frame_count
, video_outbuf_size
;
175 /* add a video output stream */
176 AVStream
*add_video_stream(AVFormatContext
*oc
, int codec_id
)
181 st
= av_new_stream(oc
, 0);
183 fprintf(stderr
, "Could not alloc stream\n");
188 c
->codec_id
= codec_id
;
189 c
->codec_type
= CODEC_TYPE_VIDEO
;
191 /* put sample parameters */
192 c
->bit_rate
= 400000;
193 /* resolution must be a multiple of two */
196 /* frames per second */
197 c
->frame_rate
= STREAM_FRAME_RATE
;
198 c
->frame_rate_base
= 1;
199 c
->gop_size
= 12; /* emit one intra frame every twelve frames at most */
200 if (c
->codec_id
== CODEC_ID_MPEG1VIDEO
||
201 c
->codec_id
== CODEC_ID_MPEG2VIDEO
) {
202 /* just for testing, we also add B frames */
205 // some formats want stream headers to be seperate
206 if(!strcmp(oc
->oformat
->name
, "mp4") || !strcmp(oc
->oformat
->name
, "mov") || !strcmp(oc
->oformat
->name
, "3gp"))
207 c
->flags
|= CODEC_FLAG_GLOBAL_HEADER
;
212 AVFrame
*alloc_picture(int pix_fmt
, int width
, int height
)
215 uint8_t *picture_buf
;
218 picture
= avcodec_alloc_frame();
221 size
= avpicture_get_size(pix_fmt
, width
, height
);
222 picture_buf
= malloc(size
);
227 avpicture_fill((AVPicture
*)picture
, picture_buf
,
228 pix_fmt
, width
, height
);
232 void open_video(AVFormatContext
*oc
, AVStream
*st
)
239 /* find the video encoder */
240 codec
= avcodec_find_encoder(c
->codec_id
);
242 fprintf(stderr
, "codec not found\n");
247 if (avcodec_open(c
, codec
) < 0) {
248 fprintf(stderr
, "could not open codec\n");
253 if (!(oc
->oformat
->flags
& AVFMT_RAWPICTURE
)) {
254 /* allocate output buffer */
255 /* XXX: API change will be done */
256 video_outbuf_size
= 200000;
257 video_outbuf
= malloc(video_outbuf_size
);
260 /* allocate the encoded raw picture */
261 picture
= alloc_picture(c
->pix_fmt
, c
->width
, c
->height
);
263 fprintf(stderr
, "Could not allocate picture\n");
267 /* if the output format is not YUV420P, then a temporary YUV420P
268 picture is needed too. It is then converted to the required
271 if (c
->pix_fmt
!= PIX_FMT_YUV420P
) {
272 tmp_picture
= alloc_picture(PIX_FMT_YUV420P
, c
->width
, c
->height
);
274 fprintf(stderr
, "Could not allocate temporary picture\n");
280 /* prepare a dummy image */
281 void fill_yuv_image(AVFrame
*pict
, int frame_index
, int width
, int height
)
288 for(y
=0;y
<height
;y
++) {
289 for(x
=0;x
<width
;x
++) {
290 pict
->data
[0][y
* pict
->linesize
[0] + x
] = x
+ y
+ i
* 3;
295 for(y
=0;y
<height
/2;y
++) {
296 for(x
=0;x
<width
/2;x
++) {
297 pict
->data
[1][y
* pict
->linesize
[1] + x
] = 128 + y
+ i
* 2;
298 pict
->data
[2][y
* pict
->linesize
[2] + x
] = 64 + x
+ i
* 5;
303 void write_video_frame(AVFormatContext
*oc
, AVStream
*st
)
307 AVFrame
*picture_ptr
;
311 if (frame_count
>= STREAM_NB_FRAMES
) {
312 /* no more frame to compress. The codec has a latency of a few
313 frames if using B frames, so we get the last frames by
314 passing a NULL picture */
317 if (c
->pix_fmt
!= PIX_FMT_YUV420P
) {
318 /* as we only generate a YUV420P picture, we must convert it
319 to the codec pixel format if needed */
320 fill_yuv_image(tmp_picture
, frame_count
, c
->width
, c
->height
);
321 img_convert((AVPicture
*)picture
, c
->pix_fmt
,
322 (AVPicture
*)tmp_picture
, PIX_FMT_YUV420P
,
323 c
->width
, c
->height
);
325 fill_yuv_image(picture
, frame_count
, c
->width
, c
->height
);
327 picture_ptr
= picture
;
331 if (oc
->oformat
->flags
& AVFMT_RAWPICTURE
) {
332 /* raw video case. The API will change slightly in the near
334 ret
= av_write_frame(oc
, st
->index
,
335 (uint8_t *)picture_ptr
, sizeof(AVPicture
));
337 /* encode the image */
338 out_size
= avcodec_encode_video(c
, video_outbuf
, video_outbuf_size
, picture_ptr
);
339 /* if zero size, it means the image was buffered */
341 /* write the compressed frame in the media file */
342 /* XXX: in case of B frames, the pts is not yet valid */
343 ret
= av_write_frame(oc
, st
->index
, video_outbuf
, out_size
);
349 fprintf(stderr
, "Error while writing video frame\n");
355 void close_video(AVFormatContext
*oc
, AVStream
*st
)
357 avcodec_close(&st
->codec
);
358 av_free(picture
->data
[0]);
361 av_free(tmp_picture
->data
[0]);
362 av_free(tmp_picture
);
364 av_free(video_outbuf
);
367 /**************************************************************/
368 /* media file output */
370 int main(int argc
, char **argv
)
372 const char *filename
;
375 AVStream
*audio_st
, *video_st
;
376 double audio_pts
, video_pts
;
379 /* initialize libavcodec, and register all codecs and formats */
383 printf("usage: %s output_file\n"
384 "API example program to output a media file with libavformat.\n"
385 "The output format is automatically guessed according to the file extension.\n"
386 "Raw images can also be output by using '%%d' in the filename\n"
393 /* auto detect the output format from the name. default is
395 fmt
= guess_format(NULL
, filename
, NULL
);
397 printf("Could not deduce output format from file extension: using MPEG.\n");
398 fmt
= guess_format("mpeg", NULL
, NULL
);
401 fprintf(stderr
, "Could not find suitable output format\n");
405 /* allocate the output media context */
406 oc
= av_mallocz(sizeof(AVFormatContext
));
408 fprintf(stderr
, "Memory error\n");
412 snprintf(oc
->filename
, sizeof(oc
->filename
), "%s", filename
);
414 /* add the audio and video streams using the default format codecs
415 and initialize the codecs */
418 if (fmt
->video_codec
!= CODEC_ID_NONE
) {
419 video_st
= add_video_stream(oc
, fmt
->video_codec
);
421 if (fmt
->audio_codec
!= CODEC_ID_NONE
) {
422 audio_st
= add_audio_stream(oc
, fmt
->audio_codec
);
425 /* set the output parameters (must be done even if no
427 if (av_set_parameters(oc
, NULL
) < 0) {
428 fprintf(stderr
, "Invalid output format parameters\n");
432 dump_format(oc
, 0, filename
, 1);
434 /* now that all the parameters are set, we can open the audio and
435 video codecs and allocate the necessary encode buffers */
437 open_video(oc
, video_st
);
439 open_audio(oc
, audio_st
);
441 /* open the output file, if needed */
442 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
443 if (url_fopen(&oc
->pb
, filename
, URL_WRONLY
) < 0) {
444 fprintf(stderr
, "Could not open '%s'\n", filename
);
449 /* write the stream header, if any */
453 /* compute current audio and video time */
455 audio_pts
= (double)audio_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
460 video_pts
= (double)video_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
464 if ((!audio_st
|| audio_pts
>= STREAM_DURATION
) &&
465 (!video_st
|| video_pts
>= STREAM_DURATION
))
468 /* write interleaved audio and video frames */
469 if (!video_st
|| (video_st
&& audio_st
&& audio_pts
< video_pts
)) {
470 write_audio_frame(oc
, audio_st
);
472 write_video_frame(oc
, video_st
);
476 /* close each codec */
478 close_video(oc
, video_st
);
480 close_audio(oc
, audio_st
);
482 /* write the trailer, if any */
483 av_write_trailer(oc
);
485 /* free the streams */
486 for(i
= 0; i
< oc
->nb_streams
; i
++) {
487 av_freep(&oc
->streams
[i
]);
490 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
491 /* close the output file */
495 /* free the stream */