]> git.sesse.net Git - ffmpeg/blob - libavformat/output-example.c
aiffdec: use av_get_audio_frame_duration() to set block_duration for AIFF-C
[ffmpeg] / libavformat / output-example.c
1 /*
2  * Copyright (c) 2003 Fabrice Bellard
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22
23 /**
24  * @file
25  * libavformat API example.
26  *
27  * @example libavformat/output-example.c
28  * Output a media file in any supported libavformat format.
29  * The default codecs are used.
30  */
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <math.h>
36
37 #include "libavutil/mathematics.h"
38 #include "libavformat/avformat.h"
39 #include "libswscale/swscale.h"
40
41 #undef exit
42
43 /* 5 seconds stream duration */
44 #define STREAM_DURATION   5.0
45 #define STREAM_FRAME_RATE 25 /* 25 images/s */
46 #define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
47 #define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
48
49 static int sws_flags = SWS_BICUBIC;
50
51 /**************************************************************/
52 /* audio output */
53
54 static float t, tincr, tincr2;
55 static int16_t *samples;
56 static int audio_input_frame_size;
57
58 /*
59  * add an audio output stream
60  */
61 static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id)
62 {
63     AVCodecContext *c;
64     AVStream *st;
65     AVCodec *codec;
66
67     /* find the audio encoder */
68     codec = avcodec_find_encoder(codec_id);
69     if (!codec) {
70         fprintf(stderr, "codec not found\n");
71         exit(1);
72     }
73
74     st = avformat_new_stream(oc, codec);
75     if (!st) {
76         fprintf(stderr, "Could not alloc stream\n");
77         exit(1);
78     }
79
80     c = st->codec;
81
82     /* put sample parameters */
83     c->sample_fmt = AV_SAMPLE_FMT_S16;
84     c->bit_rate = 64000;
85     c->sample_rate = 44100;
86     c->channels = 2;
87
88     // some formats want stream headers to be separate
89     if(oc->oformat->flags & AVFMT_GLOBALHEADER)
90         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
91
92     return st;
93 }
94
95 static void open_audio(AVFormatContext *oc, AVStream *st)
96 {
97     AVCodecContext *c;
98
99     c = st->codec;
100
101     /* open it */
102     if (avcodec_open2(c, NULL, NULL) < 0) {
103         fprintf(stderr, "could not open codec\n");
104         exit(1);
105     }
106
107     /* init signal generator */
108     t = 0;
109     tincr = 2 * M_PI * 110.0 / c->sample_rate;
110     /* increment frequency by 110 Hz per second */
111     tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
112
113     if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
114         audio_input_frame_size = 10000;
115     else
116         audio_input_frame_size = c->frame_size;
117     samples = av_malloc(audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt)
118                         * c->channels);
119 }
120
121 /* prepare a 16 bit dummy audio frame of 'frame_size' samples and
122    'nb_channels' channels */
123 static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
124 {
125     int j, i, v;
126     int16_t *q;
127
128     q = samples;
129     for(j=0;j<frame_size;j++) {
130         v = (int)(sin(t) * 10000);
131         for(i = 0; i < nb_channels; i++)
132             *q++ = v;
133         t += tincr;
134         tincr += tincr2;
135     }
136 }
137
138 static void write_audio_frame(AVFormatContext *oc, AVStream *st)
139 {
140     AVCodecContext *c;
141     AVPacket pkt;
142     AVFrame *frame = avcodec_alloc_frame();
143     int got_packet;
144
145     av_init_packet(&pkt);
146     c = st->codec;
147
148     get_audio_frame(samples, audio_input_frame_size, c->channels);
149     frame->nb_samples = audio_input_frame_size;
150     avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (uint8_t *)samples,
151                              audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt)
152                              * c->channels, 1);
153
154     avcodec_encode_audio2(c, &pkt, frame, &got_packet);
155     if (!got_packet)
156         return;
157
158     pkt.stream_index= st->index;
159
160     /* write the compressed frame in the media file */
161     if (av_interleaved_write_frame(oc, &pkt) != 0) {
162         fprintf(stderr, "Error while writing audio frame\n");
163         exit(1);
164     }
165 }
166
167 static void close_audio(AVFormatContext *oc, AVStream *st)
168 {
169     avcodec_close(st->codec);
170
171     av_free(samples);
172 }
173
174 /**************************************************************/
175 /* video output */
176
177 static AVFrame *picture, *tmp_picture;
178 static uint8_t *video_outbuf;
179 static int frame_count, video_outbuf_size;
180
181 /* add a video output stream */
182 static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id)
183 {
184     AVCodecContext *c;
185     AVStream *st;
186     AVCodec *codec;
187
188     /* find the video encoder */
189     codec = avcodec_find_encoder(codec_id);
190     if (!codec) {
191         fprintf(stderr, "codec not found\n");
192         exit(1);
193     }
194
195     st = avformat_new_stream(oc, codec);
196     if (!st) {
197         fprintf(stderr, "Could not alloc stream\n");
198         exit(1);
199     }
200
201     c = st->codec;
202
203     /* put sample parameters */
204     c->bit_rate = 400000;
205     /* resolution must be a multiple of two */
206     c->width = 352;
207     c->height = 288;
208     /* time base: this is the fundamental unit of time (in seconds) in terms
209        of which frame timestamps are represented. for fixed-fps content,
210        timebase should be 1/framerate and timestamp increments should be
211        identically 1. */
212     c->time_base.den = STREAM_FRAME_RATE;
213     c->time_base.num = 1;
214     c->gop_size = 12; /* emit one intra frame every twelve frames at most */
215     c->pix_fmt = STREAM_PIX_FMT;
216     if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
217         /* just for testing, we also add B frames */
218         c->max_b_frames = 2;
219     }
220     if (c->codec_id == CODEC_ID_MPEG1VIDEO){
221         /* Needed to avoid using macroblocks in which some coeffs overflow.
222            This does not happen with normal video, it just happens here as
223            the motion of the chroma plane does not match the luma plane. */
224         c->mb_decision=2;
225     }
226     // some formats want stream headers to be separate
227     if(oc->oformat->flags & AVFMT_GLOBALHEADER)
228         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
229
230     return st;
231 }
232
233 static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height)
234 {
235     AVFrame *picture;
236     uint8_t *picture_buf;
237     int size;
238
239     picture = avcodec_alloc_frame();
240     if (!picture)
241         return NULL;
242     size = avpicture_get_size(pix_fmt, width, height);
243     picture_buf = av_malloc(size);
244     if (!picture_buf) {
245         av_free(picture);
246         return NULL;
247     }
248     avpicture_fill((AVPicture *)picture, picture_buf,
249                    pix_fmt, width, height);
250     return picture;
251 }
252
253 static void open_video(AVFormatContext *oc, AVStream *st)
254 {
255     AVCodecContext *c;
256
257     c = st->codec;
258
259     /* open the codec */
260     if (avcodec_open2(c, NULL, NULL) < 0) {
261         fprintf(stderr, "could not open codec\n");
262         exit(1);
263     }
264
265     video_outbuf = NULL;
266     if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
267         /* allocate output buffer */
268         /* XXX: API change will be done */
269         /* buffers passed into lav* can be allocated any way you prefer,
270            as long as they're aligned enough for the architecture, and
271            they're freed appropriately (such as using av_free for buffers
272            allocated with av_malloc) */
273         video_outbuf_size = 200000;
274         video_outbuf = av_malloc(video_outbuf_size);
275     }
276
277     /* allocate the encoded raw picture */
278     picture = alloc_picture(c->pix_fmt, c->width, c->height);
279     if (!picture) {
280         fprintf(stderr, "Could not allocate picture\n");
281         exit(1);
282     }
283
284     /* if the output format is not YUV420P, then a temporary YUV420P
285        picture is needed too. It is then converted to the required
286        output format */
287     tmp_picture = NULL;
288     if (c->pix_fmt != PIX_FMT_YUV420P) {
289         tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
290         if (!tmp_picture) {
291             fprintf(stderr, "Could not allocate temporary picture\n");
292             exit(1);
293         }
294     }
295 }
296
297 /* prepare a dummy image */
298 static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
299 {
300     int x, y, i;
301
302     i = frame_index;
303
304     /* Y */
305     for(y=0;y<height;y++) {
306         for(x=0;x<width;x++) {
307             pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
308         }
309     }
310
311     /* Cb and Cr */
312     for(y=0;y<height/2;y++) {
313         for(x=0;x<width/2;x++) {
314             pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
315             pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
316         }
317     }
318 }
319
320 static void write_video_frame(AVFormatContext *oc, AVStream *st)
321 {
322     int out_size, ret;
323     AVCodecContext *c;
324     static struct SwsContext *img_convert_ctx;
325
326     c = st->codec;
327
328     if (frame_count >= STREAM_NB_FRAMES) {
329         /* no more frame to compress. The codec has a latency of a few
330            frames if using B frames, so we get the last frames by
331            passing the same picture again */
332     } else {
333         if (c->pix_fmt != PIX_FMT_YUV420P) {
334             /* as we only generate a YUV420P picture, we must convert it
335                to the codec pixel format if needed */
336             if (img_convert_ctx == NULL) {
337                 img_convert_ctx = sws_getContext(c->width, c->height,
338                                                  PIX_FMT_YUV420P,
339                                                  c->width, c->height,
340                                                  c->pix_fmt,
341                                                  sws_flags, NULL, NULL, NULL);
342                 if (img_convert_ctx == NULL) {
343                     fprintf(stderr, "Cannot initialize the conversion context\n");
344                     exit(1);
345                 }
346             }
347             fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
348             sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
349                       0, c->height, picture->data, picture->linesize);
350         } else {
351             fill_yuv_image(picture, frame_count, c->width, c->height);
352         }
353     }
354
355
356     if (oc->oformat->flags & AVFMT_RAWPICTURE) {
357         /* raw video case. The API will change slightly in the near
358            futur for that */
359         AVPacket pkt;
360         av_init_packet(&pkt);
361
362         pkt.flags |= AV_PKT_FLAG_KEY;
363         pkt.stream_index= st->index;
364         pkt.data= (uint8_t *)picture;
365         pkt.size= sizeof(AVPicture);
366
367         ret = av_interleaved_write_frame(oc, &pkt);
368     } else {
369         /* encode the image */
370         out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
371         /* if zero size, it means the image was buffered */
372         if (out_size > 0) {
373             AVPacket pkt;
374             av_init_packet(&pkt);
375
376             if (c->coded_frame->pts != AV_NOPTS_VALUE)
377                 pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
378             if(c->coded_frame->key_frame)
379                 pkt.flags |= AV_PKT_FLAG_KEY;
380             pkt.stream_index= st->index;
381             pkt.data= video_outbuf;
382             pkt.size= out_size;
383
384             /* write the compressed frame in the media file */
385             ret = av_interleaved_write_frame(oc, &pkt);
386         } else {
387             ret = 0;
388         }
389     }
390     if (ret != 0) {
391         fprintf(stderr, "Error while writing video frame\n");
392         exit(1);
393     }
394     frame_count++;
395 }
396
397 static void close_video(AVFormatContext *oc, AVStream *st)
398 {
399     avcodec_close(st->codec);
400     av_free(picture->data[0]);
401     av_free(picture);
402     if (tmp_picture) {
403         av_free(tmp_picture->data[0]);
404         av_free(tmp_picture);
405     }
406     av_free(video_outbuf);
407 }
408
409 /**************************************************************/
410 /* media file output */
411
412 int main(int argc, char **argv)
413 {
414     const char *filename;
415     AVOutputFormat *fmt;
416     AVFormatContext *oc;
417     AVStream *audio_st, *video_st;
418     double audio_pts, video_pts;
419     int i;
420
421     /* initialize libavcodec, and register all codecs and formats */
422     av_register_all();
423
424     if (argc != 2) {
425         printf("usage: %s output_file\n"
426                "API example program to output a media file with libavformat.\n"
427                "The output format is automatically guessed according to the file extension.\n"
428                "Raw images can also be output by using '%%d' in the filename\n"
429                "\n", argv[0]);
430         return 1;
431     }
432
433     filename = argv[1];
434
435     /* auto detect the output format from the name. default is
436        mpeg. */
437     fmt = av_guess_format(NULL, filename, NULL);
438     if (!fmt) {
439         printf("Could not deduce output format from file extension: using MPEG.\n");
440         fmt = av_guess_format("mpeg", NULL, NULL);
441     }
442     if (!fmt) {
443         fprintf(stderr, "Could not find suitable output format\n");
444         return 1;
445     }
446
447     /* allocate the output media context */
448     oc = avformat_alloc_context();
449     if (!oc) {
450         fprintf(stderr, "Memory error\n");
451         return 1;
452     }
453     oc->oformat = fmt;
454     snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
455
456     /* add the audio and video streams using the default format codecs
457        and initialize the codecs */
458     video_st = NULL;
459     audio_st = NULL;
460     if (fmt->video_codec != CODEC_ID_NONE) {
461         video_st = add_video_stream(oc, fmt->video_codec);
462     }
463     if (fmt->audio_codec != CODEC_ID_NONE) {
464         audio_st = add_audio_stream(oc, fmt->audio_codec);
465     }
466
467     av_dump_format(oc, 0, filename, 1);
468
469     /* now that all the parameters are set, we can open the audio and
470        video codecs and allocate the necessary encode buffers */
471     if (video_st)
472         open_video(oc, video_st);
473     if (audio_st)
474         open_audio(oc, audio_st);
475
476     /* open the output file, if needed */
477     if (!(fmt->flags & AVFMT_NOFILE)) {
478         if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
479             fprintf(stderr, "Could not open '%s'\n", filename);
480             return 1;
481         }
482     }
483
484     /* write the stream header, if any */
485     avformat_write_header(oc, NULL);
486
487     for(;;) {
488         /* compute current audio and video time */
489         if (audio_st)
490             audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
491         else
492             audio_pts = 0.0;
493
494         if (video_st)
495             video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
496         else
497             video_pts = 0.0;
498
499         if ((!audio_st || audio_pts >= STREAM_DURATION) &&
500             (!video_st || video_pts >= STREAM_DURATION))
501             break;
502
503         /* write interleaved audio and video frames */
504         if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
505             write_audio_frame(oc, audio_st);
506         } else {
507             write_video_frame(oc, video_st);
508         }
509     }
510
511     /* write the trailer, if any.  the trailer must be written
512      * before you close the CodecContexts open when you wrote the
513      * header; otherwise write_trailer may try to use memory that
514      * was freed on av_codec_close() */
515     av_write_trailer(oc);
516
517     /* close each codec */
518     if (video_st)
519         close_video(oc, video_st);
520     if (audio_st)
521         close_audio(oc, audio_st);
522
523     /* free the streams */
524     for(i = 0; i < oc->nb_streams; i++) {
525         av_freep(&oc->streams[i]->codec);
526         av_freep(&oc->streams[i]);
527     }
528
529     if (!(fmt->flags & AVFMT_NOFILE)) {
530         /* close the output file */
531         avio_close(oc->pb);
532     }
533
534     /* free the stream */
535     av_free(oc);
536
537     return 0;
538 }