1/*
2 * copyright (c) 2001 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * avcodec API use example.
24 *
25 * Note that this library only handles codecs (mpeg, mpeg4, etc...),
26 * not file formats (avi, vob, etc...). See library 'libavformat' for the
27 * format handling
28 */
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33
34#ifdef HAVE_AV_CONFIG_H
35#undef HAVE_AV_CONFIG_H
36#endif
37
38#include "libavcodec/avcodec.h"
39#include "libavutil/mathematics.h"
40
41#define INBUF_SIZE 4096
42#define AUDIO_INBUF_SIZE 20480
43#define AUDIO_REFILL_THRESH 4096
44
45/*
46 * Audio encoding example
47 */
48static void audio_encode_example(const char *filename)
49{
50    AVCodec *codec;
51    AVCodecContext *c= NULL;
52    int frame_size, i, j, out_size, outbuf_size;
53    FILE *f;
54    short *samples;
55    float t, tincr;
56    uint8_t *outbuf;
57
58    printf("Audio encoding\n");
59
60    /* find the MP2 encoder */
61    codec = avcodec_find_encoder(CODEC_ID_MP2);
62    if (!codec) {
63        fprintf(stderr, "codec not found\n");
64        exit(1);
65    }
66
67    c= avcodec_alloc_context();
68
69    /* put sample parameters */
70    c->bit_rate = 64000;
71    c->sample_rate = 44100;
72    c->channels = 2;
73
74    /* open it */
75    if (avcodec_open(c, codec) < 0) {
76        fprintf(stderr, "could not open codec\n");
77        exit(1);
78    }
79
80    /* the codec gives us the frame size, in samples */
81    frame_size = c->frame_size;
82    samples = malloc(frame_size * 2 * c->channels);
83    outbuf_size = 10000;
84    outbuf = malloc(outbuf_size);
85
86    f = fopen(filename, "wb");
87    if (!f) {
88        fprintf(stderr, "could not open %s\n", filename);
89        exit(1);
90    }
91
92    /* encode a single tone sound */
93    t = 0;
94    tincr = 2 * M_PI * 440.0 / c->sample_rate;
95    for(i=0;i<200;i++) {
96        for(j=0;j<frame_size;j++) {
97            samples[2*j] = (int)(sin(t) * 10000);
98            samples[2*j+1] = samples[2*j];
99            t += tincr;
100        }
101        /* encode the samples */
102        out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
103        fwrite(outbuf, 1, out_size, f);
104    }
105    fclose(f);
106    free(outbuf);
107    free(samples);
108
109    avcodec_close(c);
110    av_free(c);
111}
112
113/*
114 * Audio decoding.
115 */
116static void audio_decode_example(const char *outfilename, const char *filename)
117{
118    AVCodec *codec;
119    AVCodecContext *c= NULL;
120    int out_size, len;
121    FILE *f, *outfile;
122    uint8_t *outbuf;
123    uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
124    AVPacket avpkt;
125
126    av_init_packet(&avpkt);
127
128    printf("Audio decoding\n");
129
130    /* find the mpeg audio decoder */
131    codec = avcodec_find_decoder(CODEC_ID_MP2);
132    if (!codec) {
133        fprintf(stderr, "codec not found\n");
134        exit(1);
135    }
136
137    c= avcodec_alloc_context();
138
139    /* open it */
140    if (avcodec_open(c, codec) < 0) {
141        fprintf(stderr, "could not open codec\n");
142        exit(1);
143    }
144
145    outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
146
147    f = fopen(filename, "rb");
148    if (!f) {
149        fprintf(stderr, "could not open %s\n", filename);
150        exit(1);
151    }
152    outfile = fopen(outfilename, "wb");
153    if (!outfile) {
154        av_free(c);
155        exit(1);
156    }
157
158    /* decode until eof */
159    avpkt.data = inbuf;
160    avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);
161
162    while (avpkt.size > 0) {
163        out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
164        len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt);
165        if (len < 0) {
166            fprintf(stderr, "Error while decoding\n");
167            exit(1);
168        }
169        if (out_size > 0) {
170            /* if a frame has been decoded, output it */
171            fwrite(outbuf, 1, out_size, outfile);
172        }
173        avpkt.size -= len;
174        avpkt.data += len;
175        if (avpkt.size < AUDIO_REFILL_THRESH) {
176            /* Refill the input buffer, to avoid trying to decode
177             * incomplete frames. Instead of this, one could also use
178             * a parser, or use a proper container format through
179             * libavformat. */
180            memmove(inbuf, avpkt.data, avpkt.size);
181            avpkt.data = inbuf;
182            len = fread(avpkt.data + avpkt.size, 1,
183                        AUDIO_INBUF_SIZE - avpkt.size, f);
184            if (len > 0)
185                avpkt.size += len;
186        }
187    }
188
189    fclose(outfile);
190    fclose(f);
191    free(outbuf);
192
193    avcodec_close(c);
194    av_free(c);
195}
196
197/*
198 * Video encoding example
199 */
200static void video_encode_example(const char *filename)
201{
202    AVCodec *codec;
203    AVCodecContext *c= NULL;
204    int i, out_size, size, x, y, outbuf_size;
205    FILE *f;
206    AVFrame *picture;
207    uint8_t *outbuf, *picture_buf;
208
209    printf("Video encoding\n");
210
211    /* find the mpeg1 video encoder */
212    codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
213    if (!codec) {
214        fprintf(stderr, "codec not found\n");
215        exit(1);
216    }
217
218    c= avcodec_alloc_context();
219    picture= avcodec_alloc_frame();
220
221    /* put sample parameters */
222    c->bit_rate = 400000;
223    /* resolution must be a multiple of two */
224    c->width = 352;
225    c->height = 288;
226    /* frames per second */
227    c->time_base= (AVRational){1,25};
228    c->gop_size = 10; /* emit one intra frame every ten frames */
229    c->max_b_frames=1;
230    c->pix_fmt = PIX_FMT_YUV420P;
231
232    /* open it */
233    if (avcodec_open(c, codec) < 0) {
234        fprintf(stderr, "could not open codec\n");
235        exit(1);
236    }
237
238    f = fopen(filename, "wb");
239    if (!f) {
240        fprintf(stderr, "could not open %s\n", filename);
241        exit(1);
242    }
243
244    /* alloc image and output buffer */
245    outbuf_size = 100000;
246    outbuf = malloc(outbuf_size);
247    size = c->width * c->height;
248    picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
249
250    picture->data[0] = picture_buf;
251    picture->data[1] = picture->data[0] + size;
252    picture->data[2] = picture->data[1] + size / 4;
253    picture->linesize[0] = c->width;
254    picture->linesize[1] = c->width / 2;
255    picture->linesize[2] = c->width / 2;
256
257    /* encode 1 second of video */
258    for(i=0;i<25;i++) {
259        fflush(stdout);
260        /* prepare a dummy image */
261        /* Y */
262        for(y=0;y<c->height;y++) {
263            for(x=0;x<c->width;x++) {
264                picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3;
265            }
266        }
267
268        /* Cb and Cr */
269        for(y=0;y<c->height/2;y++) {
270            for(x=0;x<c->width/2;x++) {
271                picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2;
272                picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5;
273            }
274        }
275
276        /* encode the image */
277        out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
278        printf("encoding frame %3d (size=%5d)\n", i, out_size);
279        fwrite(outbuf, 1, out_size, f);
280    }
281
282    /* get the delayed frames */
283    for(; out_size; i++) {
284        fflush(stdout);
285
286        out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
287        printf("write frame %3d (size=%5d)\n", i, out_size);
288        fwrite(outbuf, 1, out_size, f);
289    }
290
291    /* add sequence end code to have a real mpeg file */
292    outbuf[0] = 0x00;
293    outbuf[1] = 0x00;
294    outbuf[2] = 0x01;
295    outbuf[3] = 0xb7;
296    fwrite(outbuf, 1, 4, f);
297    fclose(f);
298    free(picture_buf);
299    free(outbuf);
300
301    avcodec_close(c);
302    av_free(c);
303    av_free(picture);
304    printf("\n");
305}
306
307/*
308 * Video decoding example
309 */
310
311static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
312                     char *filename)
313{
314    FILE *f;
315    int i;
316
317    f=fopen(filename,"w");
318    fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
319    for(i=0;i<ysize;i++)
320        fwrite(buf + i * wrap,1,xsize,f);
321    fclose(f);
322}
323
324static void video_decode_example(const char *outfilename, const char *filename)
325{
326    AVCodec *codec;
327    AVCodecContext *c= NULL;
328    int frame, got_picture, len;
329    FILE *f;
330    AVFrame *picture;
331    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
332    char buf[1024];
333    AVPacket avpkt;
334
335    av_init_packet(&avpkt);
336
337    /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */
338    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
339
340    printf("Video decoding\n");
341
342    /* find the mpeg1 video decoder */
343    codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
344    if (!codec) {
345        fprintf(stderr, "codec not found\n");
346        exit(1);
347    }
348
349    c= avcodec_alloc_context();
350    picture= avcodec_alloc_frame();
351
352    if(codec->capabilities&CODEC_CAP_TRUNCATED)
353        c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */
354
355    /* For some codecs, such as msmpeg4 and mpeg4, width and height
356       MUST be initialized there because this information is not
357       available in the bitstream. */
358
359    /* open it */
360    if (avcodec_open(c, codec) < 0) {
361        fprintf(stderr, "could not open codec\n");
362        exit(1);
363    }
364
365    /* the codec gives us the frame size, in samples */
366
367    f = fopen(filename, "rb");
368    if (!f) {
369        fprintf(stderr, "could not open %s\n", filename);
370        exit(1);
371    }
372
373    frame = 0;
374    for(;;) {
375        avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
376        if (avpkt.size == 0)
377            break;
378
379        /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
380           and this is the only method to use them because you cannot
381           know the compressed data size before analysing it.
382
383           BUT some other codecs (msmpeg4, mpeg4) are inherently frame
384           based, so you must call them with all the data for one
385           frame exactly. You must also initialize 'width' and
386           'height' before initializing them. */
387
388        /* NOTE2: some codecs allow the raw parameters (frame size,
389           sample rate) to be changed at any frame. We handle this, so
390           you should also take care of it */
391
392        /* here, we use a stream based decoder (mpeg1video), so we
393           feed decoder and see if it could decode a frame */
394        avpkt.data = inbuf;
395        while (avpkt.size > 0) {
396            len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);
397            if (len < 0) {
398                fprintf(stderr, "Error while decoding frame %d\n", frame);
399                exit(1);
400            }
401            if (got_picture) {
402                printf("saving frame %3d\n", frame);
403                fflush(stdout);
404
405                /* the picture is allocated by the decoder. no need to
406                   free it */
407                snprintf(buf, sizeof(buf), outfilename, frame);
408                pgm_save(picture->data[0], picture->linesize[0],
409                         c->width, c->height, buf);
410                frame++;
411            }
412            avpkt.size -= len;
413            avpkt.data += len;
414        }
415    }
416
417    /* some codecs, such as MPEG, transmit the I and P frame with a
418       latency of one frame. You must do the following to have a
419       chance to get the last frame of the video */
420    avpkt.data = NULL;
421    avpkt.size = 0;
422    len = avcodec_decode_video2(c, picture, &got_picture, &avpkt);
423    if (got_picture) {
424        printf("saving last frame %3d\n", frame);
425        fflush(stdout);
426
427        /* the picture is allocated by the decoder. no need to
428           free it */
429        snprintf(buf, sizeof(buf), outfilename, frame);
430        pgm_save(picture->data[0], picture->linesize[0],
431                 c->width, c->height, buf);
432        frame++;
433    }
434
435    fclose(f);
436
437    avcodec_close(c);
438    av_free(c);
439    av_free(picture);
440    printf("\n");
441}
442
443int main(int argc, char **argv)
444{
445    const char *filename;
446
447    /* must be called before using avcodec lib */
448    avcodec_init();
449
450    /* register all the codecs */
451    avcodec_register_all();
452
453    if (argc <= 1) {
454        audio_encode_example("/tmp/test.mp2");
455        audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
456
457        video_encode_example("/tmp/test.mpg");
458        filename = "/tmp/test.mpg";
459    } else {
460        filename = argv[1];
461    }
462
463    //    audio_decode_example("/tmp/test.sw", filename);
464    video_decode_example("/tmp/test%d.pgm", filename);
465
466    return 0;
467}
468