]> git.sesse.net Git - ffmpeg/blob - libavcodec/apiexample.c
8bpp support (no dithering yet, use -vop noise for now)
[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 codec_context, *c = &codec_context;
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     /* put default values */
39     memset(c, 0, sizeof(*c));
40
41     /* put sample parameters */
42     c->bit_rate = 64000;
43     c->sample_rate = 44100;
44     c->channels = 2;
45
46     /* open it */
47     if (avcodec_open(c, codec) < 0) {
48         fprintf(stderr, "could not open codec\n");
49         exit(1);
50     }
51     
52     /* the codec gives us the frame size, in samples */
53     frame_size = c->frame_size;
54     samples = malloc(frame_size * 2 * c->channels);
55     outbuf_size = 10000;
56     outbuf = malloc(outbuf_size);
57
58     f = fopen(filename, "w");
59     if (!f) {
60         fprintf(stderr, "could not open %s\n", filename);
61         exit(1);
62     }
63         
64     /* encode a single tone sound */
65     t = 0;
66     tincr = 2 * M_PI * 440.0 / c->sample_rate;
67     for(i=0;i<200;i++) {
68         for(j=0;j<frame_size;j++) {
69             samples[2*j] = (int)(sin(t) * 10000);
70             samples[2*j+1] = samples[2*j];
71             t += tincr;
72         }
73         /* encode the samples */
74         out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples);
75         fwrite(outbuf, 1, out_size, f);
76     }
77     fclose(f);
78     free(outbuf);
79     free(samples);
80
81     avcodec_close(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 codec_context, *c = &codec_context;
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     /* put default values */
106     memset(c, 0, sizeof(*c));
107
108     /* open it */
109     if (avcodec_open(c, codec) < 0) {
110         fprintf(stderr, "could not open codec\n");
111         exit(1);
112     }
113     
114     outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);
115
116     f = fopen(filename, "r");
117     if (!f) {
118         fprintf(stderr, "could not open %s\n", filename);
119         exit(1);
120     }
121     outfile = fopen(outfilename, "w");
122     if (!outfile) {
123         fprintf(stderr, "could not open %s\n", outfilename);
124         exit(1);
125     }
126         
127     /* decode until eof */
128     inbuf_ptr = inbuf;
129     for(;;) {
130         size = fread(inbuf, 1, INBUF_SIZE, f);
131         if (size == 0)
132             break;
133
134         inbuf_ptr = inbuf;
135         while (size > 0) {
136             len = avcodec_decode_audio(c, (short *)outbuf, &out_size, 
137                                        inbuf_ptr, size);
138             if (len < 0) {
139                 fprintf(stderr, "Error while decoding\n");
140                 exit(1);
141             }
142             if (out_size > 0) {
143                 /* if a frame has been decoded, output it */
144                 fwrite(outbuf, 1, out_size, outfile);
145             }
146             size -= len;
147             inbuf_ptr += len;
148         }
149     }
150
151     fclose(outfile);
152     fclose(f);
153     free(outbuf);
154
155     avcodec_close(c);
156 }
157
158 /*
159  * Video encoding example 
160  */
161 void video_encode_example(const char *filename)
162 {
163     AVCodec *codec;
164     AVCodecContext codec_context, *c = &codec_context;
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     /* put default values */
180     memset(c, 0, sizeof(*c));
181
182     /* put sample parameters */
183     c->bit_rate = 400000;
184     /* resolution must be a multiple of two */
185     c->width = 352;  
186     c->height = 288;
187     /* frames per second */
188     c->frame_rate = 25 * FRAME_RATE_BASE;  
189     c->gop_size = 10; /* emit one intra frame every ten frames */
190
191     /* open it */
192     if (avcodec_open(c, codec) < 0) {
193         fprintf(stderr, "could not open codec\n");
194         exit(1);
195     }
196     
197     /* the codec gives us the frame size, in samples */
198
199     f = fopen(filename, "w");
200     if (!f) {
201         fprintf(stderr, "could not open %s\n", filename);
202         exit(1);
203     }
204     
205     /* alloc image and output buffer */
206     outbuf_size = 100000;
207     outbuf = malloc(outbuf_size);
208     size = c->width * c->height;
209     picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */
210     
211     picture.data[0] = picture_buf;
212     picture.data[1] = picture.data[0] + size;
213     picture.data[2] = picture.data[1] + size / 4;
214     picture.linesize[0] = c->width;
215     picture.linesize[1] = c->width / 2;
216     picture.linesize[2] = c->width / 2;
217
218     /* encode 1 second of video */
219     for(i=0;i<25;i++) {
220         printf("encoding frame %3d\r", i);
221         fflush(stdout);
222         /* prepare a dummy image */
223         /* Y */
224         for(y=0;y<c->height;y++) {
225             for(x=0;x<c->width;x++) {
226                 picture.data[0][y * picture.linesize[0] + x] = x + y + i * 3;
227             }
228         }
229
230         /* Cb and Cr */
231         for(y=0;y<c->height/2;y++) {
232             for(x=0;x<c->width/2;x++) {
233                 picture.data[1][y * picture.linesize[1] + x] = 128 + y + i * 2;
234                 picture.data[2][y * picture.linesize[2] + x] = 64 + x + i * 5;
235             }
236         }
237
238         /* encode the image */
239         out_size = avcodec_encode_video(c, outbuf, outbuf_size, &picture);
240         fwrite(outbuf, 1, out_size, f);
241     }
242
243     /* add sequence end code to have a real mpeg file */
244     outbuf[0] = 0x00;
245     outbuf[1] = 0x00;
246     outbuf[2] = 0x01;
247     outbuf[3] = 0xb7;
248     fwrite(outbuf, 1, 4, f);
249     fclose(f);
250     free(picture_buf);
251     free(outbuf);
252
253     avcodec_close(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 codec_context, *c = &codec_context;
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     /* put default values */
293     memset(c, 0, sizeof(*c));
294
295     /* for some codecs, such as msmpeg4 and mpeg4, width and height
296        MUST be initialized there because these info are not available
297        in the bitstream */
298
299     /* open it */
300     if (avcodec_open(c, codec) < 0) {
301         fprintf(stderr, "could not open codec\n");
302         exit(1);
303     }
304     
305     /* the codec gives us the frame size, in samples */
306
307     f = fopen(filename, "r");
308     if (!f) {
309         fprintf(stderr, "could not open %s\n", filename);
310         exit(1);
311     }
312     
313     frame = 0;
314     for(;;) {
315         size = fread(inbuf, 1, INBUF_SIZE, f);
316         if (size == 0)
317             break;
318
319         /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)
320            and this is the only method to use them because you cannot
321            know the compressed data size before analysing it. 
322
323            BUT some other codecs (msmpeg4, mpeg4) are inherently frame
324            based, so you must call them with all the data for one
325            frame exactly. You must also initialize 'width' and
326            'height' before initializing them. */
327
328         /* NOTE2: some codecs allow the raw parameters (frame size,
329            sample rate) to be changed at any frame. We handle this, so
330            you should also take care of it */
331
332         /* here, we use a stream based decoder (mpeg1video), so we
333            feed decoder and see if it could decode a frame */
334         inbuf_ptr = inbuf;
335         while (size > 0) {
336             len = avcodec_decode_video(c, &picture, &got_picture, 
337                                        inbuf_ptr, size);
338             if (len < 0) {
339                 fprintf(stderr, "Error while decoding frame %d\n", frame);
340                 exit(1);
341             }
342             if (got_picture) {
343                 printf("saving frame %3d\r", frame);
344                 fflush(stdout);
345
346                 /* the picture is allocated by the decoder. no need to
347                    free it */
348                 snprintf(buf, sizeof(buf), outfilename, frame);
349                 pgm_save(picture.data[0], picture.linesize[0], 
350                          c->width, c->height, buf);
351                 frame++;
352             }
353             size -= len;
354             inbuf_ptr += len;
355         }
356     }
357
358     /* some codecs, such as MPEG, transmit the I and P frame with a
359        latency of one frame. You must do the following to have a
360        chance to get the last frame of the video */
361     len = avcodec_decode_video(c, &picture, &got_picture, 
362                                NULL, 0);
363     if (got_picture) {
364         printf("saving frame %3d\r", frame);
365         fflush(stdout);
366         
367         /* the picture is allocated by the decoder. no need to
368            free it */
369         snprintf(buf, sizeof(buf), outfilename, frame);
370         pgm_save(picture.data[0], picture.linesize[0], 
371                  c->width, c->height, buf);
372         frame++;
373     }
374         
375     fclose(f);
376
377     avcodec_close(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 }