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