decoding_encoding.c 18.7 KB
Newer Older
1
/*
2
 * Copyright (c) 2001 Fabrice Bellard
3
 *
4 5 6 7 8 9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
10
 *
11 12
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
13
 *
14 15 16 17 18 19 20
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
21 22
 */

Michael Niedermayer's avatar
Michael Niedermayer committed
23
/**
24
 * @file
25
 * libavcodec API use example.
Fabrice Bellard's avatar
Fabrice Bellard committed
26
 *
27
 * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...),
28
 * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the
29
 * format handling
30
 * @example doc/examples/decoding_encoding.c
Fabrice Bellard's avatar
Fabrice Bellard committed
31
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
32

33 34
#include <math.h>

35 36
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
37
#include <libavutil/channel_layout.h>
38
#include <libavutil/common.h>
39
#include <libavutil/imgutils.h>
40 41
#include <libavutil/mathematics.h>
#include <libavutil/samplefmt.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
42 43

#define INBUF_SIZE 4096
44 45
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096
Fabrice Bellard's avatar
Fabrice Bellard committed
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt)
{
    const enum AVSampleFormat *p = codec->sample_fmts;

    while (*p != AV_SAMPLE_FMT_NONE) {
        if (*p == sample_fmt)
            return 1;
        p++;
    }
    return 0;
}

/* just pick the highest supported samplerate */
static int select_sample_rate(AVCodec *codec)
{
    const int *p;
    int best_samplerate = 0;

    if (!codec->supported_samplerates)
        return 44100;

    p = codec->supported_samplerates;
    while (*p) {
        best_samplerate = FFMAX(*p, best_samplerate);
        p++;
    }
    return best_samplerate;
}

/* select layout with the highest channel count */
static int select_channel_layout(AVCodec *codec)
{
    const uint64_t *p;
    uint64_t best_ch_layout = 0;
    int best_nb_channells   = 0;

    if (!codec->channel_layouts)
        return AV_CH_LAYOUT_STEREO;

    p = codec->channel_layouts;
    while (*p) {
        int nb_channels = av_get_channel_layout_nb_channels(*p);

        if (nb_channels > best_nb_channells) {
            best_ch_layout    = *p;
            best_nb_channells = nb_channels;
        }
        p++;
    }
    return best_ch_layout;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
100
/*
101
 * Audio encoding example
Fabrice Bellard's avatar
Fabrice Bellard committed
102
 */
103
static void audio_encode_example(const char *filename)
Fabrice Bellard's avatar
Fabrice Bellard committed
104 105
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
106
    AVCodecContext *c= NULL;
107 108 109 110
    AVFrame *frame;
    AVPacket pkt;
    int i, j, k, ret, got_output;
    int buffer_size;
Fabrice Bellard's avatar
Fabrice Bellard committed
111
    FILE *f;
112
    uint16_t *samples;
Fabrice Bellard's avatar
Fabrice Bellard committed
113 114
    float t, tincr;

115
    printf("Encode audio file %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
116 117

    /* find the MP2 encoder */
118
    codec = avcodec_find_encoder(AV_CODEC_ID_MP2);
Fabrice Bellard's avatar
Fabrice Bellard committed
119
    if (!codec) {
120
        fprintf(stderr, "Codec not found\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
121 122 123
        exit(1);
    }

124
    c = avcodec_alloc_context3(codec);
125 126 127 128
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }
129

Fabrice Bellard's avatar
Fabrice Bellard committed
130 131
    /* put sample parameters */
    c->bit_rate = 64000;
132 133

    /* check that the encoder supports s16 pcm input */
134
    c->sample_fmt = AV_SAMPLE_FMT_S16;
135
    if (!check_sample_fmt(codec, c->sample_fmt)) {
136
        fprintf(stderr, "Encoder does not support sample format %s",
137 138 139 140 141 142 143 144
                av_get_sample_fmt_name(c->sample_fmt));
        exit(1);
    }

    /* select other audio parameters supported by the encoder */
    c->sample_rate    = select_sample_rate(codec);
    c->channel_layout = select_channel_layout(codec);
    c->channels       = av_get_channel_layout_nb_channels(c->channel_layout);
Fabrice Bellard's avatar
Fabrice Bellard committed
145 146

    /* open it */
147
    if (avcodec_open2(c, codec, NULL) < 0) {
148
        fprintf(stderr, "Could not open codec\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
149 150
        exit(1);
    }
151

152
    f = fopen(filename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
153
    if (!f) {
154
        fprintf(stderr, "Could not open %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
155 156
        exit(1);
    }
157

158 159 160
    /* frame containing input raw audio */
    frame = avcodec_alloc_frame();
    if (!frame) {
161
        fprintf(stderr, "Could not allocate audio frame\n");
162 163 164 165 166 167 168 169 170 171 172 173 174
        exit(1);
    }

    frame->nb_samples     = c->frame_size;
    frame->format         = c->sample_fmt;
    frame->channel_layout = c->channel_layout;

    /* the codec gives us the frame size, in samples,
     * we calculate the size of the samples buffer in bytes */
    buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size,
                                             c->sample_fmt, 0);
    samples = av_malloc(buffer_size);
    if (!samples) {
175
        fprintf(stderr, "Could not allocate %d bytes for samples buffer\n",
176 177 178 179 180 181 182
                buffer_size);
        exit(1);
    }
    /* setup the data pointers in the AVFrame */
    ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
                                   (const uint8_t*)samples, buffer_size, 0);
    if (ret < 0) {
183
        fprintf(stderr, "Could not setup audio frame\n");
184 185 186
        exit(1);
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
187 188
    /* encode a single tone sound */
    t = 0;
189
    tincr = 2 * M_PI * 440.0 / c->sample_rate;
Fabrice Bellard's avatar
Fabrice Bellard committed
190
    for(i=0;i<200;i++) {
191 192 193 194 195
        av_init_packet(&pkt);
        pkt.data = NULL; // packet data will be allocated by the encoder
        pkt.size = 0;

        for (j = 0; j < c->frame_size; j++) {
Fabrice Bellard's avatar
Fabrice Bellard committed
196
            samples[2*j] = (int)(sin(t) * 10000);
197 198 199

            for (k = 1; k < c->channels; k++)
                samples[2*j + k] = samples[2*j];
Fabrice Bellard's avatar
Fabrice Bellard committed
200 201 202
            t += tincr;
        }
        /* encode the samples */
203 204
        ret = avcodec_encode_audio2(c, &pkt, frame, &got_output);
        if (ret < 0) {
205
            fprintf(stderr, "Error encoding audio frame\n");
206 207 208 209 210 211
            exit(1);
        }
        if (got_output) {
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
212
    }
213 214 215 216 217

    /* get the delayed frames */
    for (got_output = 1; got_output; i++) {
        ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
218
            fprintf(stderr, "Error encoding frame\n");
219 220 221 222 223 224 225 226
            exit(1);
        }

        if (got_output) {
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
227 228
    fclose(f);

229
    av_freep(&samples);
230
    avcodec_free_frame(&frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
231
    avcodec_close(c);
232
    av_free(c);
Fabrice Bellard's avatar
Fabrice Bellard committed
233 234 235
}

/*
236
 * Audio decoding.
Fabrice Bellard's avatar
Fabrice Bellard committed
237
 */
238
static void audio_decode_example(const char *outfilename, const char *filename)
Fabrice Bellard's avatar
Fabrice Bellard committed
239 240
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
241
    AVCodecContext *c= NULL;
242
    int len;
Fabrice Bellard's avatar
Fabrice Bellard committed
243
    FILE *f, *outfile;
244
    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
245
    AVPacket avpkt;
246
    AVFrame *decoded_frame = NULL;
247 248

    av_init_packet(&avpkt);
Fabrice Bellard's avatar
Fabrice Bellard committed
249

250
    printf("Decode audio file %s to %s\n", filename, outfilename);
251

Fabrice Bellard's avatar
Fabrice Bellard committed
252
    /* find the mpeg audio decoder */
253
    codec = avcodec_find_decoder(AV_CODEC_ID_MP2);
Fabrice Bellard's avatar
Fabrice Bellard committed
254
    if (!codec) {
255
        fprintf(stderr, "Codec not found\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
256 257 258
        exit(1);
    }

259
    c = avcodec_alloc_context3(codec);
260 261 262 263
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
264 265

    /* open it */
266
    if (avcodec_open2(c, codec, NULL) < 0) {
267
        fprintf(stderr, "Could not open codec\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
268 269
        exit(1);
    }
270

271
    f = fopen(filename, "rb");
Fabrice Bellard's avatar
Fabrice Bellard committed
272
    if (!f) {
273
        fprintf(stderr, "Could not open %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
274 275
        exit(1);
    }
276
    outfile = fopen(outfilename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
277
    if (!outfile) {
278
        av_free(c);
Fabrice Bellard's avatar
Fabrice Bellard committed
279 280
        exit(1);
    }
281

Fabrice Bellard's avatar
Fabrice Bellard committed
282
    /* decode until eof */
283
    avpkt.data = inbuf;
284 285 286
    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);

    while (avpkt.size > 0) {
287 288 289 290
        int got_frame = 0;

        if (!decoded_frame) {
            if (!(decoded_frame = avcodec_alloc_frame())) {
291
                fprintf(stderr, "Could not allocate audio frame\n");
292 293 294 295 296 297
                exit(1);
            }
        } else
            avcodec_get_frame_defaults(decoded_frame);

        len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);
298 299 300
        if (len < 0) {
            fprintf(stderr, "Error while decoding\n");
            exit(1);
Fabrice Bellard's avatar
Fabrice Bellard committed
301
        }
302
        if (got_frame) {
303
            /* if a frame has been decoded, output it */
304 305 306 307
            int data_size = av_samples_get_buffer_size(NULL, c->channels,
                                                       decoded_frame->nb_samples,
                                                       c->sample_fmt, 1);
            fwrite(decoded_frame->data[0], 1, data_size, outfile);
308 309 310
        }
        avpkt.size -= len;
        avpkt.data += len;
311 312
        avpkt.dts =
        avpkt.pts = AV_NOPTS_VALUE;
313 314 315 316 317 318 319 320 321 322 323 324 325
        if (avpkt.size < AUDIO_REFILL_THRESH) {
            /* Refill the input buffer, to avoid trying to decode
             * incomplete frames. Instead of this, one could also use
             * a parser, or use a proper container format through
             * libavformat. */
            memmove(inbuf, avpkt.data, avpkt.size);
            avpkt.data = inbuf;
            len = fread(avpkt.data + avpkt.size, 1,
                        AUDIO_INBUF_SIZE - avpkt.size, f);
            if (len > 0)
                avpkt.size += len;
        }
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
326 327 328 329 330

    fclose(outfile);
    fclose(f);

    avcodec_close(c);
331
    av_free(c);
332
    avcodec_free_frame(&decoded_frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
333 334 335
}

/*
336
 * Video encoding example
Fabrice Bellard's avatar
Fabrice Bellard committed
337
 */
338
static void video_encode_example(const char *filename, int codec_id)
Fabrice Bellard's avatar
Fabrice Bellard committed
339 340
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
341
    AVCodecContext *c= NULL;
342
    int i, ret, x, y, got_output;
Fabrice Bellard's avatar
Fabrice Bellard committed
343
    FILE *f;
344
    AVFrame *frame;
345 346
    AVPacket pkt;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };
Fabrice Bellard's avatar
Fabrice Bellard committed
347

348
    printf("Encode video file %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
349 350

    /* find the mpeg1 video encoder */
351
    codec = avcodec_find_encoder(codec_id);
Fabrice Bellard's avatar
Fabrice Bellard committed
352
    if (!codec) {
353
        fprintf(stderr, "Codec not found\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
354 355 356
        exit(1);
    }

357
    c = avcodec_alloc_context3(codec);
358 359 360 361
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }
362

Fabrice Bellard's avatar
Fabrice Bellard committed
363 364 365
    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
366
    c->width = 352;
Fabrice Bellard's avatar
Fabrice Bellard committed
367 368
    c->height = 288;
    /* frames per second */
369
    c->time_base= (AVRational){1,25};
Fabrice Bellard's avatar
Fabrice Bellard committed
370
    c->gop_size = 10; /* emit one intra frame every ten frames */
371
    c->max_b_frames=1;
372
    c->pix_fmt = AV_PIX_FMT_YUV420P;
Fabrice Bellard's avatar
Fabrice Bellard committed
373

374
    if(codec_id == AV_CODEC_ID_H264)
375
        av_opt_set(c->priv_data, "preset", "slow", 0);
376

Fabrice Bellard's avatar
Fabrice Bellard committed
377
    /* open it */
378
    if (avcodec_open2(c, codec, NULL) < 0) {
379
        fprintf(stderr, "Could not open codec\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
380 381
        exit(1);
    }
382

383
    f = fopen(filename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
384
    if (!f) {
385
        fprintf(stderr, "Could not open %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
386 387
        exit(1);
    }
388

389 390
    frame = avcodec_alloc_frame();
    if (!frame) {
391 392 393
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
394 395 396
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;
397

398 399
    /* the image can be allocated by any means and av_image_alloc() is
     * just the most convenient way if av_malloc() is to be used */
400
    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,
401 402
                         c->pix_fmt, 32);
    if (ret < 0) {
403
        fprintf(stderr, "Could not allocate raw picture buffer\n");
404 405
        exit(1);
    }
406

Fabrice Bellard's avatar
Fabrice Bellard committed
407 408
    /* encode 1 second of video */
    for(i=0;i<25;i++) {
409 410 411 412
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;

Fabrice Bellard's avatar
Fabrice Bellard committed
413 414 415 416 417
        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
418
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
Fabrice Bellard's avatar
Fabrice Bellard committed
419 420 421 422 423 424
            }
        }

        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
425 426
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
Fabrice Bellard's avatar
Fabrice Bellard committed
427 428 429
            }
        }

430
        frame->pts = i;
431

Fabrice Bellard's avatar
Fabrice Bellard committed
432
        /* encode the image */
433
        ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
434
        if (ret < 0) {
435
            fprintf(stderr, "Error encoding frame\n");
436 437 438 439
            exit(1);
        }

        if (got_output) {
440
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
441 442 443
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
444 445 446
    }

    /* get the delayed frames */
447
    for (got_output = 1; got_output; i++) {
448
        fflush(stdout);
449

450 451
        ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);
        if (ret < 0) {
452
            fprintf(stderr, "Error encoding frame\n");
453 454 455 456
            exit(1);
        }

        if (got_output) {
457
            printf("Write frame %3d (size=%5d)\n", i, pkt.size);
458 459 460
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
461 462 463
    }

    /* add sequence end code to have a real mpeg file */
464
    fwrite(endcode, 1, sizeof(endcode), f);
Fabrice Bellard's avatar
Fabrice Bellard committed
465 466 467
    fclose(f);

    avcodec_close(c);
468
    av_free(c);
469
    av_freep(&frame->data[0]);
470
    avcodec_free_frame(&frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
471 472 473 474
    printf("\n");
}

/*
475
 * Video decoding example
Fabrice Bellard's avatar
Fabrice Bellard committed
476 477
 */

478 479
static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
                     char *filename)
Fabrice Bellard's avatar
Fabrice Bellard committed
480 481 482 483 484 485 486 487 488 489 490
{
    FILE *f;
    int i;

    f=fopen(filename,"w");
    fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
    for(i=0;i<ysize;i++)
        fwrite(buf + i * wrap,1,xsize,f);
    fclose(f);
}

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
static int decode_write_frame(const char *outfilename, AVCodecContext *avctx,
                              AVFrame *frame, int *frame_count, AVPacket *pkt, int last)
{
    int len, got_frame;
    char buf[1024];

    len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);
    if (len < 0) {
        fprintf(stderr, "Error while decoding frame %d\n", *frame_count);
        return len;
    }
    if (got_frame) {
        printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count);
        fflush(stdout);

        /* the picture is allocated by the decoder, no need to free it */
        snprintf(buf, sizeof(buf), outfilename, *frame_count);
        pgm_save(frame->data[0], frame->linesize[0],
                 avctx->width, avctx->height, buf);
        (*frame_count)++;
    }
    if (pkt->data) {
        pkt->size -= len;
        pkt->data += len;
    }
    return 0;
}

519
static void video_decode_example(const char *outfilename, const char *filename)
Fabrice Bellard's avatar
Fabrice Bellard committed
520 521
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
522
    AVCodecContext *c= NULL;
523
    int frame_count;
Fabrice Bellard's avatar
Fabrice Bellard committed
524
    FILE *f;
525
    AVFrame *frame;
526 527 528 529
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
    AVPacket avpkt;

    av_init_packet(&avpkt);
Fabrice Bellard's avatar
Fabrice Bellard committed
530

531 532 533
    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

534
    printf("Decode video file %s to %s\n", filename, outfilename);
Fabrice Bellard's avatar
Fabrice Bellard committed
535 536

    /* find the mpeg1 video decoder */
537
    codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
Fabrice Bellard's avatar
Fabrice Bellard committed
538
    if (!codec) {
539
        fprintf(stderr, "Codec not found\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
540 541 542
        exit(1);
    }

543
    c = avcodec_alloc_context3(codec);
544 545 546 547 548
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

549
    if(codec->capabilities&CODEC_CAP_TRUNCATED)
Diego Biurrun's avatar
Diego Biurrun committed
550
        c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */
551

Diego Biurrun's avatar
Diego Biurrun committed
552 553 554
    /* For some codecs, such as msmpeg4 and mpeg4, width and height
       MUST be initialized there because this information is not
       available in the bitstream. */
Fabrice Bellard's avatar
Fabrice Bellard committed
555 556

    /* open it */
557
    if (avcodec_open2(c, codec, NULL) < 0) {
558
        fprintf(stderr, "Could not open codec\n");
Fabrice Bellard's avatar
Fabrice Bellard committed
559 560
        exit(1);
    }
561

562
    f = fopen(filename, "rb");
Fabrice Bellard's avatar
Fabrice Bellard committed
563
    if (!f) {
564
        fprintf(stderr, "Could not open %s\n", filename);
Fabrice Bellard's avatar
Fabrice Bellard committed
565
        exit(1);
566 567
    }

568 569
    frame = avcodec_alloc_frame();
    if (!frame) {
570 571
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
Fabrice Bellard's avatar
Fabrice Bellard committed
572
    }
573

574
    frame_count = 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
575
    for(;;) {
576 577
        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
        if (avpkt.size == 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
578 579 580 581
            break;

        /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
           and this is the only method to use them because you cannot
582
           know the compressed data size before analysing it.
Fabrice Bellard's avatar
Fabrice Bellard committed
583

584 585 586
           BUT some other codecs (msmpeg4, mpeg4) are inherently frame
           based, so you must call them with all the data for one
           frame exactly. You must also initialize 'width' and
Fabrice Bellard's avatar
Fabrice Bellard committed
587 588 589 590 591 592 593 594
           'height' before initializing them. */

        /* NOTE2: some codecs allow the raw parameters (frame size,
           sample rate) to be changed at any frame. We handle this, so
           you should also take care of it */

        /* here, we use a stream based decoder (mpeg1video), so we
           feed decoder and see if it could decode a frame */
595
        avpkt.data = inbuf;
596 597
        while (avpkt.size > 0)
            if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0)
Fabrice Bellard's avatar
Fabrice Bellard committed
598 599 600 601 602 603
                exit(1);
    }

    /* some codecs, such as MPEG, transmit the I and P frame with a
       latency of one frame. You must do the following to have a
       chance to get the last frame of the video */
604 605
    avpkt.data = NULL;
    avpkt.size = 0;
606
    decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1);
607

Fabrice Bellard's avatar
Fabrice Bellard committed
608 609 610
    fclose(f);

    avcodec_close(c);
611
    av_free(c);
612
    avcodec_free_frame(&frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
613 614 615 616 617
    printf("\n");
}

int main(int argc, char **argv)
{
618
    const char *output_type;
Fabrice Bellard's avatar
Fabrice Bellard committed
619

620
    /* register all the codecs */
Fabrice Bellard's avatar
Fabrice Bellard committed
621
    avcodec_register_all();
622

623 624 625
    if (argc < 2) {
        printf("usage: %s output_type\n"
               "API example program to decode/encode a media stream with libavcodec.\n"
626 627
               "This program generates a synthetic stream and encodes it to a file\n"
               "named test.h264, test.mp2 or test.mpg depending on output_type.\n"
628 629
               "The encoded stream is then decoded and written to a raw data output.\n"
               "output_type must be choosen between 'h264', 'mp2', 'mpg'.\n",
630 631 632 633
               argv[0]);
        return 1;
    }
    output_type = argv[1];
Fabrice Bellard's avatar
Fabrice Bellard committed
634

635
    if (!strcmp(output_type, "h264")) {
636
        video_encode_example("test.h264", AV_CODEC_ID_H264);
637 638 639 640
    } else if (!strcmp(output_type, "mp2")) {
        audio_encode_example("test.mp2");
        audio_decode_example("test.sw", "test.mp2");
    } else if (!strcmp(output_type, "mpg")) {
641
        video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO);
642
        video_decode_example("test%02d.pgm", "test.mpg");
Fabrice Bellard's avatar
Fabrice Bellard committed
643
    } else {
644 645 646
        fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n",
                output_type);
        return 1;
Fabrice Bellard's avatar
Fabrice Bellard committed
647 648 649 650
    }

    return 0;
}