Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Copyright (c) 2001 Fabrice Bellard | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | * of this software and associated documentation files (the "Software"), to deal | |
6 | * in the Software without restriction, including without limitation the rights | |
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 | * copies of the Software, and to permit persons to whom the Software is | |
9 | * furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 | * THE SOFTWARE. | |
21 | */ | |
22 | ||
23 | /** | |
24 | * @file | |
25 | * libavcodec API use example. | |
26 | * | |
27 | * @example decoding_encoding.c | |
28 | * Note that libavcodec only handles codecs (mpeg, mpeg4, etc...), | |
29 | * not file formats (avi, vob, mp4, mov, mkv, mxf, flv, mpegts, mpegps, etc...). See library 'libavformat' for the | |
30 | * format handling | |
31 | */ | |
32 | ||
33 | #include <math.h> | |
34 | ||
35 | #include <libavutil/opt.h> | |
36 | #include <libavcodec/avcodec.h> | |
37 | #include <libavutil/channel_layout.h> | |
38 | #include <libavutil/common.h> | |
39 | #include <libavutil/imgutils.h> | |
40 | #include <libavutil/mathematics.h> | |
41 | #include <libavutil/samplefmt.h> | |
42 | ||
43 | #define INBUF_SIZE 4096 | |
44 | #define AUDIO_INBUF_SIZE 20480 | |
45 | #define AUDIO_REFILL_THRESH 4096 | |
46 | ||
47 | /* check that a given sample format is supported by the encoder */ | |
48 | static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt) | |
49 | { | |
50 | const enum AVSampleFormat *p = codec->sample_fmts; | |
51 | ||
52 | while (*p != AV_SAMPLE_FMT_NONE) { | |
53 | if (*p == sample_fmt) | |
54 | return 1; | |
55 | p++; | |
56 | } | |
57 | return 0; | |
58 | } | |
59 | ||
60 | /* just pick the highest supported samplerate */ | |
61 | static int select_sample_rate(AVCodec *codec) | |
62 | { | |
63 | const int *p; | |
64 | int best_samplerate = 0; | |
65 | ||
66 | if (!codec->supported_samplerates) | |
67 | return 44100; | |
68 | ||
69 | p = codec->supported_samplerates; | |
70 | while (*p) { | |
71 | best_samplerate = FFMAX(*p, best_samplerate); | |
72 | p++; | |
73 | } | |
74 | return best_samplerate; | |
75 | } | |
76 | ||
77 | /* select layout with the highest channel count */ | |
78 | static int select_channel_layout(AVCodec *codec) | |
79 | { | |
80 | const uint64_t *p; | |
81 | uint64_t best_ch_layout = 0; | |
82 | int best_nb_channels = 0; | |
83 | ||
84 | if (!codec->channel_layouts) | |
85 | return AV_CH_LAYOUT_STEREO; | |
86 | ||
87 | p = codec->channel_layouts; | |
88 | while (*p) { | |
89 | int nb_channels = av_get_channel_layout_nb_channels(*p); | |
90 | ||
91 | if (nb_channels > best_nb_channels) { | |
92 | best_ch_layout = *p; | |
93 | best_nb_channels = nb_channels; | |
94 | } | |
95 | p++; | |
96 | } | |
97 | return best_ch_layout; | |
98 | } | |
99 | ||
100 | /* | |
101 | * Audio encoding example | |
102 | */ | |
103 | static void audio_encode_example(const char *filename) | |
104 | { | |
105 | AVCodec *codec; | |
106 | AVCodecContext *c= NULL; | |
107 | AVFrame *frame; | |
108 | AVPacket pkt; | |
109 | int i, j, k, ret, got_output; | |
110 | int buffer_size; | |
111 | FILE *f; | |
112 | uint16_t *samples; | |
113 | float t, tincr; | |
114 | ||
115 | printf("Encode audio file %s\n", filename); | |
116 | ||
117 | /* find the MP2 encoder */ | |
118 | codec = avcodec_find_encoder(AV_CODEC_ID_MP2); | |
119 | if (!codec) { | |
120 | fprintf(stderr, "Codec not found\n"); | |
121 | exit(1); | |
122 | } | |
123 | ||
124 | c = avcodec_alloc_context3(codec); | |
125 | if (!c) { | |
126 | fprintf(stderr, "Could not allocate audio codec context\n"); | |
127 | exit(1); | |
128 | } | |
129 | ||
130 | /* put sample parameters */ | |
131 | c->bit_rate = 64000; | |
132 | ||
133 | /* check that the encoder supports s16 pcm input */ | |
134 | c->sample_fmt = AV_SAMPLE_FMT_S16; | |
135 | if (!check_sample_fmt(codec, c->sample_fmt)) { | |
136 | fprintf(stderr, "Encoder does not support sample format %s", | |
137 | av_get_sample_fmt_name(c->sample_fmt)); | |
138 | exit(1); | |
139 | } | |
140 | ||
141 | /* select other audio parameters supported by the encoder */ | |
142 | c->sample_rate = select_sample_rate(codec); | |
143 | c->channel_layout = select_channel_layout(codec); | |
144 | c->channels = av_get_channel_layout_nb_channels(c->channel_layout); | |
145 | ||
146 | /* open it */ | |
147 | if (avcodec_open2(c, codec, NULL) < 0) { | |
148 | fprintf(stderr, "Could not open codec\n"); | |
149 | exit(1); | |
150 | } | |
151 | ||
152 | f = fopen(filename, "wb"); | |
153 | if (!f) { | |
154 | fprintf(stderr, "Could not open %s\n", filename); | |
155 | exit(1); | |
156 | } | |
157 | ||
158 | /* frame containing input raw audio */ | |
159 | frame = av_frame_alloc(); | |
160 | if (!frame) { | |
161 | fprintf(stderr, "Could not allocate audio frame\n"); | |
162 | exit(1); | |
163 | } | |
164 | ||
165 | frame->nb_samples = c->frame_size; | |
166 | frame->format = c->sample_fmt; | |
167 | frame->channel_layout = c->channel_layout; | |
168 | ||
169 | /* the codec gives us the frame size, in samples, | |
170 | * we calculate the size of the samples buffer in bytes */ | |
171 | buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, | |
172 | c->sample_fmt, 0); | |
173 | if (buffer_size < 0) { | |
174 | fprintf(stderr, "Could not get sample buffer size\n"); | |
175 | exit(1); | |
176 | } | |
177 | samples = av_malloc(buffer_size); | |
178 | if (!samples) { | |
179 | fprintf(stderr, "Could not allocate %d bytes for samples buffer\n", | |
180 | buffer_size); | |
181 | exit(1); | |
182 | } | |
183 | /* setup the data pointers in the AVFrame */ | |
184 | ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, | |
185 | (const uint8_t*)samples, buffer_size, 0); | |
186 | if (ret < 0) { | |
187 | fprintf(stderr, "Could not setup audio frame\n"); | |
188 | exit(1); | |
189 | } | |
190 | ||
191 | /* encode a single tone sound */ | |
192 | t = 0; | |
193 | tincr = 2 * M_PI * 440.0 / c->sample_rate; | |
194 | for (i = 0; i < 200; i++) { | |
195 | av_init_packet(&pkt); | |
196 | pkt.data = NULL; // packet data will be allocated by the encoder | |
197 | pkt.size = 0; | |
198 | ||
199 | for (j = 0; j < c->frame_size; j++) { | |
200 | samples[2*j] = (int)(sin(t) * 10000); | |
201 | ||
202 | for (k = 1; k < c->channels; k++) | |
203 | samples[2*j + k] = samples[2*j]; | |
204 | t += tincr; | |
205 | } | |
206 | /* encode the samples */ | |
207 | ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); | |
208 | if (ret < 0) { | |
209 | fprintf(stderr, "Error encoding audio frame\n"); | |
210 | exit(1); | |
211 | } | |
212 | if (got_output) { | |
213 | fwrite(pkt.data, 1, pkt.size, f); | |
214 | av_free_packet(&pkt); | |
215 | } | |
216 | } | |
217 | ||
218 | /* get the delayed frames */ | |
219 | for (got_output = 1; got_output; i++) { | |
220 | ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output); | |
221 | if (ret < 0) { | |
222 | fprintf(stderr, "Error encoding frame\n"); | |
223 | exit(1); | |
224 | } | |
225 | ||
226 | if (got_output) { | |
227 | fwrite(pkt.data, 1, pkt.size, f); | |
228 | av_free_packet(&pkt); | |
229 | } | |
230 | } | |
231 | fclose(f); | |
232 | ||
233 | av_freep(&samples); | |
234 | av_frame_free(&frame); | |
235 | avcodec_close(c); | |
236 | av_free(c); | |
237 | } | |
238 | ||
239 | /* | |
240 | * Audio decoding. | |
241 | */ | |
242 | static void audio_decode_example(const char *outfilename, const char *filename) | |
243 | { | |
244 | AVCodec *codec; | |
245 | AVCodecContext *c= NULL; | |
246 | int len; | |
247 | FILE *f, *outfile; | |
248 | uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; | |
249 | AVPacket avpkt; | |
250 | AVFrame *decoded_frame = NULL; | |
251 | ||
252 | av_init_packet(&avpkt); | |
253 | ||
254 | printf("Decode audio file %s to %s\n", filename, outfilename); | |
255 | ||
256 | /* find the mpeg audio decoder */ | |
257 | codec = avcodec_find_decoder(AV_CODEC_ID_MP2); | |
258 | if (!codec) { | |
259 | fprintf(stderr, "Codec not found\n"); | |
260 | exit(1); | |
261 | } | |
262 | ||
263 | c = avcodec_alloc_context3(codec); | |
264 | if (!c) { | |
265 | fprintf(stderr, "Could not allocate audio codec context\n"); | |
266 | exit(1); | |
267 | } | |
268 | ||
269 | /* open it */ | |
270 | if (avcodec_open2(c, codec, NULL) < 0) { | |
271 | fprintf(stderr, "Could not open codec\n"); | |
272 | exit(1); | |
273 | } | |
274 | ||
275 | f = fopen(filename, "rb"); | |
276 | if (!f) { | |
277 | fprintf(stderr, "Could not open %s\n", filename); | |
278 | exit(1); | |
279 | } | |
280 | outfile = fopen(outfilename, "wb"); | |
281 | if (!outfile) { | |
282 | av_free(c); | |
283 | exit(1); | |
284 | } | |
285 | ||
286 | /* decode until eof */ | |
287 | avpkt.data = inbuf; | |
288 | avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); | |
289 | ||
290 | while (avpkt.size > 0) { | |
291 | int got_frame = 0; | |
292 | ||
293 | if (!decoded_frame) { | |
294 | if (!(decoded_frame = av_frame_alloc())) { | |
295 | fprintf(stderr, "Could not allocate audio frame\n"); | |
296 | exit(1); | |
297 | } | |
298 | } | |
299 | ||
300 | len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); | |
301 | if (len < 0) { | |
302 | fprintf(stderr, "Error while decoding\n"); | |
303 | exit(1); | |
304 | } | |
305 | if (got_frame) { | |
306 | /* if a frame has been decoded, output it */ | |
307 | int data_size = av_samples_get_buffer_size(NULL, c->channels, | |
308 | decoded_frame->nb_samples, | |
309 | c->sample_fmt, 1); | |
310 | if (data_size < 0) { | |
311 | /* This should not occur, checking just for paranoia */ | |
312 | fprintf(stderr, "Failed to calculate data size\n"); | |
313 | exit(1); | |
314 | } | |
315 | fwrite(decoded_frame->data[0], 1, data_size, outfile); | |
316 | } | |
317 | avpkt.size -= len; | |
318 | avpkt.data += len; | |
319 | avpkt.dts = | |
320 | avpkt.pts = AV_NOPTS_VALUE; | |
321 | if (avpkt.size < AUDIO_REFILL_THRESH) { | |
322 | /* Refill the input buffer, to avoid trying to decode | |
323 | * incomplete frames. Instead of this, one could also use | |
324 | * a parser, or use a proper container format through | |
325 | * libavformat. */ | |
326 | memmove(inbuf, avpkt.data, avpkt.size); | |
327 | avpkt.data = inbuf; | |
328 | len = fread(avpkt.data + avpkt.size, 1, | |
329 | AUDIO_INBUF_SIZE - avpkt.size, f); | |
330 | if (len > 0) | |
331 | avpkt.size += len; | |
332 | } | |
333 | } | |
334 | ||
335 | fclose(outfile); | |
336 | fclose(f); | |
337 | ||
338 | avcodec_close(c); | |
339 | av_free(c); | |
340 | av_frame_free(&decoded_frame); | |
341 | } | |
342 | ||
343 | /* | |
344 | * Video encoding example | |
345 | */ | |
346 | static void video_encode_example(const char *filename, int codec_id) | |
347 | { | |
348 | AVCodec *codec; | |
349 | AVCodecContext *c= NULL; | |
350 | int i, ret, x, y, got_output; | |
351 | FILE *f; | |
352 | AVFrame *frame; | |
353 | AVPacket pkt; | |
354 | uint8_t endcode[] = { 0, 0, 1, 0xb7 }; | |
355 | ||
356 | printf("Encode video file %s\n", filename); | |
357 | ||
358 | /* find the mpeg1 video encoder */ | |
359 | codec = avcodec_find_encoder(codec_id); | |
360 | if (!codec) { | |
361 | fprintf(stderr, "Codec not found\n"); | |
362 | exit(1); | |
363 | } | |
364 | ||
365 | c = avcodec_alloc_context3(codec); | |
366 | if (!c) { | |
367 | fprintf(stderr, "Could not allocate video codec context\n"); | |
368 | exit(1); | |
369 | } | |
370 | ||
371 | /* put sample parameters */ | |
372 | c->bit_rate = 400000; | |
373 | /* resolution must be a multiple of two */ | |
374 | c->width = 352; | |
375 | c->height = 288; | |
376 | /* frames per second */ | |
377 | c->time_base = (AVRational){1,25}; | |
378 | /* emit one intra frame every ten frames | |
379 | * check frame pict_type before passing frame | |
380 | * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I | |
381 | * then gop_size is ignored and the output of encoder | |
382 | * will always be I frame irrespective to gop_size | |
383 | */ | |
384 | c->gop_size = 10; | |
385 | c->max_b_frames = 1; | |
386 | c->pix_fmt = AV_PIX_FMT_YUV420P; | |
387 | ||
388 | if (codec_id == AV_CODEC_ID_H264) | |
389 | av_opt_set(c->priv_data, "preset", "slow", 0); | |
390 | ||
391 | /* open it */ | |
392 | if (avcodec_open2(c, codec, NULL) < 0) { | |
393 | fprintf(stderr, "Could not open codec\n"); | |
394 | exit(1); | |
395 | } | |
396 | ||
397 | f = fopen(filename, "wb"); | |
398 | if (!f) { | |
399 | fprintf(stderr, "Could not open %s\n", filename); | |
400 | exit(1); | |
401 | } | |
402 | ||
403 | frame = av_frame_alloc(); | |
404 | if (!frame) { | |
405 | fprintf(stderr, "Could not allocate video frame\n"); | |
406 | exit(1); | |
407 | } | |
408 | frame->format = c->pix_fmt; | |
409 | frame->width = c->width; | |
410 | frame->height = c->height; | |
411 | ||
412 | /* the image can be allocated by any means and av_image_alloc() is | |
413 | * just the most convenient way if av_malloc() is to be used */ | |
414 | ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, | |
415 | c->pix_fmt, 32); | |
416 | if (ret < 0) { | |
417 | fprintf(stderr, "Could not allocate raw picture buffer\n"); | |
418 | exit(1); | |
419 | } | |
420 | ||
421 | /* encode 1 second of video */ | |
422 | for (i = 0; i < 25; i++) { | |
423 | av_init_packet(&pkt); | |
424 | pkt.data = NULL; // packet data will be allocated by the encoder | |
425 | pkt.size = 0; | |
426 | ||
427 | fflush(stdout); | |
428 | /* prepare a dummy image */ | |
429 | /* Y */ | |
430 | for (y = 0; y < c->height; y++) { | |
431 | for (x = 0; x < c->width; x++) { | |
432 | frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; | |
433 | } | |
434 | } | |
435 | ||
436 | /* Cb and Cr */ | |
437 | for (y = 0; y < c->height/2; y++) { | |
438 | for (x = 0; x < c->width/2; x++) { | |
439 | frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; | |
440 | frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; | |
441 | } | |
442 | } | |
443 | ||
444 | frame->pts = i; | |
445 | ||
446 | /* encode the image */ | |
447 | ret = avcodec_encode_video2(c, &pkt, frame, &got_output); | |
448 | if (ret < 0) { | |
449 | fprintf(stderr, "Error encoding frame\n"); | |
450 | exit(1); | |
451 | } | |
452 | ||
453 | if (got_output) { | |
454 | printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |
455 | fwrite(pkt.data, 1, pkt.size, f); | |
456 | av_free_packet(&pkt); | |
457 | } | |
458 | } | |
459 | ||
460 | /* get the delayed frames */ | |
461 | for (got_output = 1; got_output; i++) { | |
462 | fflush(stdout); | |
463 | ||
464 | ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); | |
465 | if (ret < 0) { | |
466 | fprintf(stderr, "Error encoding frame\n"); | |
467 | exit(1); | |
468 | } | |
469 | ||
470 | if (got_output) { | |
471 | printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |
472 | fwrite(pkt.data, 1, pkt.size, f); | |
473 | av_free_packet(&pkt); | |
474 | } | |
475 | } | |
476 | ||
477 | /* add sequence end code to have a real mpeg file */ | |
478 | fwrite(endcode, 1, sizeof(endcode), f); | |
479 | fclose(f); | |
480 | ||
481 | avcodec_close(c); | |
482 | av_free(c); | |
483 | av_freep(&frame->data[0]); | |
484 | av_frame_free(&frame); | |
485 | printf("\n"); | |
486 | } | |
487 | ||
488 | /* | |
489 | * Video decoding example | |
490 | */ | |
491 | ||
492 | static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, | |
493 | char *filename) | |
494 | { | |
495 | FILE *f; | |
496 | int i; | |
497 | ||
498 | f = fopen(filename,"w"); | |
499 | fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); | |
500 | for (i = 0; i < ysize; i++) | |
501 | fwrite(buf + i * wrap, 1, xsize, f); | |
502 | fclose(f); | |
503 | } | |
504 | ||
505 | static int decode_write_frame(const char *outfilename, AVCodecContext *avctx, | |
506 | AVFrame *frame, int *frame_count, AVPacket *pkt, int last) | |
507 | { | |
508 | int len, got_frame; | |
509 | char buf[1024]; | |
510 | ||
511 | len = avcodec_decode_video2(avctx, frame, &got_frame, pkt); | |
512 | if (len < 0) { | |
513 | fprintf(stderr, "Error while decoding frame %d\n", *frame_count); | |
514 | return len; | |
515 | } | |
516 | if (got_frame) { | |
517 | printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count); | |
518 | fflush(stdout); | |
519 | ||
520 | /* the picture is allocated by the decoder, no need to free it */ | |
521 | snprintf(buf, sizeof(buf), outfilename, *frame_count); | |
522 | pgm_save(frame->data[0], frame->linesize[0], | |
523 | avctx->width, avctx->height, buf); | |
524 | (*frame_count)++; | |
525 | } | |
526 | if (pkt->data) { | |
527 | pkt->size -= len; | |
528 | pkt->data += len; | |
529 | } | |
530 | return 0; | |
531 | } | |
532 | ||
533 | static void video_decode_example(const char *outfilename, const char *filename) | |
534 | { | |
535 | AVCodec *codec; | |
536 | AVCodecContext *c= NULL; | |
537 | int frame_count; | |
538 | FILE *f; | |
539 | AVFrame *frame; | |
540 | uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; | |
541 | AVPacket avpkt; | |
542 | ||
543 | av_init_packet(&avpkt); | |
544 | ||
545 | /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ | |
546 | memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); | |
547 | ||
548 | printf("Decode video file %s to %s\n", filename, outfilename); | |
549 | ||
550 | /* find the mpeg1 video decoder */ | |
551 | codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); | |
552 | if (!codec) { | |
553 | fprintf(stderr, "Codec not found\n"); | |
554 | exit(1); | |
555 | } | |
556 | ||
557 | c = avcodec_alloc_context3(codec); | |
558 | if (!c) { | |
559 | fprintf(stderr, "Could not allocate video codec context\n"); | |
560 | exit(1); | |
561 | } | |
562 | ||
563 | if(codec->capabilities&CODEC_CAP_TRUNCATED) | |
564 | c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ | |
565 | ||
566 | /* For some codecs, such as msmpeg4 and mpeg4, width and height | |
567 | MUST be initialized there because this information is not | |
568 | available in the bitstream. */ | |
569 | ||
570 | /* open it */ | |
571 | if (avcodec_open2(c, codec, NULL) < 0) { | |
572 | fprintf(stderr, "Could not open codec\n"); | |
573 | exit(1); | |
574 | } | |
575 | ||
576 | f = fopen(filename, "rb"); | |
577 | if (!f) { | |
578 | fprintf(stderr, "Could not open %s\n", filename); | |
579 | exit(1); | |
580 | } | |
581 | ||
582 | frame = av_frame_alloc(); | |
583 | if (!frame) { | |
584 | fprintf(stderr, "Could not allocate video frame\n"); | |
585 | exit(1); | |
586 | } | |
587 | ||
588 | frame_count = 0; | |
589 | for (;;) { | |
590 | avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); | |
591 | if (avpkt.size == 0) | |
592 | break; | |
593 | ||
594 | /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) | |
595 | and this is the only method to use them because you cannot | |
596 | know the compressed data size before analysing it. | |
597 | ||
598 | BUT some other codecs (msmpeg4, mpeg4) are inherently frame | |
599 | based, so you must call them with all the data for one | |
600 | frame exactly. You must also initialize 'width' and | |
601 | 'height' before initializing them. */ | |
602 | ||
603 | /* NOTE2: some codecs allow the raw parameters (frame size, | |
604 | sample rate) to be changed at any frame. We handle this, so | |
605 | you should also take care of it */ | |
606 | ||
607 | /* here, we use a stream based decoder (mpeg1video), so we | |
608 | feed decoder and see if it could decode a frame */ | |
609 | avpkt.data = inbuf; | |
610 | while (avpkt.size > 0) | |
611 | if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0) | |
612 | exit(1); | |
613 | } | |
614 | ||
615 | /* some codecs, such as MPEG, transmit the I and P frame with a | |
616 | latency of one frame. You must do the following to have a | |
617 | chance to get the last frame of the video */ | |
618 | avpkt.data = NULL; | |
619 | avpkt.size = 0; | |
620 | decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1); | |
621 | ||
622 | fclose(f); | |
623 | ||
624 | avcodec_close(c); | |
625 | av_free(c); | |
626 | av_frame_free(&frame); | |
627 | printf("\n"); | |
628 | } | |
629 | ||
630 | int main(int argc, char **argv) | |
631 | { | |
632 | const char *output_type; | |
633 | ||
634 | /* register all the codecs */ | |
635 | avcodec_register_all(); | |
636 | ||
637 | if (argc < 2) { | |
638 | printf("usage: %s output_type\n" | |
639 | "API example program to decode/encode a media stream with libavcodec.\n" | |
640 | "This program generates a synthetic stream and encodes it to a file\n" | |
641 | "named test.h264, test.mp2 or test.mpg depending on output_type.\n" | |
642 | "The encoded stream is then decoded and written to a raw data output.\n" | |
643 | "output_type must be chosen between 'h264', 'mp2', 'mpg'.\n", | |
644 | argv[0]); | |
645 | return 1; | |
646 | } | |
647 | output_type = argv[1]; | |
648 | ||
649 | if (!strcmp(output_type, "h264")) { | |
650 | video_encode_example("test.h264", AV_CODEC_ID_H264); | |
651 | } else if (!strcmp(output_type, "mp2")) { | |
652 | audio_encode_example("test.mp2"); | |
653 | audio_decode_example("test.sw", "test.mp2"); | |
654 | } else if (!strcmp(output_type, "mpg")) { | |
655 | video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO); | |
656 | video_decode_example("test%02d.pgm", "test.mpg"); | |
657 | } else { | |
658 | fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n", | |
659 | output_type); | |
660 | return 1; | |
661 | } | |
662 | ||
663 | return 0; | |
664 | } |