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