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 /**************************************************************/
38 float t
, tincr
, tincr2
;
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
)
52 st
= av_new_stream(oc
, 1);
54 fprintf(stderr
, "Could not alloc stream\n");
59 c
->codec_id
= codec_id
;
60 c
->codec_type
= CODEC_TYPE_AUDIO
;
62 /* put sample parameters */
64 c
->sample_rate
= 44100;
69 void open_audio(AVFormatContext
*oc
, AVStream
*st
)
76 /* find the audio encoder */
77 codec
= avcodec_find_encoder(c
->codec_id
);
79 fprintf(stderr
, "codec not found\n");
84 if (avcodec_open(c
, codec
) < 0) {
85 fprintf(stderr
, "could not open codec\n");
89 /* init signal generator */
91 tincr
= 2 * M_PI
* 110.0 / c
->sample_rate
;
92 /* increment frequency by 110 Hz per second */
93 tincr2
= 2 * M_PI
* 110.0 / c
->sample_rate
/ c
->sample_rate
;
95 audio_outbuf_size
= 10000;
96 audio_outbuf
= malloc(audio_outbuf_size
);
98 /* ugly hack for PCM codecs (will be removed ASAP with new PCM
99 support to compute the input frame size in samples */
100 if (c
->frame_size
<= 1) {
101 audio_input_frame_size
= audio_outbuf_size
/ c
->channels
;
102 switch(st
->codec
.codec_id
) {
103 case CODEC_ID_PCM_S16LE
:
104 case CODEC_ID_PCM_S16BE
:
105 case CODEC_ID_PCM_U16LE
:
106 case CODEC_ID_PCM_U16BE
:
107 audio_input_frame_size
>>= 1;
113 audio_input_frame_size
= c
->frame_size
;
115 samples
= malloc(audio_input_frame_size
* 2 * c
->channels
);
118 void write_audio_frame(AVFormatContext
*oc
, AVStream
*st
)
126 for(j
=0;j
<audio_input_frame_size
;j
++) {
127 samples
[2*j
] = (int)(sin(t
) * 10000);
128 samples
[2*j
+1] = samples
[2*j
];
133 out_size
= avcodec_encode_audio(c
, audio_outbuf
, audio_outbuf_size
, samples
);
135 /* write the compressed frame in the media file */
136 if (av_write_frame(oc
, st
->index
, audio_outbuf
, out_size
) != 0) {
137 fprintf(stderr
, "Error while writing audio frame\n");
142 void close_audio(AVFormatContext
*oc
, AVStream
*st
)
144 avcodec_close(&st
->codec
);
147 av_free(audio_outbuf
);
150 /**************************************************************/
153 AVFrame
*picture
, *tmp_picture
;
154 uint8_t *video_outbuf
;
155 int frame_count
, video_outbuf_size
;
157 /* add a video output stream */
158 AVStream
*add_video_stream(AVFormatContext
*oc
, int codec_id
)
163 st
= av_new_stream(oc
, 0);
165 fprintf(stderr
, "Could not alloc stream\n");
170 c
->codec_id
= codec_id
;
171 c
->codec_type
= CODEC_TYPE_VIDEO
;
173 /* put sample parameters */
174 c
->bit_rate
= 400000;
175 /* resolution must be a multiple of two */
178 /* frames per second */
180 c
->frame_rate_base
= 1;
181 c
->gop_size
= 12; /* emit one intra frame every twelve frames */
186 AVFrame
*alloc_picture(int pix_fmt
, int width
, int height
)
189 uint8_t *picture_buf
;
192 picture
= avcodec_alloc_frame();
195 size
= avpicture_get_size(pix_fmt
, width
, height
);
196 picture_buf
= malloc(size
);
201 avpicture_fill((AVPicture
*)picture
, picture_buf
,
202 pix_fmt
, width
, height
);
206 void open_video(AVFormatContext
*oc
, AVStream
*st
)
213 /* find the video encoder */
214 codec
= avcodec_find_encoder(c
->codec_id
);
216 fprintf(stderr
, "codec not found\n");
221 if (avcodec_open(c
, codec
) < 0) {
222 fprintf(stderr
, "could not open codec\n");
227 if (!(oc
->oformat
->flags
& AVFMT_RAWPICTURE
)) {
228 /* allocate output buffer */
229 /* XXX: API change will be done */
230 video_outbuf_size
= 200000;
231 video_outbuf
= malloc(video_outbuf_size
);
234 /* allocate the encoded raw picture */
235 picture
= alloc_picture(c
->pix_fmt
, c
->width
, c
->height
);
237 fprintf(stderr
, "Could not allocate picture\n");
241 /* if the output format is not YUV420P, then a temporary YUV420P
242 picture is needed too. It is then converted to the required
245 if (c
->pix_fmt
!= PIX_FMT_YUV420P
) {
246 tmp_picture
= alloc_picture(PIX_FMT_YUV420P
, c
->width
, c
->height
);
248 fprintf(stderr
, "Could not allocate temporary picture\n");
254 /* prepare a dummy image */
255 void fill_yuv_image(AVFrame
*pict
, int frame_index
, int width
, int height
)
262 for(y
=0;y
<height
;y
++) {
263 for(x
=0;x
<width
;x
++) {
264 pict
->data
[0][y
* pict
->linesize
[0] + x
] = x
+ y
+ i
* 3;
269 for(y
=0;y
<height
/2;y
++) {
270 for(x
=0;x
<width
/2;x
++) {
271 pict
->data
[1][y
* pict
->linesize
[1] + x
] = 128 + y
+ i
* 2;
272 pict
->data
[2][y
* pict
->linesize
[2] + x
] = 64 + x
+ i
* 5;
277 void write_video_frame(AVFormatContext
*oc
, AVStream
*st
)
284 if (c
->pix_fmt
!= PIX_FMT_YUV420P
) {
285 /* as we only generate a YUV420P picture, we must convert it
286 to the codec pixel format if needed */
287 fill_yuv_image(tmp_picture
, frame_count
, c
->width
, c
->height
);
288 img_convert((AVPicture
*)picture
, c
->pix_fmt
,
289 (AVPicture
*)tmp_picture
, PIX_FMT_YUV420P
,
290 c
->width
, c
->height
);
292 fill_yuv_image(picture
, frame_count
, c
->width
, c
->height
);
296 if (oc
->oformat
->flags
& AVFMT_RAWPICTURE
) {
297 /* raw video case. The API will change slightly in the near
299 ret
= av_write_frame(oc
, st
->index
,
300 (uint8_t *)picture
, sizeof(AVPicture
));
302 /* encode the image */
303 out_size
= avcodec_encode_video(c
, video_outbuf
, video_outbuf_size
, picture
);
305 /* write the compressed frame in the media file */
306 ret
= av_write_frame(oc
, st
->index
, video_outbuf
, out_size
);
309 fprintf(stderr
, "Error while writing video frame\n");
315 void close_video(AVFormatContext
*oc
, AVStream
*st
)
317 avcodec_close(&st
->codec
);
318 av_free(picture
->data
[0]);
321 av_free(tmp_picture
->data
[0]);
322 av_free(tmp_picture
);
324 av_free(video_outbuf
);
327 /**************************************************************/
328 /* media file output */
330 int main(int argc
, char **argv
)
332 const char *filename
;
335 AVStream
*audio_st
, *video_st
;
336 double audio_pts
, video_pts
;
339 /* initialize libavcodec, and register all codecs and formats */
343 printf("usage: %s output_file\n"
344 "API example program to output a media file with libavformat.\n"
345 "The output format is automatically guessed according to the file extension.\n"
346 "Raw images can also be output by using '%%d' in the filename\n"
353 /* auto detect the output format from the name. default is
355 fmt
= guess_format(NULL
, filename
, NULL
);
357 printf("Could not deduce output format from file extension: using MPEG.\n");
358 fmt
= guess_format("mpeg", NULL
, NULL
);
361 fprintf(stderr
, "Could not find suitable output format\n");
365 /* allocate the output media context */
366 oc
= av_mallocz(sizeof(AVFormatContext
));
368 fprintf(stderr
, "Memory error\n");
372 snprintf(oc
->filename
, sizeof(oc
->filename
), "%s", filename
);
374 /* add the audio and video streams using the default format codecs
375 and initialize the codecs */
378 if (fmt
->video_codec
!= CODEC_ID_NONE
) {
379 video_st
= add_video_stream(oc
, fmt
->video_codec
);
381 if (fmt
->audio_codec
!= CODEC_ID_NONE
) {
382 audio_st
= add_audio_stream(oc
, fmt
->audio_codec
);
385 /* set the output parameters (must be done even if no
387 if (av_set_parameters(oc
, NULL
) < 0) {
388 fprintf(stderr
, "Invalid output format parameters\n");
392 dump_format(oc
, 0, filename
, 1);
394 /* now that all the parameters are set, we can open the audio and
395 video codecs and allocate the necessary encode buffers */
397 open_video(oc
, video_st
);
399 open_audio(oc
, audio_st
);
401 /* open the output file, if needed */
402 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
403 if (url_fopen(&oc
->pb
, filename
, URL_WRONLY
) < 0) {
404 fprintf(stderr
, "Could not open '%s'\n", filename
);
409 /* write the stream header, if any */
413 /* compute current audio and video time */
415 audio_pts
= (double)audio_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
420 video_pts
= (double)video_st
->pts
.val
* oc
->pts_num
/ oc
->pts_den
;
424 if ((!audio_st
|| audio_pts
>= STREAM_DURATION
) &&
425 (!video_st
|| video_pts
>= STREAM_DURATION
))
428 /* write interleaved audio and video frames */
429 if (!video_st
|| (video_st
&& audio_st
&& audio_pts
< video_pts
)) {
430 write_audio_frame(oc
, audio_st
);
432 write_video_frame(oc
, video_st
);
436 /* close each codec */
438 close_video(oc
, video_st
);
440 close_audio(oc
, audio_st
);
442 /* write the trailer, if any */
443 av_write_trailer(oc
);
445 /* free the streams */
446 for(i
= 0; i
< oc
->nb_streams
; i
++) {
447 av_freep(&oc
->streams
[i
]);
450 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
451 /* close the output file */
455 /* free the stream */