~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/output_example.c

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2004-08-29 10:53:42 UTC
  • Revision ID: james.westby@ubuntu.com-20040829105342-qgmnry37eadfkoxx
Tags: upstream-1.1.3
ImportĀ upstreamĀ versionĀ 1.1.3

Show diffs side-by-side

added added

removed removed

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