apiexample.c 13.3 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1 2 3
/**
 * @file apiexample.c
 * avcodec API use example.
Fabrice Bellard's avatar
Fabrice Bellard committed
4 5
 *
 * Note that this library only handles codecs (mpeg, mpeg4, etc...),
Fabrice Bellard's avatar
Fabrice Bellard committed
6
 * not file formats (avi, vob, etc...). See library 'libavformat' for the
Fabrice Bellard's avatar
Fabrice Bellard committed
7 8
 * format handling 
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
9

Fabrice Bellard's avatar
Fabrice Bellard committed
10 11 12 13 14
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

15 16 17 18
#ifdef HAVE_AV_CONFIG_H
#undef HAVE_AV_CONFIG_H
#endif

Fabrice Bellard's avatar
Fabrice Bellard committed
19 20 21 22 23 24 25 26 27 28
#include "avcodec.h"

#define INBUF_SIZE 4096

/*
 * Audio encoding example 
 */
void audio_encode_example(const char *filename)
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
29
    AVCodecContext *c= NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
30 31 32 33
    int frame_size, i, j, out_size, outbuf_size;
    FILE *f;
    short *samples;
    float t, tincr;
34
    uint8_t *outbuf;
Fabrice Bellard's avatar
Fabrice Bellard committed
35 36 37 38 39 40 41 42 43 44

    printf("Audio encoding\n");

    /* find the MP2 encoder */
    codec = avcodec_find_encoder(CODEC_ID_MP2);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
45 46
    c= avcodec_alloc_context();
    
Fabrice Bellard's avatar
Fabrice Bellard committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    /* put sample parameters */
    c->bit_rate = 64000;
    c->sample_rate = 44100;
    c->channels = 2;

    /* open it */
    if (avcodec_open(c, codec) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }
    
    /* the codec gives us the frame size, in samples */
    frame_size = c->frame_size;
    samples = malloc(frame_size * 2 * c->channels);
    outbuf_size = 10000;
    outbuf = malloc(outbuf_size);

64
    f = fopen(filename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
        
    /* encode a single tone sound */
    t = 0;
    tincr = 2 * M_PI * 440.0 / c->sample_rate;
    for(i=0;i<200;i++) {
        for(j=0;j<frame_size;j++) {
            samples[2*j] = (int)(sin(t) * 10000);
            samples[2*j+1] = samples[2*j];
            t += tincr;
        }
        /* encode the samples */
        out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
        fwrite(outbuf, 1, out_size, f);
    }
    fclose(f);
    free(outbuf);
    free(samples);

    avcodec_close(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
88
    free(c);
Fabrice Bellard's avatar
Fabrice Bellard committed
89 90 91 92 93 94 95 96
}

/*
 * Audio decoding. 
 */
void audio_decode_example(const char *outfilename, const char *filename)
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
97
    AVCodecContext *c= NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
98 99
    int out_size, size, len;
    FILE *f, *outfile;
100
    uint8_t *outbuf;
101
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
Fabrice Bellard's avatar
Fabrice Bellard committed
102 103

    printf("Audio decoding\n");
104 105 106
    
    /* 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);
Fabrice Bellard's avatar
Fabrice Bellard committed
107 108 109 110 111 112 113 114

    /* find the mpeg audio decoder */
    codec = avcodec_find_decoder(CODEC_ID_MP2);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
115
    c= avcodec_alloc_context();
Fabrice Bellard's avatar
Fabrice Bellard committed
116 117 118 119 120 121 122 123 124

    /* open it */
    if (avcodec_open(c, codec) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }
    
    outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);

125
    f = fopen(filename, "rb");
Fabrice Bellard's avatar
Fabrice Bellard committed
126 127 128 129
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
130
    outfile = fopen(outfilename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
131
    if (!outfile) {
Michael Niedermayer's avatar
Michael Niedermayer committed
132
        free(c);
Fabrice Bellard's avatar
Fabrice Bellard committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
        exit(1);
    }
        
    /* decode until eof */
    inbuf_ptr = inbuf;
    for(;;) {
        size = fread(inbuf, 1, INBUF_SIZE, f);
        if (size == 0)
            break;

        inbuf_ptr = inbuf;
        while (size > 0) {
            len = avcodec_decode_audio(c, (short *)outbuf, &out_size, 
                                       inbuf_ptr, size);
            if (len < 0) {
                fprintf(stderr, "Error while decoding\n");
                exit(1);
            }
            if (out_size > 0) {
                /* if a frame has been decoded, output it */
                fwrite(outbuf, 1, out_size, outfile);
            }
            size -= len;
            inbuf_ptr += len;
        }
    }

    fclose(outfile);
    fclose(f);
    free(outbuf);

    avcodec_close(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
165
    free(c);
Fabrice Bellard's avatar
Fabrice Bellard committed
166 167 168 169 170 171 172 173
}

/*
 * Video encoding example 
 */
void video_encode_example(const char *filename)
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
174
    AVCodecContext *c= NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
175 176
    int i, out_size, size, x, y, outbuf_size;
    FILE *f;
177
    AVFrame *picture;
178
    uint8_t *outbuf, *picture_buf;
Fabrice Bellard's avatar
Fabrice Bellard committed
179 180 181 182 183 184 185 186 187 188

    printf("Video encoding\n");

    /* find the mpeg1 video encoder */
    codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
189
    c= avcodec_alloc_context();
190
    picture= avcodec_alloc_frame();
Michael Niedermayer's avatar
Michael Niedermayer committed
191
    
Fabrice Bellard's avatar
Fabrice Bellard committed
192 193 194 195 196 197
    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;  
    c->height = 288;
    /* frames per second */
198 199
    c->frame_rate = 25;  
    c->frame_rate_base= 1;
Fabrice Bellard's avatar
Fabrice Bellard committed
200
    c->gop_size = 10; /* emit one intra frame every ten frames */
201
    c->max_b_frames=1;
Fabrice Bellard's avatar
Fabrice Bellard committed
202 203 204 205 206 207 208 209 210

    /* open it */
    if (avcodec_open(c, codec) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }
    
    /* the codec gives us the frame size, in samples */

211
    f = fopen(filename, "wb");
Fabrice Bellard's avatar
Fabrice Bellard committed
212 213 214 215 216 217 218 219 220 221 222
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    
    /* alloc image and output buffer */
    outbuf_size = 100000;
    outbuf = malloc(outbuf_size);
    size = c->width * c->height;
    picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
    
Michael Niedermayer's avatar
Michael Niedermayer committed
223 224 225 226 227 228
    picture->data[0] = picture_buf;
    picture->data[1] = picture->data[0] + size;
    picture->data[2] = picture->data[1] + size / 4;
    picture->linesize[0] = c->width;
    picture->linesize[1] = c->width / 2;
    picture->linesize[2] = c->width / 2;
Fabrice Bellard's avatar
Fabrice Bellard committed
229 230 231 232 233 234 235 236

    /* encode 1 second of video */
    for(i=0;i<25;i++) {
        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
Michael Niedermayer's avatar
Michael Niedermayer committed
237
                picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
Fabrice Bellard's avatar
Fabrice Bellard committed
238 239 240 241 242 243
            }
        }

        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
Michael Niedermayer's avatar
Michael Niedermayer committed
244 245
                picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
                picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
Fabrice Bellard's avatar
Fabrice Bellard committed
246 247 248 249
            }
        }

        /* encode the image */
Michael Niedermayer's avatar
Michael Niedermayer committed
250
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
251 252 253 254 255 256 257 258 259 260
        printf("encoding frame %3d (size=%5d)\n", i, out_size);
        fwrite(outbuf, 1, out_size, f);
    }

    /* get the delayed frames */
    for(; out_size; i++) {
        fflush(stdout);
        
        out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
        printf("write frame %3d (size=%5d)\n", i, out_size);
Fabrice Bellard's avatar
Fabrice Bellard committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274
        fwrite(outbuf, 1, out_size, f);
    }

    /* add sequence end code to have a real mpeg file */
    outbuf[0] = 0x00;
    outbuf[1] = 0x00;
    outbuf[2] = 0x01;
    outbuf[3] = 0xb7;
    fwrite(outbuf, 1, 4, f);
    fclose(f);
    free(picture_buf);
    free(outbuf);

    avcodec_close(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
275
    free(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
276
    free(picture);
Fabrice Bellard's avatar
Fabrice Bellard committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    printf("\n");
}

/*
 * Video decoding example 
 */

void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename) 
{
    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);
}

void video_decode_example(const char *outfilename, const char *filename)
{
    AVCodec *codec;
Michael Niedermayer's avatar
Michael Niedermayer committed
299
    AVCodecContext *c= NULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
300 301
    int frame, size, got_picture, len;
    FILE *f;
302
    AVFrame *picture;
303
    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE], *inbuf_ptr;
Fabrice Bellard's avatar
Fabrice Bellard committed
304 305
    char buf[1024];

306 307 308
    /* 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);

Fabrice Bellard's avatar
Fabrice Bellard committed
309 310 311 312 313 314 315 316 317
    printf("Video decoding\n");

    /* find the mpeg1 video decoder */
    codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
    if (!codec) {
        fprintf(stderr, "codec not found\n");
        exit(1);
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
318
    c= avcodec_alloc_context();
319
    picture= avcodec_alloc_frame();
Fabrice Bellard's avatar
Fabrice Bellard committed
320

321 322 323
    if(codec->capabilities&CODEC_CAP_TRUNCATED)
        c->flags|= CODEC_FLAG_TRUNCATED; /* we dont send complete frames */

324
    /* for some codecs, such as msmpeg4 and mpeg4, width and height
Fabrice Bellard's avatar
Fabrice Bellard committed
325 326 327 328 329 330 331 332 333 334 335
       MUST be initialized there because these info are not available
       in the bitstream */

    /* open it */
    if (avcodec_open(c, codec) < 0) {
        fprintf(stderr, "could not open codec\n");
        exit(1);
    }
    
    /* the codec gives us the frame size, in samples */

336
    f = fopen(filename, "rb");
Fabrice Bellard's avatar
Fabrice Bellard committed
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
    if (!f) {
        fprintf(stderr, "could not open %s\n", filename);
        exit(1);
    }
    
    frame = 0;
    for(;;) {
        size = fread(inbuf, 1, INBUF_SIZE, f);
        if (size == 0)
            break;

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

352 353 354
           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
355 356 357 358 359 360 361 362 363 364
           '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 */
        inbuf_ptr = inbuf;
        while (size > 0) {
Michael Niedermayer's avatar
Michael Niedermayer committed
365
            len = avcodec_decode_video(c, picture, &got_picture, 
Fabrice Bellard's avatar
Fabrice Bellard committed
366 367 368 369 370 371
                                       inbuf_ptr, size);
            if (len < 0) {
                fprintf(stderr, "Error while decoding frame %d\n", frame);
                exit(1);
            }
            if (got_picture) {
372
                printf("saving frame %3d\n", frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
373 374 375 376 377
                fflush(stdout);

                /* the picture is allocated by the decoder. no need to
                   free it */
                snprintf(buf, sizeof(buf), outfilename, frame);
Michael Niedermayer's avatar
Michael Niedermayer committed
378
                pgm_save(picture->data[0], picture->linesize[0], 
Fabrice Bellard's avatar
Fabrice Bellard committed
379 380 381 382 383 384 385 386 387 388 389
                         c->width, c->height, buf);
                frame++;
            }
            size -= len;
            inbuf_ptr += len;
        }
    }

    /* 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 */
Michael Niedermayer's avatar
Michael Niedermayer committed
390
    len = avcodec_decode_video(c, picture, &got_picture, 
Fabrice Bellard's avatar
Fabrice Bellard committed
391 392
                               NULL, 0);
    if (got_picture) {
393
        printf("saving last frame %3d\n", frame);
Fabrice Bellard's avatar
Fabrice Bellard committed
394 395 396 397 398
        fflush(stdout);
        
        /* the picture is allocated by the decoder. no need to
           free it */
        snprintf(buf, sizeof(buf), outfilename, frame);
Michael Niedermayer's avatar
Michael Niedermayer committed
399
        pgm_save(picture->data[0], picture->linesize[0], 
Fabrice Bellard's avatar
Fabrice Bellard committed
400 401 402 403 404 405 406
                 c->width, c->height, buf);
        frame++;
    }
        
    fclose(f);

    avcodec_close(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
407
    free(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
408
    free(picture);
Fabrice Bellard's avatar
Fabrice Bellard committed
409 410 411
    printf("\n");
}

412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
// simple example how the options could be used
int options_example(int argc, char* argv[])
{
    AVCodec* codec = avcodec_find_encoder_by_name((argc > 1) ? argv[2] : "mpeg4");
    const AVOption* c;
    AVCodecContext* avctx;
    char* def = av_malloc(5000);
    const char* col = "";
    int i = 0;

    if (!codec)
	return -1;
    c = codec->options;
    avctx = avcodec_alloc_context();
    *def = 0;

    if (c) {
	const AVOption *stack[FF_OPT_MAX_DEPTH];
	int depth = 0;
	for (;;) {
	    if (!c->name) {
433
		if (c->help) {
434
		    stack[depth++] = c;
435
		    c = (const AVOption*)c->help;
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
		} else {
		    if (depth == 0)
			break; // finished
		    c = stack[--depth];
                    c++;
		}
	    } else {
		int t = c->type & FF_OPT_TYPE_MASK;
		printf("Config   %s  %s\n",
		       t == FF_OPT_TYPE_BOOL ? "bool   " :
		       t == FF_OPT_TYPE_DOUBLE ? "double  " :
		       t == FF_OPT_TYPE_INT ? "integer" :
		       t == FF_OPT_TYPE_STRING ? "string " :
		       "unknown??", c->name);
		switch (t) {
		case FF_OPT_TYPE_BOOL:
		    i += sprintf(def + i, "%s%s=%s",
				 col, c->name,
				 c->defval != 0. ? "on" : "off");
		    break;
		case FF_OPT_TYPE_DOUBLE:
		    i += sprintf(def + i, "%s%s=%f",
				 col, c->name, c->defval);
		    break;
		case FF_OPT_TYPE_INT:
		    i += sprintf(def + i, "%s%s=%d",
				 col, c->name, (int) c->defval);
		    break;
		case FF_OPT_TYPE_STRING:
		    if (c->defstr) {
			char* d = av_strdup(c->defstr);
			char* f = strchr(d, ',');
			if (f)
                            *f = 0;
			i += sprintf(def + i, "%s%s=%s",
				     col, c->name, d);
                        av_free(d);
		    }
		    break;
		}
		col = ":";
		c++;
	    }
	}
    }
    printf("Default Options: %s\n", def);
    av_free(def);
    return 0;
}

Fabrice Bellard's avatar
Fabrice Bellard committed
486 487 488 489 490 491 492 493 494 495 496

int main(int argc, char **argv)
{
    const char *filename;

    /* must be called before using avcodec lib */
    avcodec_init();

    /* register all the codecs (you can also register only the codec
       you wish to have smaller code */
    avcodec_register_all();
497 498 499 500

#ifdef OPT_TEST
    options_example(argc, argv);
#else
Fabrice Bellard's avatar
Fabrice Bellard committed
501 502 503 504 505 506 507 508 509 510 511 512
    if (argc <= 1) {
        audio_encode_example("/tmp/test.mp2");
        audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");

        video_encode_example("/tmp/test.mpg");
        filename = "/tmp/test.mpg";
    } else {
        filename = argv[1];
    }

    //    audio_decode_example("/tmp/test.sw", filename);
    video_decode_example("/tmp/test%d.pgm", filename);
513
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
514 515 516

    return 0;
}