documenting most stuff in AVCodecContext
[libav.git] / libavcodec / apiexample.c
CommitLineData
de6d9b64
FB
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 */
19void 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 */
87void 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 */
161void 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
261void 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
273void 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
58f26ba9 295 /* for some codecs, such as msmpeg4 and mpeg4, width and height
de6d9b64
FB
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
58f26ba9
FB
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
de6d9b64
FB
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
382int 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}