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