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) { | |
f6fa7814 | 291 | int i, ch; |
2ba45a60 DM |
292 | int got_frame = 0; |
293 | ||
294 | if (!decoded_frame) { | |
295 | if (!(decoded_frame = av_frame_alloc())) { | |
296 | fprintf(stderr, "Could not allocate audio frame\n"); | |
297 | exit(1); | |
298 | } | |
299 | } | |
300 | ||
301 | len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); | |
302 | if (len < 0) { | |
303 | fprintf(stderr, "Error while decoding\n"); | |
304 | exit(1); | |
305 | } | |
306 | if (got_frame) { | |
307 | /* if a frame has been decoded, output it */ | |
f6fa7814 | 308 | int data_size = av_get_bytes_per_sample(c->sample_fmt); |
2ba45a60 DM |
309 | if (data_size < 0) { |
310 | /* This should not occur, checking just for paranoia */ | |
311 | fprintf(stderr, "Failed to calculate data size\n"); | |
312 | exit(1); | |
313 | } | |
f6fa7814 DM |
314 | for (i=0; i<decoded_frame->nb_samples; i++) |
315 | for (ch=0; ch<c->channels; ch++) | |
316 | fwrite(decoded_frame->data[ch] + data_size*i, 1, data_size, outfile); | |
2ba45a60 DM |
317 | } |
318 | avpkt.size -= len; | |
319 | avpkt.data += len; | |
320 | avpkt.dts = | |
321 | avpkt.pts = AV_NOPTS_VALUE; | |
322 | if (avpkt.size < AUDIO_REFILL_THRESH) { | |
323 | /* Refill the input buffer, to avoid trying to decode | |
324 | * incomplete frames. Instead of this, one could also use | |
325 | * a parser, or use a proper container format through | |
326 | * libavformat. */ | |
327 | memmove(inbuf, avpkt.data, avpkt.size); | |
328 | avpkt.data = inbuf; | |
329 | len = fread(avpkt.data + avpkt.size, 1, | |
330 | AUDIO_INBUF_SIZE - avpkt.size, f); | |
331 | if (len > 0) | |
332 | avpkt.size += len; | |
333 | } | |
334 | } | |
335 | ||
336 | fclose(outfile); | |
337 | fclose(f); | |
338 | ||
339 | avcodec_close(c); | |
340 | av_free(c); | |
341 | av_frame_free(&decoded_frame); | |
342 | } | |
343 | ||
344 | /* | |
345 | * Video encoding example | |
346 | */ | |
347 | static void video_encode_example(const char *filename, int codec_id) | |
348 | { | |
349 | AVCodec *codec; | |
350 | AVCodecContext *c= NULL; | |
351 | int i, ret, x, y, got_output; | |
352 | FILE *f; | |
353 | AVFrame *frame; | |
354 | AVPacket pkt; | |
355 | uint8_t endcode[] = { 0, 0, 1, 0xb7 }; | |
356 | ||
357 | printf("Encode video file %s\n", filename); | |
358 | ||
359 | /* find the mpeg1 video encoder */ | |
360 | codec = avcodec_find_encoder(codec_id); | |
361 | if (!codec) { | |
362 | fprintf(stderr, "Codec not found\n"); | |
363 | exit(1); | |
364 | } | |
365 | ||
366 | c = avcodec_alloc_context3(codec); | |
367 | if (!c) { | |
368 | fprintf(stderr, "Could not allocate video codec context\n"); | |
369 | exit(1); | |
370 | } | |
371 | ||
372 | /* put sample parameters */ | |
373 | c->bit_rate = 400000; | |
374 | /* resolution must be a multiple of two */ | |
375 | c->width = 352; | |
376 | c->height = 288; | |
377 | /* frames per second */ | |
378 | c->time_base = (AVRational){1,25}; | |
379 | /* emit one intra frame every ten frames | |
380 | * check frame pict_type before passing frame | |
381 | * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I | |
382 | * then gop_size is ignored and the output of encoder | |
383 | * will always be I frame irrespective to gop_size | |
384 | */ | |
385 | c->gop_size = 10; | |
386 | c->max_b_frames = 1; | |
387 | c->pix_fmt = AV_PIX_FMT_YUV420P; | |
388 | ||
389 | if (codec_id == AV_CODEC_ID_H264) | |
390 | av_opt_set(c->priv_data, "preset", "slow", 0); | |
391 | ||
392 | /* open it */ | |
393 | if (avcodec_open2(c, codec, NULL) < 0) { | |
394 | fprintf(stderr, "Could not open codec\n"); | |
395 | exit(1); | |
396 | } | |
397 | ||
398 | f = fopen(filename, "wb"); | |
399 | if (!f) { | |
400 | fprintf(stderr, "Could not open %s\n", filename); | |
401 | exit(1); | |
402 | } | |
403 | ||
404 | frame = av_frame_alloc(); | |
405 | if (!frame) { | |
406 | fprintf(stderr, "Could not allocate video frame\n"); | |
407 | exit(1); | |
408 | } | |
409 | frame->format = c->pix_fmt; | |
410 | frame->width = c->width; | |
411 | frame->height = c->height; | |
412 | ||
413 | /* the image can be allocated by any means and av_image_alloc() is | |
414 | * just the most convenient way if av_malloc() is to be used */ | |
415 | ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, | |
416 | c->pix_fmt, 32); | |
417 | if (ret < 0) { | |
418 | fprintf(stderr, "Could not allocate raw picture buffer\n"); | |
419 | exit(1); | |
420 | } | |
421 | ||
422 | /* encode 1 second of video */ | |
423 | for (i = 0; i < 25; i++) { | |
424 | av_init_packet(&pkt); | |
425 | pkt.data = NULL; // packet data will be allocated by the encoder | |
426 | pkt.size = 0; | |
427 | ||
428 | fflush(stdout); | |
429 | /* prepare a dummy image */ | |
430 | /* Y */ | |
431 | for (y = 0; y < c->height; y++) { | |
432 | for (x = 0; x < c->width; x++) { | |
433 | frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3; | |
434 | } | |
435 | } | |
436 | ||
437 | /* Cb and Cr */ | |
438 | for (y = 0; y < c->height/2; y++) { | |
439 | for (x = 0; x < c->width/2; x++) { | |
440 | frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2; | |
441 | frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5; | |
442 | } | |
443 | } | |
444 | ||
445 | frame->pts = i; | |
446 | ||
447 | /* encode the image */ | |
448 | ret = avcodec_encode_video2(c, &pkt, frame, &got_output); | |
449 | if (ret < 0) { | |
450 | fprintf(stderr, "Error encoding frame\n"); | |
451 | exit(1); | |
452 | } | |
453 | ||
454 | if (got_output) { | |
455 | printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |
456 | fwrite(pkt.data, 1, pkt.size, f); | |
457 | av_free_packet(&pkt); | |
458 | } | |
459 | } | |
460 | ||
461 | /* get the delayed frames */ | |
462 | for (got_output = 1; got_output; i++) { | |
463 | fflush(stdout); | |
464 | ||
465 | ret = avcodec_encode_video2(c, &pkt, NULL, &got_output); | |
466 | if (ret < 0) { | |
467 | fprintf(stderr, "Error encoding frame\n"); | |
468 | exit(1); | |
469 | } | |
470 | ||
471 | if (got_output) { | |
472 | printf("Write frame %3d (size=%5d)\n", i, pkt.size); | |
473 | fwrite(pkt.data, 1, pkt.size, f); | |
474 | av_free_packet(&pkt); | |
475 | } | |
476 | } | |
477 | ||
478 | /* add sequence end code to have a real mpeg file */ | |
479 | fwrite(endcode, 1, sizeof(endcode), f); | |
480 | fclose(f); | |
481 | ||
482 | avcodec_close(c); | |
483 | av_free(c); | |
484 | av_freep(&frame->data[0]); | |
485 | av_frame_free(&frame); | |
486 | printf("\n"); | |
487 | } | |
488 | ||
489 | /* | |
490 | * Video decoding example | |
491 | */ | |
492 | ||
493 | static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, | |
494 | char *filename) | |
495 | { | |
496 | FILE *f; | |
497 | int i; | |
498 | ||
499 | f = fopen(filename,"w"); | |
500 | fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255); | |
501 | for (i = 0; i < ysize; i++) | |
502 | fwrite(buf + i * wrap, 1, xsize, f); | |
503 | fclose(f); | |
504 | } | |
505 | ||
506 | static int decode_write_frame(const char *outfilename, AVCodecContext *avctx, | |
507 | AVFrame *frame, int *frame_count, AVPacket *pkt, int last) | |
508 | { | |
509 | int len, got_frame; | |
510 | char buf[1024]; | |
511 | ||
512 | len = avcodec_decode_video2(avctx, frame, &got_frame, pkt); | |
513 | if (len < 0) { | |
514 | fprintf(stderr, "Error while decoding frame %d\n", *frame_count); | |
515 | return len; | |
516 | } | |
517 | if (got_frame) { | |
518 | printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count); | |
519 | fflush(stdout); | |
520 | ||
521 | /* the picture is allocated by the decoder, no need to free it */ | |
522 | snprintf(buf, sizeof(buf), outfilename, *frame_count); | |
523 | pgm_save(frame->data[0], frame->linesize[0], | |
524 | avctx->width, avctx->height, buf); | |
525 | (*frame_count)++; | |
526 | } | |
527 | if (pkt->data) { | |
528 | pkt->size -= len; | |
529 | pkt->data += len; | |
530 | } | |
531 | return 0; | |
532 | } | |
533 | ||
534 | static void video_decode_example(const char *outfilename, const char *filename) | |
535 | { | |
536 | AVCodec *codec; | |
537 | AVCodecContext *c= NULL; | |
538 | int frame_count; | |
539 | FILE *f; | |
540 | AVFrame *frame; | |
541 | uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; | |
542 | AVPacket avpkt; | |
543 | ||
544 | av_init_packet(&avpkt); | |
545 | ||
546 | /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ | |
547 | memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); | |
548 | ||
549 | printf("Decode video file %s to %s\n", filename, outfilename); | |
550 | ||
551 | /* find the mpeg1 video decoder */ | |
552 | codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); | |
553 | if (!codec) { | |
554 | fprintf(stderr, "Codec not found\n"); | |
555 | exit(1); | |
556 | } | |
557 | ||
558 | c = avcodec_alloc_context3(codec); | |
559 | if (!c) { | |
560 | fprintf(stderr, "Could not allocate video codec context\n"); | |
561 | exit(1); | |
562 | } | |
563 | ||
564 | if(codec->capabilities&CODEC_CAP_TRUNCATED) | |
565 | c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ | |
566 | ||
567 | /* For some codecs, such as msmpeg4 and mpeg4, width and height | |
568 | MUST be initialized there because this information is not | |
569 | available in the bitstream. */ | |
570 | ||
571 | /* open it */ | |
572 | if (avcodec_open2(c, codec, NULL) < 0) { | |
573 | fprintf(stderr, "Could not open codec\n"); | |
574 | exit(1); | |
575 | } | |
576 | ||
577 | f = fopen(filename, "rb"); | |
578 | if (!f) { | |
579 | fprintf(stderr, "Could not open %s\n", filename); | |
580 | exit(1); | |
581 | } | |
582 | ||
583 | frame = av_frame_alloc(); | |
584 | if (!frame) { | |
585 | fprintf(stderr, "Could not allocate video frame\n"); | |
586 | exit(1); | |
587 | } | |
588 | ||
589 | frame_count = 0; | |
590 | for (;;) { | |
591 | avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); | |
592 | if (avpkt.size == 0) | |
593 | break; | |
594 | ||
595 | /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) | |
596 | and this is the only method to use them because you cannot | |
597 | know the compressed data size before analysing it. | |
598 | ||
599 | BUT some other codecs (msmpeg4, mpeg4) are inherently frame | |
600 | based, so you must call them with all the data for one | |
601 | frame exactly. You must also initialize 'width' and | |
602 | 'height' before initializing them. */ | |
603 | ||
604 | /* NOTE2: some codecs allow the raw parameters (frame size, | |
605 | sample rate) to be changed at any frame. We handle this, so | |
606 | you should also take care of it */ | |
607 | ||
608 | /* here, we use a stream based decoder (mpeg1video), so we | |
609 | feed decoder and see if it could decode a frame */ | |
610 | avpkt.data = inbuf; | |
611 | while (avpkt.size > 0) | |
612 | if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0) | |
613 | exit(1); | |
614 | } | |
615 | ||
616 | /* some codecs, such as MPEG, transmit the I and P frame with a | |
617 | latency of one frame. You must do the following to have a | |
618 | chance to get the last frame of the video */ | |
619 | avpkt.data = NULL; | |
620 | avpkt.size = 0; | |
621 | decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1); | |
622 | ||
623 | fclose(f); | |
624 | ||
625 | avcodec_close(c); | |
626 | av_free(c); | |
627 | av_frame_free(&frame); | |
628 | printf("\n"); | |
629 | } | |
630 | ||
631 | int main(int argc, char **argv) | |
632 | { | |
633 | const char *output_type; | |
634 | ||
635 | /* register all the codecs */ | |
636 | avcodec_register_all(); | |
637 | ||
638 | if (argc < 2) { | |
639 | printf("usage: %s output_type\n" | |
640 | "API example program to decode/encode a media stream with libavcodec.\n" | |
641 | "This program generates a synthetic stream and encodes it to a file\n" | |
642 | "named test.h264, test.mp2 or test.mpg depending on output_type.\n" | |
643 | "The encoded stream is then decoded and written to a raw data output.\n" | |
644 | "output_type must be chosen between 'h264', 'mp2', 'mpg'.\n", | |
645 | argv[0]); | |
646 | return 1; | |
647 | } | |
648 | output_type = argv[1]; | |
649 | ||
650 | if (!strcmp(output_type, "h264")) { | |
651 | video_encode_example("test.h264", AV_CODEC_ID_H264); | |
652 | } else if (!strcmp(output_type, "mp2")) { | |
653 | audio_encode_example("test.mp2"); | |
f6fa7814 | 654 | audio_decode_example("test.pcm", "test.mp2"); |
2ba45a60 DM |
655 | } else if (!strcmp(output_type, "mpg")) { |
656 | video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO); | |
657 | video_decode_example("test%02d.pgm", "test.mpg"); | |
658 | } else { | |
659 | fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n", | |
660 | output_type); | |
661 | return 1; | |
662 | } | |
663 | ||
664 | return 0; | |
665 | } |