apiexample doesnt send complete frames to the codec
[ffmpeg.git] / libavcodec / apiexample.c
1 /* avcodec API use example.
2  *
3  * Note that this library only handles codecs (mpeg, mpeg4, etc...),
4  * not file formats (avi, vob, etc...). See library 'libav' for the
5  * format handling 
6  */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <math.h>
11
12 #include "avcodec.h"
13
14 #define INBUF_SIZE 4096
15
16 /*
17  * Audio encoding example 
18  */
19 void audio_encode_example(const char *filename)
20 {
21     AVCodec *codec;
22     AVCodecContext *c= NULL;
23     int frame_size, i, j, out_size, outbuf_size;
24     FILE *f;
25     short *samples;
26     float t, tincr;
27     UINT8 *outbuf;
28
29     printf("Audio encoding\n");
30
31     /* find the MP2 encoder */
32     codec = avcodec_find_encoder(CODEC_ID_MP2);
33     if (!codec) {
34         fprintf(stderr, "codec not found\n");
35         exit(1);
36     }
37
38     c= avcodec_alloc_context();
39     
40     /* put sample parameters */
41     c->bit_rate = 64000;
42     c->sample_rate = 44100;
43     c->channels = 2;
44
45     /* open it */
46     if (avcodec_open(c, codec) < 0) {
47         fprintf(stderr, "could not open codec\n");
48         exit(1);
49     }
50     
51     /* the codec gives us the frame size, in samples */
52     frame_size = c->frame_size;
53     samples = malloc(frame_size * 2 * c->channels);
54     outbuf_size = 10000;
55     outbuf = malloc(outbuf_size);
56
57     f = fopen(filename, "w");
58     if (!f) {
59         fprintf(stderr, "could not open %s\n", filename);
60         exit(1);
61     }
62         
63     /* encode a single tone sound */
64     t = 0;
65     tincr = 2 * M_PI * 440.0 / c->sample_rate;
66     for(i=0;i<200;i++) {
67         for(j=0;j<frame_size;j++) {
68             samples[2*j] = (int)(sin(t) * 10000);
69             samples[2*j+1] = samples[2*j];
70             t += tincr;
71         }
72         /* encode the samples */
73         out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
74         fwrite(outbuf, 1, out_size, f);
75     }
76     fclose(f);
77     free(outbuf);
78     free(samples);
79
80     avcodec_close(c);
81     free(c);
82 }
83
84 /*
85  * Audio decoding. 
86  */
87 void audio_decode_example(const char *outfilename, const char *filename)
88 {
89     AVCodec *codec;
90     AVCodecContext *c= NULL;
91     int out_size, size, len;
92     FILE *f, *outfile;
93     UINT8 *outbuf;
94     UINT8 inbuf[INBUF_SIZE], *inbuf_ptr;
95
96     printf("Audio decoding\n");
97
98     /* find the mpeg audio decoder */
99     codec = avcodec_find_decoder(CODEC_ID_MP2);
100     if (!codec) {
101         fprintf(stderr, "codec not found\n");
102         exit(1);
103     }
104
105     c= avcodec_alloc_context();
106
107     /* open it */
108     if (avcodec_open(c, codec) < 0) {
109         fprintf(stderr, "could not open codec\n");
110         exit(1);
111     }
112     
113     outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
114
115     f = fopen(filename, "r");
116     if (!f) {
117         fprintf(stderr, "could not open %s\n", filename);
118         exit(1);
119     }
120     outfile = fopen(outfilename, "w");
121     if (!outfile) {
122         free(c);
123         exit(1);
124     }
125         
126     /* decode until eof */
127     inbuf_ptr = inbuf;
128     for(;;) {
129         size = fread(inbuf, 1, INBUF_SIZE, f);
130         if (size == 0)
131             break;
132
133         inbuf_ptr = inbuf;
134         while (size > 0) {
135             len = avcodec_decode_audio(c, (short *)outbuf, &out_size, 
136                                        inbuf_ptr, size);
137             if (len < 0) {
138                 fprintf(stderr, "Error while decoding\n");
139                 exit(1);
140             }
141             if (out_size > 0) {
142                 /* if a frame has been decoded, output it */
143                 fwrite(outbuf, 1, out_size, outfile);
144             }
145             size -= len;
146             inbuf_ptr += len;
147         }
148     }
149
150     fclose(outfile);
151     fclose(f);
152     free(outbuf);
153
154     avcodec_close(c);
155     free(c);
156 }
157
158 /*
159  * Video encoding example 
160  */
161 void video_encode_example(const char *filename)
162 {
163     AVCodec *codec;
164     AVCodecContext *c= NULL;
165     int i, out_size, size, x, y, outbuf_size;
166     FILE *f;
167     AVPicture picture;
168     UINT8 *outbuf, *picture_buf;
169
170     printf("Video encoding\n");
171
172     /* find the mpeg1 video encoder */
173     codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
174     if (!codec) {
175         fprintf(stderr, "codec not found\n");
176         exit(1);
177     }
178
179     c= avcodec_alloc_context();
180     
181     /* put sample parameters */
182     c->bit_rate = 400000;
183     /* resolution must be a multiple of two */
184     c->width = 352;  
185     c->height = 288;
186     /* frames per second */
187     c->frame_rate = 25 * FRAME_RATE_BASE;  
188     c->gop_size = 10; /* emit one intra frame every ten frames */
189
190     /* open it */
191     if (avcodec_open(c, codec) < 0) {
192         fprintf(stderr, "could not open codec\n");
193         exit(1);
194     }
195     
196     /* the codec gives us the frame size, in samples */
197
198     f = fopen(filename, "w");
199     if (!f) {
200         fprintf(stderr, "could not open %s\n", filename);
201         exit(1);
202     }
203     
204     /* alloc image and output buffer */
205     outbuf_size = 100000;
206     outbuf = malloc(outbuf_size);
207     size = c->width * c->height;
208     picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
209     
210     picture.data[0] = picture_buf;
211     picture.data[1] = picture.data[0] + size;
212     picture.data[2] = picture.data[1] + size / 4;
213     picture.linesize[0] = c->width;
214     picture.linesize[1] = c->width / 2;
215     picture.linesize[2] = c->width / 2;
216
217     /* encode 1 second of video */
218     for(i=0;i<25;i++) {
219         printf("encoding frame %3d\r", i);
220         fflush(stdout);
221         /* prepare a dummy image */
222         /* Y */
223         for(y=0;y<c->height;y++) {
224             for(x=0;x<c->width;x++) {
225                 picture.data[0][y * picture.linesize[0] + x] = x + y + i * 3;
226             }
227         }
228
229         /* Cb and Cr */
230         for(y=0;y<c->height/2;y++) {
231             for(x=0;x<c->width/2;x++) {
232                 picture.data[1][y * picture.linesize[1] + x] = 128 + y + i * 2;
233                 picture.data[2][y * picture.linesize[2] + x] = 64 + x + i * 5;
234             }
235         }
236
237         /* encode the image */
238         out_size = avcodec_encode_video(c, outbuf, outbuf_size, &picture);
239         fwrite(outbuf, 1, out_size, f);
240     }
241
242     /* add sequence end code to have a real mpeg file */
243     outbuf[0] = 0x00;
244     outbuf[1] = 0x00;
245     outbuf[2] = 0x01;
246     outbuf[3] = 0xb7;
247     fwrite(outbuf, 1, 4, f);
248     fclose(f);
249     free(picture_buf);
250     free(outbuf);
251
252     avcodec_close(c);
253     free(c);
254     printf("\n");
255 }
256
257 /*
258  * Video decoding example 
259  */
260
261 void pgm_save(unsigned char *buf,int wrap, int xsize,int ysize,char *filename) 
262 {
263     FILE *f;
264     int i;
265
266     f=fopen(filename,"w");
267     fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);
268     for(i=0;i<ysize;i++)
269         fwrite(buf + i * wrap,1,xsize,f);
270     fclose(f);
271 }
272
273 void video_decode_example(const char *outfilename, const char *filename)
274 {
275     AVCodec *codec;
276     AVCodecContext *c= NULL;
277     int frame, size, got_picture, len;
278     FILE *f;
279     AVPicture picture;
280     UINT8 inbuf[INBUF_SIZE], *inbuf_ptr;
281     char buf[1024];
282
283     printf("Video decoding\n");
284
285     /* find the mpeg1 video decoder */
286     codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO);
287     if (!codec) {
288         fprintf(stderr, "codec not found\n");
289         exit(1);
290     }
291
292     c= avcodec_alloc_context();
293
294     if(codec->capabilities&CODEC_CAP_TRUNCATED)
295         c->flags|= CODEC_FLAG_TRUNCATED; /* we dont send complete frames */
296
297     /* for some codecs, such as msmpeg4 and mpeg4, width and height
298        MUST be initialized there because these info are not available
299        in the bitstream */
300
301     /* open it */
302     if (avcodec_open(c, codec) < 0) {
303         fprintf(stderr, "could not open codec\n");
304         exit(1);
305     }
306     
307     /* the codec gives us the frame size, in samples */
308
309     f = fopen(filename, "r");
310     if (!f) {
311         fprintf(stderr, "could not open %s\n", filename);
312         exit(1);
313     }
314     
315     frame = 0;
316     for(;;) {
317         size = fread(inbuf, 1, INBUF_SIZE, f);
318         if (size == 0)
319             break;
320
321         /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
322            and this is the only method to use them because you cannot
323            know the compressed data size before analysing it. 
324
325            BUT some other codecs (msmpeg4, mpeg4) are inherently frame
326            based, so you must call them with all the data for one
327            frame exactly. You must also initialize 'width' and
328            'height' before initializing them. */
329
330         /* NOTE2: some codecs allow the raw parameters (frame size,
331            sample rate) to be changed at any frame. We handle this, so
332            you should also take care of it */
333
334         /* here, we use a stream based decoder (mpeg1video), so we
335            feed decoder and see if it could decode a frame */
336         inbuf_ptr = inbuf;
337         while (size > 0) {
338             len = avcodec_decode_video(c, &picture, &got_picture, 
339                                        inbuf_ptr, size);
340             if (len < 0) {
341                 fprintf(stderr, "Error while decoding frame %d\n", frame);
342                 exit(1);
343             }
344             if (got_picture) {
345                 printf("saving frame %3d\r", frame);
346                 fflush(stdout);
347
348                 /* the picture is allocated by the decoder. no need to
349                    free it */
350                 snprintf(buf, sizeof(buf), outfilename, frame);
351                 pgm_save(picture.data[0], picture.linesize[0], 
352                          c->width, c->height, buf);
353                 frame++;
354             }
355             size -= len;
356             inbuf_ptr += len;
357         }
358     }
359
360     /* some codecs, such as MPEG, transmit the I and P frame with a
361        latency of one frame. You must do the following to have a
362        chance to get the last frame of the video */
363     len = avcodec_decode_video(c, &picture, &got_picture, 
364                                NULL, 0);
365     if (got_picture) {
366         printf("saving frame %3d\r", frame);
367         fflush(stdout);
368         
369         /* the picture is allocated by the decoder. no need to
370            free it */
371         snprintf(buf, sizeof(buf), outfilename, frame);
372         pgm_save(picture.data[0], picture.linesize[0], 
373                  c->width, c->height, buf);
374         frame++;
375     }
376         
377     fclose(f);
378
379     avcodec_close(c);
380     free(c);
381     printf("\n");
382 }
383
384
385 int main(int argc, char **argv)
386 {
387     const char *filename;
388
389     /* must be called before using avcodec lib */
390     avcodec_init();
391
392     /* register all the codecs (you can also register only the codec
393        you wish to have smaller code */
394     avcodec_register_all();
395     
396     if (argc <= 1) {
397         audio_encode_example("/tmp/test.mp2");
398         audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
399
400         video_encode_example("/tmp/test.mpg");
401         filename = "/tmp/test.mpg";
402     } else {
403         filename = argv[1];
404     }
405
406     //    audio_decode_example("/tmp/test.sw", filename);
407     video_decode_example("/tmp/test%d.pgm", filename);
408
409     return 0;
410 }