Statistics
| Branch: | Revision:

ffmpeg / output_example.c @ 3a74415d

History | View | Annotate | Download (15.9 KB)

1 8de65d4f Fabrice Bellard
/*
2
 * Libavformat API example: Output a media file in any supported
3
 * libavformat format. The default codecs are used.
4 115329f1 Diego Biurrun
 *
5 8de65d4f Fabrice Bellard
 * Copyright (c) 2003 Fabrice Bellard
6 115329f1 Diego Biurrun
 *
7 8de65d4f Fabrice Bellard
 * 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:
13 115329f1 Diego Biurrun
 *
14 8de65d4f Fabrice Bellard
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16 115329f1 Diego Biurrun
 *
17 8de65d4f Fabrice Bellard
 * 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
23 115329f1 Diego Biurrun
 * THE SOFTWARE.
24 8de65d4f Fabrice Bellard
 */
25
#include <stdlib.h>
26
#include <stdio.h>
27 af547ce5 Michael Niedermayer
#include <string.h>
28 8de65d4f Fabrice Bellard
#include <math.h>
29
30 264cb2b8 Michael Niedermayer
#ifndef M_PI
31 a40de112 Panagiotis Issaris
#define M_PI 3.14159265358979323846
32 264cb2b8 Michael Niedermayer
#endif
33
34 8de65d4f Fabrice Bellard
#include "avformat.h"
35 03ae87a3 Luca Abeni
#include "swscale.h"
36 8de65d4f Fabrice Bellard
37
/* 5 seconds stream duration */
38 cb0c448a Fabrice Bellard
#define STREAM_DURATION   5.0
39
#define STREAM_FRAME_RATE 25 /* 25 images/s */
40
#define STREAM_NB_FRAMES  ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
41 002c01a6 Andreas Öman
#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
42 8de65d4f Fabrice Bellard
43 03ae87a3 Luca Abeni
static int sws_flags = SWS_BICUBIC;
44
45 8de65d4f Fabrice Bellard
/**************************************************************/
46
/* audio output */
47
48 e70fcf07 Fabrice Bellard
float t, tincr, tincr2;
49 8de65d4f Fabrice Bellard
int16_t *samples;
50
uint8_t *audio_outbuf;
51
int audio_outbuf_size;
52
int audio_input_frame_size;
53
54 115329f1 Diego Biurrun
/*
55 8de65d4f Fabrice Bellard
 * add an audio output stream
56
 */
57 ceaf1909 Dieter
static AVStream *add_audio_stream(AVFormatContext *oc, int codec_id)
58 8de65d4f Fabrice Bellard
{
59
    AVCodecContext *c;
60
    AVStream *st;
61
62
    st = av_new_stream(oc, 1);
63
    if (!st) {
64
        fprintf(stderr, "Could not alloc stream\n");
65
        exit(1);
66
    }
67
68 01f4895c Michael Niedermayer
    c = st->codec;
69 e70fcf07 Fabrice Bellard
    c->codec_id = codec_id;
70 8de65d4f Fabrice Bellard
    c->codec_type = CODEC_TYPE_AUDIO;
71
72
    /* put sample parameters */
73
    c->bit_rate = 64000;
74
    c->sample_rate = 44100;
75
    c->channels = 2;
76 e70fcf07 Fabrice Bellard
    return st;
77
}
78
79 ceaf1909 Dieter
static void open_audio(AVFormatContext *oc, AVStream *st)
80 e70fcf07 Fabrice Bellard
{
81
    AVCodecContext *c;
82
    AVCodec *codec;
83
84 01f4895c Michael Niedermayer
    c = st->codec;
85 e70fcf07 Fabrice Bellard
86
    /* find the audio encoder */
87
    codec = avcodec_find_encoder(c->codec_id);
88
    if (!codec) {
89
        fprintf(stderr, "codec not found\n");
90
        exit(1);
91
    }
92 8de65d4f Fabrice Bellard
93
    /* open it */
94
    if (avcodec_open(c, codec) < 0) {
95
        fprintf(stderr, "could not open codec\n");
96
        exit(1);
97
    }
98
99
    /* init signal generator */
100
    t = 0;
101 e70fcf07 Fabrice Bellard
    tincr = 2 * M_PI * 110.0 / c->sample_rate;
102
    /* increment frequency by 110 Hz per second */
103
    tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
104 8de65d4f Fabrice Bellard
105
    audio_outbuf_size = 10000;
106 5d915e82 Ramiro Polla
    audio_outbuf = av_malloc(audio_outbuf_size);
107 8de65d4f Fabrice Bellard
108
    /* ugly hack for PCM codecs (will be removed ASAP with new PCM
109
       support to compute the input frame size in samples */
110
    if (c->frame_size <= 1) {
111
        audio_input_frame_size = audio_outbuf_size / c->channels;
112 01f4895c Michael Niedermayer
        switch(st->codec->codec_id) {
113 8de65d4f Fabrice Bellard
        case CODEC_ID_PCM_S16LE:
114
        case CODEC_ID_PCM_S16BE:
115
        case CODEC_ID_PCM_U16LE:
116
        case CODEC_ID_PCM_U16BE:
117
            audio_input_frame_size >>= 1;
118
            break;
119
        default:
120
            break;
121
        }
122
    } else {
123
        audio_input_frame_size = c->frame_size;
124
    }
125 5d915e82 Ramiro Polla
    samples = av_malloc(audio_input_frame_size * 2 * c->channels);
126 8de65d4f Fabrice Bellard
}
127
128 cb750e33 Fabrice Bellard
/* prepare a 16 bit dummy audio frame of 'frame_size' samples and
129
   'nb_channels' channels */
130 ceaf1909 Dieter
static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
131 cb750e33 Fabrice Bellard
{
132
    int j, i, v;
133
    int16_t *q;
134
135
    q = samples;
136
    for(j=0;j<frame_size;j++) {
137
        v = (int)(sin(t) * 10000);
138
        for(i = 0; i < nb_channels; i++)
139
            *q++ = v;
140
        t += tincr;
141
        tincr += tincr2;
142
    }
143
}
144
145 ceaf1909 Dieter
static void write_audio_frame(AVFormatContext *oc, AVStream *st)
146 8de65d4f Fabrice Bellard
{
147
    AVCodecContext *c;
148 e928649b Michael Niedermayer
    AVPacket pkt;
149
    av_init_packet(&pkt);
150 115329f1 Diego Biurrun
151 01f4895c Michael Niedermayer
    c = st->codec;
152 8de65d4f Fabrice Bellard
153 cb750e33 Fabrice Bellard
    get_audio_frame(samples, audio_input_frame_size, c->channels);
154
155 e928649b Michael Niedermayer
    pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
156
157 002c01a6 Andreas Öman
    pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
158 e928649b Michael Niedermayer
    pkt.flags |= PKT_FLAG_KEY;
159
    pkt.stream_index= st->index;
160
    pkt.data= audio_outbuf;
161 8de65d4f Fabrice Bellard
162
    /* write the compressed frame in the media file */
163 e928649b Michael Niedermayer
    if (av_write_frame(oc, &pkt) != 0) {
164 8de65d4f Fabrice Bellard
        fprintf(stderr, "Error while writing audio frame\n");
165
        exit(1);
166
    }
167
}
168
169 ceaf1909 Dieter
static void close_audio(AVFormatContext *oc, AVStream *st)
170 e70fcf07 Fabrice Bellard
{
171 01f4895c Michael Niedermayer
    avcodec_close(st->codec);
172 115329f1 Diego Biurrun
173 e70fcf07 Fabrice Bellard
    av_free(samples);
174
    av_free(audio_outbuf);
175
}
176
177 8de65d4f Fabrice Bellard
/**************************************************************/
178
/* video output */
179
180 e70fcf07 Fabrice Bellard
AVFrame *picture, *tmp_picture;
181 8de65d4f Fabrice Bellard
uint8_t *video_outbuf;
182
int frame_count, video_outbuf_size;
183
184
/* add a video output stream */
185 ceaf1909 Dieter
static AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
186 8de65d4f Fabrice Bellard
{
187
    AVCodecContext *c;
188
    AVStream *st;
189
190
    st = av_new_stream(oc, 0);
191
    if (!st) {
192
        fprintf(stderr, "Could not alloc stream\n");
193
        exit(1);
194
    }
195 115329f1 Diego Biurrun
196 01f4895c Michael Niedermayer
    c = st->codec;
197 e70fcf07 Fabrice Bellard
    c->codec_id = codec_id;
198 8de65d4f Fabrice Bellard
    c->codec_type = CODEC_TYPE_VIDEO;
199
200
    /* put sample parameters */
201
    c->bit_rate = 400000;
202
    /* resolution must be a multiple of two */
203 115329f1 Diego Biurrun
    c->width = 352;
204 8de65d4f Fabrice Bellard
    c->height = 288;
205 5b28c8c3 Michael Niedermayer
    /* time base: this is the fundamental unit of time (in seconds) in terms
206
       of which frame timestamps are represented. for fixed-fps content,
207
       timebase should be 1/framerate and timestamp increments should be
208
       identically 1. */
209 115329f1 Diego Biurrun
    c->time_base.den = STREAM_FRAME_RATE;
210 c0df9d75 Michael Niedermayer
    c->time_base.num = 1;
211 cb0c448a Fabrice Bellard
    c->gop_size = 12; /* emit one intra frame every twelve frames at most */
212 002c01a6 Andreas Öman
    c->pix_fmt = STREAM_PIX_FMT;
213 85e33747 Michael Niedermayer
    if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
214 cb0c448a Fabrice Bellard
        /* just for testing, we also add B frames */
215
        c->max_b_frames = 2;
216
    }
217 85e33747 Michael Niedermayer
    if (c->codec_id == CODEC_ID_MPEG1VIDEO){
218 115329f1 Diego Biurrun
        /* needed to avoid using macroblocks in which some coeffs overflow
219
           this doesnt happen with normal video, it just happens here as the
220 85e33747 Michael Niedermayer
           motion of the chroma plane doesnt match the luma plane */
221
        c->mb_decision=2;
222
    }
223 0afd2a92 Diego Biurrun
    // some formats want stream headers to be separate
224 af547ce5 Michael Niedermayer
    if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
225
        c->flags |= CODEC_FLAG_GLOBAL_HEADER;
226 115329f1 Diego Biurrun
227 e70fcf07 Fabrice Bellard
    return st;
228
}
229
230 ceaf1909 Dieter
static AVFrame *alloc_picture(int pix_fmt, int width, int height)
231 e70fcf07 Fabrice Bellard
{
232
    AVFrame *picture;
233
    uint8_t *picture_buf;
234
    int size;
235 115329f1 Diego Biurrun
236 e70fcf07 Fabrice Bellard
    picture = avcodec_alloc_frame();
237
    if (!picture)
238
        return NULL;
239
    size = avpicture_get_size(pix_fmt, width, height);
240 5d915e82 Ramiro Polla
    picture_buf = av_malloc(size);
241 e70fcf07 Fabrice Bellard
    if (!picture_buf) {
242
        av_free(picture);
243
        return NULL;
244
    }
245 115329f1 Diego Biurrun
    avpicture_fill((AVPicture *)picture, picture_buf,
246 e70fcf07 Fabrice Bellard
                   pix_fmt, width, height);
247
    return picture;
248
}
249 115329f1 Diego Biurrun
250 ceaf1909 Dieter
static void open_video(AVFormatContext *oc, AVStream *st)
251 e70fcf07 Fabrice Bellard
{
252
    AVCodec *codec;
253
    AVCodecContext *c;
254
255 01f4895c Michael Niedermayer
    c = st->codec;
256 e70fcf07 Fabrice Bellard
257
    /* find the video encoder */
258
    codec = avcodec_find_encoder(c->codec_id);
259
    if (!codec) {
260
        fprintf(stderr, "codec not found\n");
261
        exit(1);
262
    }
263
264
    /* open the codec */
265 8de65d4f Fabrice Bellard
    if (avcodec_open(c, codec) < 0) {
266
        fprintf(stderr, "could not open codec\n");
267
        exit(1);
268
    }
269
270 e70fcf07 Fabrice Bellard
    video_outbuf = NULL;
271
    if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
272
        /* allocate output buffer */
273
        /* XXX: API change will be done */
274 5d915e82 Ramiro Polla
        /* buffers passed into lav* can be allocated any way you prefer,
275
           as long as they're aligned enough for the architecture, and
276
           they're freed appropriately (such as using av_free for buffers
277
           allocated with av_malloc) */
278 e70fcf07 Fabrice Bellard
        video_outbuf_size = 200000;
279 5d915e82 Ramiro Polla
        video_outbuf = av_malloc(video_outbuf_size);
280 e70fcf07 Fabrice Bellard
    }
281 8de65d4f Fabrice Bellard
282 e70fcf07 Fabrice Bellard
    /* allocate the encoded raw picture */
283
    picture = alloc_picture(c->pix_fmt, c->width, c->height);
284
    if (!picture) {
285
        fprintf(stderr, "Could not allocate picture\n");
286
        exit(1);
287
    }
288 8de65d4f Fabrice Bellard
289 e70fcf07 Fabrice Bellard
    /* if the output format is not YUV420P, then a temporary YUV420P
290
       picture is needed too. It is then converted to the required
291
       output format */
292
    tmp_picture = NULL;
293
    if (c->pix_fmt != PIX_FMT_YUV420P) {
294
        tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
295
        if (!tmp_picture) {
296
            fprintf(stderr, "Could not allocate temporary picture\n");
297
            exit(1);
298
        }
299
    }
300
}
301 8de65d4f Fabrice Bellard
302 e70fcf07 Fabrice Bellard
/* prepare a dummy image */
303 ceaf1909 Dieter
static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
304 8de65d4f Fabrice Bellard
{
305 e70fcf07 Fabrice Bellard
    int x, y, i;
306
307
    i = frame_index;
308 8de65d4f Fabrice Bellard
309
    /* Y */
310 e70fcf07 Fabrice Bellard
    for(y=0;y<height;y++) {
311
        for(x=0;x<width;x++) {
312
            pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
313 8de65d4f Fabrice Bellard
        }
314
    }
315 115329f1 Diego Biurrun
316 8de65d4f Fabrice Bellard
    /* Cb and Cr */
317 e70fcf07 Fabrice Bellard
    for(y=0;y<height/2;y++) {
318
        for(x=0;x<width/2;x++) {
319
            pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
320
            pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
321 8de65d4f Fabrice Bellard
        }
322
    }
323 e70fcf07 Fabrice Bellard
}
324 8de65d4f Fabrice Bellard
325 ceaf1909 Dieter
static void write_video_frame(AVFormatContext *oc, AVStream *st)
326 e70fcf07 Fabrice Bellard
{
327
    int out_size, ret;
328
    AVCodecContext *c;
329 03ae87a3 Luca Abeni
    static struct SwsContext *img_convert_ctx;
330 115329f1 Diego Biurrun
331 01f4895c Michael Niedermayer
    c = st->codec;
332 115329f1 Diego Biurrun
333 cb0c448a Fabrice Bellard
    if (frame_count >= STREAM_NB_FRAMES) {
334
        /* no more frame to compress. The codec has a latency of a few
335
           frames if using B frames, so we get the last frames by
336 002c01a6 Andreas Öman
           passing the same picture again */
337 e70fcf07 Fabrice Bellard
    } else {
338 cb0c448a Fabrice Bellard
        if (c->pix_fmt != PIX_FMT_YUV420P) {
339
            /* as we only generate a YUV420P picture, we must convert it
340
               to the codec pixel format if needed */
341 03ae87a3 Luca Abeni
            if (img_convert_ctx == NULL) {
342
                img_convert_ctx = sws_getContext(c->width, c->height,
343
                                                 PIX_FMT_YUV420P,
344
                                                 c->width, c->height,
345
                                                 c->pix_fmt,
346
                                                 sws_flags, NULL, NULL, NULL);
347
                if (img_convert_ctx == NULL) {
348
                    fprintf(stderr, "Cannot initialize the conversion context\n");
349
                    exit(1);
350
                }
351
            }
352 cb0c448a Fabrice Bellard
            fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
353 03ae87a3 Luca Abeni
            sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
354
                      0, c->height, picture->data, picture->linesize);
355 cb0c448a Fabrice Bellard
        } else {
356
            fill_yuv_image(picture, frame_count, c->width, c->height);
357
        }
358 e70fcf07 Fabrice Bellard
    }
359
360 115329f1 Diego Biurrun
361 e70fcf07 Fabrice Bellard
    if (oc->oformat->flags & AVFMT_RAWPICTURE) {
362
        /* raw video case. The API will change slightly in the near
363
           futur for that */
364 e928649b Michael Niedermayer
        AVPacket pkt;
365
        av_init_packet(&pkt);
366 115329f1 Diego Biurrun
367 e928649b Michael Niedermayer
        pkt.flags |= PKT_FLAG_KEY;
368
        pkt.stream_index= st->index;
369 002c01a6 Andreas Öman
        pkt.data= (uint8_t *)picture;
370 e928649b Michael Niedermayer
        pkt.size= sizeof(AVPicture);
371 115329f1 Diego Biurrun
372 e928649b Michael Niedermayer
        ret = av_write_frame(oc, &pkt);
373 e70fcf07 Fabrice Bellard
    } else {
374
        /* encode the image */
375 002c01a6 Andreas Öman
        out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
376 cb0c448a Fabrice Bellard
        /* if zero size, it means the image was buffered */
377 b5bc8591 Michael Niedermayer
        if (out_size > 0) {
378 e928649b Michael Niedermayer
            AVPacket pkt;
379
            av_init_packet(&pkt);
380 115329f1 Diego Biurrun
381 002c01a6 Andreas Öman
            pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
382 e928649b Michael Niedermayer
            if(c->coded_frame->key_frame)
383
                pkt.flags |= PKT_FLAG_KEY;
384
            pkt.stream_index= st->index;
385
            pkt.data= video_outbuf;
386
            pkt.size= out_size;
387 115329f1 Diego Biurrun
388 cb0c448a Fabrice Bellard
            /* write the compressed frame in the media file */
389 e928649b Michael Niedermayer
            ret = av_write_frame(oc, &pkt);
390 cb0c448a Fabrice Bellard
        } else {
391
            ret = 0;
392
        }
393 e70fcf07 Fabrice Bellard
    }
394
    if (ret != 0) {
395 8de65d4f Fabrice Bellard
        fprintf(stderr, "Error while writing video frame\n");
396
        exit(1);
397
    }
398 e70fcf07 Fabrice Bellard
    frame_count++;
399
}
400
401 ceaf1909 Dieter
static void close_video(AVFormatContext *oc, AVStream *st)
402 e70fcf07 Fabrice Bellard
{
403 01f4895c Michael Niedermayer
    avcodec_close(st->codec);
404 e70fcf07 Fabrice Bellard
    av_free(picture->data[0]);
405
    av_free(picture);
406
    if (tmp_picture) {
407
        av_free(tmp_picture->data[0]);
408
        av_free(tmp_picture);
409
    }
410
    av_free(video_outbuf);
411 8de65d4f Fabrice Bellard
}
412
413
/**************************************************************/
414
/* media file output */
415
416
int main(int argc, char **argv)
417
{
418
    const char *filename;
419
    AVOutputFormat *fmt;
420
    AVFormatContext *oc;
421 e70fcf07 Fabrice Bellard
    AVStream *audio_st, *video_st;
422 8de65d4f Fabrice Bellard
    double audio_pts, video_pts;
423 e70fcf07 Fabrice Bellard
    int i;
424
425 8de65d4f Fabrice Bellard
    /* initialize libavcodec, and register all codecs and formats */
426
    av_register_all();
427 115329f1 Diego Biurrun
428 8de65d4f Fabrice Bellard
    if (argc != 2) {
429
        printf("usage: %s output_file\n"
430 e70fcf07 Fabrice Bellard
               "API example program to output a media file with libavformat.\n"
431
               "The output format is automatically guessed according to the file extension.\n"
432
               "Raw images can also be output by using '%%d' in the filename\n"
433 8de65d4f Fabrice Bellard
               "\n", argv[0]);
434
        exit(1);
435
    }
436 115329f1 Diego Biurrun
437 8de65d4f Fabrice Bellard
    filename = argv[1];
438
439
    /* auto detect the output format from the name. default is
440
       mpeg. */
441
    fmt = guess_format(NULL, filename, NULL);
442
    if (!fmt) {
443
        printf("Could not deduce output format from file extension: using MPEG.\n");
444
        fmt = guess_format("mpeg", NULL, NULL);
445
    }
446
    if (!fmt) {
447
        fprintf(stderr, "Could not find suitable output format\n");
448
        exit(1);
449
    }
450 115329f1 Diego Biurrun
451 8de65d4f Fabrice Bellard
    /* allocate the output media context */
452 bc874dae Michel Bardiaux
    oc = av_alloc_format_context();
453 8de65d4f Fabrice Bellard
    if (!oc) {
454
        fprintf(stderr, "Memory error\n");
455
        exit(1);
456
    }
457
    oc->oformat = fmt;
458 e70fcf07 Fabrice Bellard
    snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
459 8de65d4f Fabrice Bellard
460
    /* add the audio and video streams using the default format codecs
461
       and initialize the codecs */
462
    video_st = NULL;
463
    audio_st = NULL;
464
    if (fmt->video_codec != CODEC_ID_NONE) {
465
        video_st = add_video_stream(oc, fmt->video_codec);
466
    }
467
    if (fmt->audio_codec != CODEC_ID_NONE) {
468
        audio_st = add_audio_stream(oc, fmt->audio_codec);
469
    }
470
471 e70fcf07 Fabrice Bellard
    /* set the output parameters (must be done even if no
472
       parameters). */
473
    if (av_set_parameters(oc, NULL) < 0) {
474
        fprintf(stderr, "Invalid output format parameters\n");
475
        exit(1);
476
    }
477
478 8de65d4f Fabrice Bellard
    dump_format(oc, 0, filename, 1);
479
480 e70fcf07 Fabrice Bellard
    /* now that all the parameters are set, we can open the audio and
481
       video codecs and allocate the necessary encode buffers */
482
    if (video_st)
483
        open_video(oc, video_st);
484
    if (audio_st)
485
        open_audio(oc, audio_st);
486
487 8de65d4f Fabrice Bellard
    /* open the output file, if needed */
488
    if (!(fmt->flags & AVFMT_NOFILE)) {
489
        if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
490
            fprintf(stderr, "Could not open '%s'\n", filename);
491
            exit(1);
492
        }
493
    }
494 115329f1 Diego Biurrun
495 8de65d4f Fabrice Bellard
    /* write the stream header, if any */
496
    av_write_header(oc);
497 115329f1 Diego Biurrun
498 8de65d4f Fabrice Bellard
    for(;;) {
499
        /* compute current audio and video time */
500
        if (audio_st)
501 e06d3d55 Michael Niedermayer
            audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
502 8de65d4f Fabrice Bellard
        else
503
            audio_pts = 0.0;
504 115329f1 Diego Biurrun
505 8de65d4f Fabrice Bellard
        if (video_st)
506 e06d3d55 Michael Niedermayer
            video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
507 8de65d4f Fabrice Bellard
        else
508
            video_pts = 0.0;
509
510 115329f1 Diego Biurrun
        if ((!audio_st || audio_pts >= STREAM_DURATION) &&
511 8de65d4f Fabrice Bellard
            (!video_st || video_pts >= STREAM_DURATION))
512
            break;
513 115329f1 Diego Biurrun
514 8de65d4f Fabrice Bellard
        /* write interleaved audio and video frames */
515 e70fcf07 Fabrice Bellard
        if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
516 8de65d4f Fabrice Bellard
            write_audio_frame(oc, audio_st);
517
        } else {
518
            write_video_frame(oc, video_st);
519
        }
520
    }
521
522
    /* close each codec */
523 e70fcf07 Fabrice Bellard
    if (video_st)
524
        close_video(oc, video_st);
525
    if (audio_st)
526
        close_audio(oc, audio_st);
527 8de65d4f Fabrice Bellard
528
    /* write the trailer, if any */
529
    av_write_trailer(oc);
530 115329f1 Diego Biurrun
531 e70fcf07 Fabrice Bellard
    /* free the streams */
532
    for(i = 0; i < oc->nb_streams; i++) {
533 8720de5b Michael Niedermayer
        av_freep(&oc->streams[i]->codec);
534 e70fcf07 Fabrice Bellard
        av_freep(&oc->streams[i]);
535
    }
536
537 8de65d4f Fabrice Bellard
    if (!(fmt->flags & AVFMT_NOFILE)) {
538
        /* close the output file */
539
        url_fclose(&oc->pb);
540
    }
541
542
    /* free the stream */
543
    av_free(oc);
544
545
    return 0;
546
}