]> git.sesse.net Git - ffmpeg/blob - libavcodec/apiexample.c
fixed some bugs in app parser - some jfif and adobe jpgs fixed
[ffmpeg] / 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     /* for some codecs, such as msmpeg4 and mpeg4, width and height
295        MUST be initialized there because these info are not available
296        in the bitstream */
297
298     /* open it */
299     if (avcodec_open(c, codec) < 0) {
300         fprintf(stderr, "could not open codec\n");
301         exit(1);
302     }
303     
304     /* the codec gives us the frame size, in samples */
305
306     f = fopen(filename, "r");
307     if (!f) {
308         fprintf(stderr, "could not open %s\n", filename);
309         exit(1);
310     }
311     
312     frame = 0;
313     for(;;) {
314         size = fread(inbuf, 1, INBUF_SIZE, f);
315         if (size == 0)
316             break;
317
318         /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
319            and this is the only method to use them because you cannot
320            know the compressed data size before analysing it. 
321
322            BUT some other codecs (msmpeg4, mpeg4) are inherently frame
323            based, so you must call them with all the data for one
324            frame exactly. You must also initialize 'width' and
325            'height' before initializing them. */
326
327         /* NOTE2: some codecs allow the raw parameters (frame size,
328            sample rate) to be changed at any frame. We handle this, so
329            you should also take care of it */
330
331         /* here, we use a stream based decoder (mpeg1video), so we
332            feed decoder and see if it could decode a frame */
333         inbuf_ptr = inbuf;
334         while (size > 0) {
335             len = avcodec_decode_video(c, &picture, &got_picture, 
336                                        inbuf_ptr, size);
337             if (len < 0) {
338                 fprintf(stderr, "Error while decoding frame %d\n", frame);
339                 exit(1);
340             }
341             if (got_picture) {
342                 printf("saving frame %3d\r", frame);
343                 fflush(stdout);
344
345                 /* the picture is allocated by the decoder. no need to
346                    free it */
347                 snprintf(buf, sizeof(buf), outfilename, frame);
348                 pgm_save(picture.data[0], picture.linesize[0], 
349                          c->width, c->height, buf);
350                 frame++;
351             }
352             size -= len;
353             inbuf_ptr += len;
354         }
355     }
356
357     /* some codecs, such as MPEG, transmit the I and P frame with a
358        latency of one frame. You must do the following to have a
359        chance to get the last frame of the video */
360     len = avcodec_decode_video(c, &picture, &got_picture, 
361                                NULL, 0);
362     if (got_picture) {
363         printf("saving frame %3d\r", frame);
364         fflush(stdout);
365         
366         /* the picture is allocated by the decoder. no need to
367            free it */
368         snprintf(buf, sizeof(buf), outfilename, frame);
369         pgm_save(picture.data[0], picture.linesize[0], 
370                  c->width, c->height, buf);
371         frame++;
372     }
373         
374     fclose(f);
375
376     avcodec_close(c);
377     free(c);
378     printf("\n");
379 }
380
381
382 int main(int argc, char **argv)
383 {
384     const char *filename;
385
386     /* must be called before using avcodec lib */
387     avcodec_init();
388
389     /* register all the codecs (you can also register only the codec
390        you wish to have smaller code */
391     avcodec_register_all();
392     
393     if (argc <= 1) {
394         audio_encode_example("/tmp/test.mp2");
395         audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
396
397         video_encode_example("/tmp/test.mpg");
398         filename = "/tmp/test.mpg";
399     } else {
400         filename = argv[1];
401     }
402
403     //    audio_decode_example("/tmp/test.sw", filename);
404     video_decode_example("/tmp/test%d.pgm", filename);
405
406     return 0;
407 }