The suffix is redundant since the containing directory itself is
called "examples". Simplify.
| ... | ... |
@@ -3,7 +3,7 @@ FFMPEG_LIBS=libavdevice libavformat libavfilter libavcodec libswscale libavutil |
| 3 | 3 |
CFLAGS+=$(shell pkg-config --cflags $(FFMPEG_LIBS)) |
| 4 | 4 |
LDFLAGS+=$(shell pkg-config --libs $(FFMPEG_LIBS)) |
| 5 | 5 |
|
| 6 |
-EXAMPLES=encoding-example muxing-example |
|
| 6 |
+EXAMPLES=encoding muxing |
|
| 7 | 7 |
|
| 8 | 8 |
OBJS=$(addsuffix .o,$(EXAMPLES)) |
| 9 | 9 |
|
| 10 | 10 |
deleted file mode 100644 |
| ... | ... |
@@ -1,468 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
- * Copyright (c) 2001 Fabrice Bellard |
|
| 3 |
- * |
|
| 4 |
- * This file is part of FFmpeg. |
|
| 5 |
- * |
|
| 6 |
- * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
- * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
- * License as published by the Free Software Foundation; either |
|
| 9 |
- * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
- * |
|
| 11 |
- * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
- * Lesser General Public License for more details. |
|
| 15 |
- * |
|
| 16 |
- * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
- * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
- */ |
|
| 20 |
- |
|
| 21 |
-/** |
|
| 22 |
- * @file |
|
| 23 |
- * libavcodec API use example. |
|
| 24 |
- * |
|
| 25 |
- * @example libavcodec/api-example.c |
|
| 26 |
- * Note that this library only handles codecs (mpeg, mpeg4, etc...), |
|
| 27 |
- * not file formats (avi, vob, etc...). See library 'libavformat' for the |
|
| 28 |
- * format handling |
|
| 29 |
- */ |
|
| 30 |
- |
|
| 31 |
-#include <stdlib.h> |
|
| 32 |
-#include <stdio.h> |
|
| 33 |
-#include <string.h> |
|
| 34 |
- |
|
| 35 |
-#ifdef HAVE_AV_CONFIG_H |
|
| 36 |
-#undef HAVE_AV_CONFIG_H |
|
| 37 |
-#endif |
|
| 38 |
- |
|
| 39 |
-#include "libavcodec/avcodec.h" |
|
| 40 |
-#include "libavutil/mathematics.h" |
|
| 41 |
- |
|
| 42 |
-#define INBUF_SIZE 4096 |
|
| 43 |
-#define AUDIO_INBUF_SIZE 20480 |
|
| 44 |
-#define AUDIO_REFILL_THRESH 4096 |
|
| 45 |
- |
|
| 46 |
-/* |
|
| 47 |
- * Audio encoding example |
|
| 48 |
- */ |
|
| 49 |
-static void audio_encode_example(const char *filename) |
|
| 50 |
-{
|
|
| 51 |
- AVCodec *codec; |
|
| 52 |
- AVCodecContext *c= NULL; |
|
| 53 |
- int frame_size, i, j, out_size, outbuf_size; |
|
| 54 |
- FILE *f; |
|
| 55 |
- short *samples; |
|
| 56 |
- float t, tincr; |
|
| 57 |
- uint8_t *outbuf; |
|
| 58 |
- |
|
| 59 |
- printf("Audio encoding\n");
|
|
| 60 |
- |
|
| 61 |
- /* find the MP2 encoder */ |
|
| 62 |
- codec = avcodec_find_encoder(CODEC_ID_MP2); |
|
| 63 |
- if (!codec) {
|
|
| 64 |
- fprintf(stderr, "codec not found\n"); |
|
| 65 |
- exit(1); |
|
| 66 |
- } |
|
| 67 |
- |
|
| 68 |
- c= avcodec_alloc_context(); |
|
| 69 |
- |
|
| 70 |
- /* put sample parameters */ |
|
| 71 |
- c->bit_rate = 64000; |
|
| 72 |
- c->sample_rate = 44100; |
|
| 73 |
- c->channels = 2; |
|
| 74 |
- |
|
| 75 |
- /* open it */ |
|
| 76 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 77 |
- fprintf(stderr, "could not open codec\n"); |
|
| 78 |
- exit(1); |
|
| 79 |
- } |
|
| 80 |
- |
|
| 81 |
- /* the codec gives us the frame size, in samples */ |
|
| 82 |
- frame_size = c->frame_size; |
|
| 83 |
- samples = malloc(frame_size * 2 * c->channels); |
|
| 84 |
- outbuf_size = 10000; |
|
| 85 |
- outbuf = malloc(outbuf_size); |
|
| 86 |
- |
|
| 87 |
- f = fopen(filename, "wb"); |
|
| 88 |
- if (!f) {
|
|
| 89 |
- fprintf(stderr, "could not open %s\n", filename); |
|
| 90 |
- exit(1); |
|
| 91 |
- } |
|
| 92 |
- |
|
| 93 |
- /* encode a single tone sound */ |
|
| 94 |
- t = 0; |
|
| 95 |
- tincr = 2 * M_PI * 440.0 / c->sample_rate; |
|
| 96 |
- for(i=0;i<200;i++) {
|
|
| 97 |
- for(j=0;j<frame_size;j++) {
|
|
| 98 |
- samples[2*j] = (int)(sin(t) * 10000); |
|
| 99 |
- samples[2*j+1] = samples[2*j]; |
|
| 100 |
- t += tincr; |
|
| 101 |
- } |
|
| 102 |
- /* encode the samples */ |
|
| 103 |
- out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples); |
|
| 104 |
- fwrite(outbuf, 1, out_size, f); |
|
| 105 |
- } |
|
| 106 |
- fclose(f); |
|
| 107 |
- free(outbuf); |
|
| 108 |
- free(samples); |
|
| 109 |
- |
|
| 110 |
- avcodec_close(c); |
|
| 111 |
- av_free(c); |
|
| 112 |
-} |
|
| 113 |
- |
|
| 114 |
-/* |
|
| 115 |
- * Audio decoding. |
|
| 116 |
- */ |
|
| 117 |
-static void audio_decode_example(const char *outfilename, const char *filename) |
|
| 118 |
-{
|
|
| 119 |
- AVCodec *codec; |
|
| 120 |
- AVCodecContext *c= NULL; |
|
| 121 |
- int out_size, len; |
|
| 122 |
- FILE *f, *outfile; |
|
| 123 |
- uint8_t *outbuf; |
|
| 124 |
- uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; |
|
| 125 |
- AVPacket avpkt; |
|
| 126 |
- |
|
| 127 |
- av_init_packet(&avpkt); |
|
| 128 |
- |
|
| 129 |
- printf("Audio decoding\n");
|
|
| 130 |
- |
|
| 131 |
- /* find the mpeg audio decoder */ |
|
| 132 |
- codec = avcodec_find_decoder(CODEC_ID_MP2); |
|
| 133 |
- if (!codec) {
|
|
| 134 |
- fprintf(stderr, "codec not found\n"); |
|
| 135 |
- exit(1); |
|
| 136 |
- } |
|
| 137 |
- |
|
| 138 |
- c= avcodec_alloc_context(); |
|
| 139 |
- |
|
| 140 |
- /* open it */ |
|
| 141 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 142 |
- fprintf(stderr, "could not open codec\n"); |
|
| 143 |
- exit(1); |
|
| 144 |
- } |
|
| 145 |
- |
|
| 146 |
- outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); |
|
| 147 |
- |
|
| 148 |
- f = fopen(filename, "rb"); |
|
| 149 |
- if (!f) {
|
|
| 150 |
- fprintf(stderr, "could not open %s\n", filename); |
|
| 151 |
- exit(1); |
|
| 152 |
- } |
|
| 153 |
- outfile = fopen(outfilename, "wb"); |
|
| 154 |
- if (!outfile) {
|
|
| 155 |
- av_free(c); |
|
| 156 |
- exit(1); |
|
| 157 |
- } |
|
| 158 |
- |
|
| 159 |
- /* decode until eof */ |
|
| 160 |
- avpkt.data = inbuf; |
|
| 161 |
- avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); |
|
| 162 |
- |
|
| 163 |
- while (avpkt.size > 0) {
|
|
| 164 |
- out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
|
| 165 |
- len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt); |
|
| 166 |
- if (len < 0) {
|
|
| 167 |
- fprintf(stderr, "Error while decoding\n"); |
|
| 168 |
- exit(1); |
|
| 169 |
- } |
|
| 170 |
- if (out_size > 0) {
|
|
| 171 |
- /* if a frame has been decoded, output it */ |
|
| 172 |
- fwrite(outbuf, 1, out_size, outfile); |
|
| 173 |
- } |
|
| 174 |
- avpkt.size -= len; |
|
| 175 |
- avpkt.data += len; |
|
| 176 |
- if (avpkt.size < AUDIO_REFILL_THRESH) {
|
|
| 177 |
- /* Refill the input buffer, to avoid trying to decode |
|
| 178 |
- * incomplete frames. Instead of this, one could also use |
|
| 179 |
- * a parser, or use a proper container format through |
|
| 180 |
- * libavformat. */ |
|
| 181 |
- memmove(inbuf, avpkt.data, avpkt.size); |
|
| 182 |
- avpkt.data = inbuf; |
|
| 183 |
- len = fread(avpkt.data + avpkt.size, 1, |
|
| 184 |
- AUDIO_INBUF_SIZE - avpkt.size, f); |
|
| 185 |
- if (len > 0) |
|
| 186 |
- avpkt.size += len; |
|
| 187 |
- } |
|
| 188 |
- } |
|
| 189 |
- |
|
| 190 |
- fclose(outfile); |
|
| 191 |
- fclose(f); |
|
| 192 |
- free(outbuf); |
|
| 193 |
- |
|
| 194 |
- avcodec_close(c); |
|
| 195 |
- av_free(c); |
|
| 196 |
-} |
|
| 197 |
- |
|
| 198 |
-/* |
|
| 199 |
- * Video encoding example |
|
| 200 |
- */ |
|
| 201 |
-static void video_encode_example(const char *filename) |
|
| 202 |
-{
|
|
| 203 |
- AVCodec *codec; |
|
| 204 |
- AVCodecContext *c= NULL; |
|
| 205 |
- int i, out_size, size, x, y, outbuf_size; |
|
| 206 |
- FILE *f; |
|
| 207 |
- AVFrame *picture; |
|
| 208 |
- uint8_t *outbuf, *picture_buf; |
|
| 209 |
- |
|
| 210 |
- printf("Video encoding\n");
|
|
| 211 |
- |
|
| 212 |
- /* find the mpeg1 video encoder */ |
|
| 213 |
- codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); |
|
| 214 |
- if (!codec) {
|
|
| 215 |
- fprintf(stderr, "codec not found\n"); |
|
| 216 |
- exit(1); |
|
| 217 |
- } |
|
| 218 |
- |
|
| 219 |
- c= avcodec_alloc_context(); |
|
| 220 |
- picture= avcodec_alloc_frame(); |
|
| 221 |
- |
|
| 222 |
- /* put sample parameters */ |
|
| 223 |
- c->bit_rate = 400000; |
|
| 224 |
- /* resolution must be a multiple of two */ |
|
| 225 |
- c->width = 352; |
|
| 226 |
- c->height = 288; |
|
| 227 |
- /* frames per second */ |
|
| 228 |
- c->time_base= (AVRational){1,25};
|
|
| 229 |
- c->gop_size = 10; /* emit one intra frame every ten frames */ |
|
| 230 |
- c->max_b_frames=1; |
|
| 231 |
- c->pix_fmt = PIX_FMT_YUV420P; |
|
| 232 |
- |
|
| 233 |
- /* open it */ |
|
| 234 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 235 |
- fprintf(stderr, "could not open codec\n"); |
|
| 236 |
- exit(1); |
|
| 237 |
- } |
|
| 238 |
- |
|
| 239 |
- f = fopen(filename, "wb"); |
|
| 240 |
- if (!f) {
|
|
| 241 |
- fprintf(stderr, "could not open %s\n", filename); |
|
| 242 |
- exit(1); |
|
| 243 |
- } |
|
| 244 |
- |
|
| 245 |
- /* alloc image and output buffer */ |
|
| 246 |
- outbuf_size = 100000; |
|
| 247 |
- outbuf = malloc(outbuf_size); |
|
| 248 |
- size = c->width * c->height; |
|
| 249 |
- picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */ |
|
| 250 |
- |
|
| 251 |
- picture->data[0] = picture_buf; |
|
| 252 |
- picture->data[1] = picture->data[0] + size; |
|
| 253 |
- picture->data[2] = picture->data[1] + size / 4; |
|
| 254 |
- picture->linesize[0] = c->width; |
|
| 255 |
- picture->linesize[1] = c->width / 2; |
|
| 256 |
- picture->linesize[2] = c->width / 2; |
|
| 257 |
- |
|
| 258 |
- /* encode 1 second of video */ |
|
| 259 |
- for(i=0;i<25;i++) {
|
|
| 260 |
- fflush(stdout); |
|
| 261 |
- /* prepare a dummy image */ |
|
| 262 |
- /* Y */ |
|
| 263 |
- for(y=0;y<c->height;y++) {
|
|
| 264 |
- for(x=0;x<c->width;x++) {
|
|
| 265 |
- picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; |
|
| 266 |
- } |
|
| 267 |
- } |
|
| 268 |
- |
|
| 269 |
- /* Cb and Cr */ |
|
| 270 |
- for(y=0;y<c->height/2;y++) {
|
|
| 271 |
- for(x=0;x<c->width/2;x++) {
|
|
| 272 |
- picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; |
|
| 273 |
- picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; |
|
| 274 |
- } |
|
| 275 |
- } |
|
| 276 |
- |
|
| 277 |
- /* encode the image */ |
|
| 278 |
- out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); |
|
| 279 |
- printf("encoding frame %3d (size=%5d)\n", i, out_size);
|
|
| 280 |
- fwrite(outbuf, 1, out_size, f); |
|
| 281 |
- } |
|
| 282 |
- |
|
| 283 |
- /* get the delayed frames */ |
|
| 284 |
- for(; out_size; i++) {
|
|
| 285 |
- fflush(stdout); |
|
| 286 |
- |
|
| 287 |
- out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); |
|
| 288 |
- printf("write frame %3d (size=%5d)\n", i, out_size);
|
|
| 289 |
- fwrite(outbuf, 1, out_size, f); |
|
| 290 |
- } |
|
| 291 |
- |
|
| 292 |
- /* add sequence end code to have a real mpeg file */ |
|
| 293 |
- outbuf[0] = 0x00; |
|
| 294 |
- outbuf[1] = 0x00; |
|
| 295 |
- outbuf[2] = 0x01; |
|
| 296 |
- outbuf[3] = 0xb7; |
|
| 297 |
- fwrite(outbuf, 1, 4, f); |
|
| 298 |
- fclose(f); |
|
| 299 |
- free(picture_buf); |
|
| 300 |
- free(outbuf); |
|
| 301 |
- |
|
| 302 |
- avcodec_close(c); |
|
| 303 |
- av_free(c); |
|
| 304 |
- av_free(picture); |
|
| 305 |
- printf("\n");
|
|
| 306 |
-} |
|
| 307 |
- |
|
| 308 |
-/* |
|
| 309 |
- * Video decoding example |
|
| 310 |
- */ |
|
| 311 |
- |
|
| 312 |
-static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, |
|
| 313 |
- char *filename) |
|
| 314 |
-{
|
|
| 315 |
- FILE *f; |
|
| 316 |
- int i; |
|
| 317 |
- |
|
| 318 |
- f=fopen(filename,"w"); |
|
| 319 |
- fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255); |
|
| 320 |
- for(i=0;i<ysize;i++) |
|
| 321 |
- fwrite(buf + i * wrap,1,xsize,f); |
|
| 322 |
- fclose(f); |
|
| 323 |
-} |
|
| 324 |
- |
|
| 325 |
-static void video_decode_example(const char *outfilename, const char *filename) |
|
| 326 |
-{
|
|
| 327 |
- AVCodec *codec; |
|
| 328 |
- AVCodecContext *c= NULL; |
|
| 329 |
- int frame, got_picture, len; |
|
| 330 |
- FILE *f; |
|
| 331 |
- AVFrame *picture; |
|
| 332 |
- uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; |
|
| 333 |
- char buf[1024]; |
|
| 334 |
- AVPacket avpkt; |
|
| 335 |
- |
|
| 336 |
- av_init_packet(&avpkt); |
|
| 337 |
- |
|
| 338 |
- /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ |
|
| 339 |
- memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
|
| 340 |
- |
|
| 341 |
- printf("Video decoding\n");
|
|
| 342 |
- |
|
| 343 |
- /* find the mpeg1 video decoder */ |
|
| 344 |
- codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); |
|
| 345 |
- if (!codec) {
|
|
| 346 |
- fprintf(stderr, "codec not found\n"); |
|
| 347 |
- exit(1); |
|
| 348 |
- } |
|
| 349 |
- |
|
| 350 |
- c= avcodec_alloc_context(); |
|
| 351 |
- picture= avcodec_alloc_frame(); |
|
| 352 |
- |
|
| 353 |
- if(codec->capabilities&CODEC_CAP_TRUNCATED) |
|
| 354 |
- c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ |
|
| 355 |
- |
|
| 356 |
- /* For some codecs, such as msmpeg4 and mpeg4, width and height |
|
| 357 |
- MUST be initialized there because this information is not |
|
| 358 |
- available in the bitstream. */ |
|
| 359 |
- |
|
| 360 |
- /* open it */ |
|
| 361 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 362 |
- fprintf(stderr, "could not open codec\n"); |
|
| 363 |
- exit(1); |
|
| 364 |
- } |
|
| 365 |
- |
|
| 366 |
- /* the codec gives us the frame size, in samples */ |
|
| 367 |
- |
|
| 368 |
- f = fopen(filename, "rb"); |
|
| 369 |
- if (!f) {
|
|
| 370 |
- fprintf(stderr, "could not open %s\n", filename); |
|
| 371 |
- exit(1); |
|
| 372 |
- } |
|
| 373 |
- |
|
| 374 |
- frame = 0; |
|
| 375 |
- for(;;) {
|
|
| 376 |
- avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); |
|
| 377 |
- if (avpkt.size == 0) |
|
| 378 |
- break; |
|
| 379 |
- |
|
| 380 |
- /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) |
|
| 381 |
- and this is the only method to use them because you cannot |
|
| 382 |
- know the compressed data size before analysing it. |
|
| 383 |
- |
|
| 384 |
- BUT some other codecs (msmpeg4, mpeg4) are inherently frame |
|
| 385 |
- based, so you must call them with all the data for one |
|
| 386 |
- frame exactly. You must also initialize 'width' and |
|
| 387 |
- 'height' before initializing them. */ |
|
| 388 |
- |
|
| 389 |
- /* NOTE2: some codecs allow the raw parameters (frame size, |
|
| 390 |
- sample rate) to be changed at any frame. We handle this, so |
|
| 391 |
- you should also take care of it */ |
|
| 392 |
- |
|
| 393 |
- /* here, we use a stream based decoder (mpeg1video), so we |
|
| 394 |
- feed decoder and see if it could decode a frame */ |
|
| 395 |
- avpkt.data = inbuf; |
|
| 396 |
- while (avpkt.size > 0) {
|
|
| 397 |
- len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); |
|
| 398 |
- if (len < 0) {
|
|
| 399 |
- fprintf(stderr, "Error while decoding frame %d\n", frame); |
|
| 400 |
- exit(1); |
|
| 401 |
- } |
|
| 402 |
- if (got_picture) {
|
|
| 403 |
- printf("saving frame %3d\n", frame);
|
|
| 404 |
- fflush(stdout); |
|
| 405 |
- |
|
| 406 |
- /* the picture is allocated by the decoder. no need to |
|
| 407 |
- free it */ |
|
| 408 |
- snprintf(buf, sizeof(buf), outfilename, frame); |
|
| 409 |
- pgm_save(picture->data[0], picture->linesize[0], |
|
| 410 |
- c->width, c->height, buf); |
|
| 411 |
- frame++; |
|
| 412 |
- } |
|
| 413 |
- avpkt.size -= len; |
|
| 414 |
- avpkt.data += len; |
|
| 415 |
- } |
|
| 416 |
- } |
|
| 417 |
- |
|
| 418 |
- /* some codecs, such as MPEG, transmit the I and P frame with a |
|
| 419 |
- latency of one frame. You must do the following to have a |
|
| 420 |
- chance to get the last frame of the video */ |
|
| 421 |
- avpkt.data = NULL; |
|
| 422 |
- avpkt.size = 0; |
|
| 423 |
- len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); |
|
| 424 |
- if (got_picture) {
|
|
| 425 |
- printf("saving last frame %3d\n", frame);
|
|
| 426 |
- fflush(stdout); |
|
| 427 |
- |
|
| 428 |
- /* the picture is allocated by the decoder. no need to |
|
| 429 |
- free it */ |
|
| 430 |
- snprintf(buf, sizeof(buf), outfilename, frame); |
|
| 431 |
- pgm_save(picture->data[0], picture->linesize[0], |
|
| 432 |
- c->width, c->height, buf); |
|
| 433 |
- frame++; |
|
| 434 |
- } |
|
| 435 |
- |
|
| 436 |
- fclose(f); |
|
| 437 |
- |
|
| 438 |
- avcodec_close(c); |
|
| 439 |
- av_free(c); |
|
| 440 |
- av_free(picture); |
|
| 441 |
- printf("\n");
|
|
| 442 |
-} |
|
| 443 |
- |
|
| 444 |
-int main(int argc, char **argv) |
|
| 445 |
-{
|
|
| 446 |
- const char *filename; |
|
| 447 |
- |
|
| 448 |
- /* must be called before using avcodec lib */ |
|
| 449 |
- avcodec_init(); |
|
| 450 |
- |
|
| 451 |
- /* register all the codecs */ |
|
| 452 |
- avcodec_register_all(); |
|
| 453 |
- |
|
| 454 |
- if (argc <= 1) {
|
|
| 455 |
- audio_encode_example("/tmp/test.mp2");
|
|
| 456 |
- audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
|
|
| 457 |
- |
|
| 458 |
- video_encode_example("/tmp/test.mpg");
|
|
| 459 |
- filename = "/tmp/test.mpg"; |
|
| 460 |
- } else {
|
|
| 461 |
- filename = argv[1]; |
|
| 462 |
- } |
|
| 463 |
- |
|
| 464 |
- // audio_decode_example("/tmp/test.sw", filename);
|
|
| 465 |
- video_decode_example("/tmp/test%d.pgm", filename);
|
|
| 466 |
- |
|
| 467 |
- return 0; |
|
| 468 |
-} |
| 469 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,468 @@ |
| 0 |
+/* |
|
| 1 |
+ * Copyright (c) 2001 Fabrice Bellard |
|
| 2 |
+ * |
|
| 3 |
+ * This file is part of FFmpeg. |
|
| 4 |
+ * |
|
| 5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 7 |
+ * License as published by the Free Software Foundation; either |
|
| 8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 9 |
+ * |
|
| 10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 13 |
+ * Lesser General Public License for more details. |
|
| 14 |
+ * |
|
| 15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 18 |
+ */ |
|
| 19 |
+ |
|
| 20 |
+/** |
|
| 21 |
+ * @file |
|
| 22 |
+ * libavcodec API use example. |
|
| 23 |
+ * |
|
| 24 |
+ * @example libavcodec/api-example.c |
|
| 25 |
+ * Note that this library only handles codecs (mpeg, mpeg4, etc...), |
|
| 26 |
+ * not file formats (avi, vob, etc...). See library 'libavformat' for the |
|
| 27 |
+ * format handling |
|
| 28 |
+ */ |
|
| 29 |
+ |
|
| 30 |
+#include <stdlib.h> |
|
| 31 |
+#include <stdio.h> |
|
| 32 |
+#include <string.h> |
|
| 33 |
+ |
|
| 34 |
+#ifdef HAVE_AV_CONFIG_H |
|
| 35 |
+#undef HAVE_AV_CONFIG_H |
|
| 36 |
+#endif |
|
| 37 |
+ |
|
| 38 |
+#include "libavcodec/avcodec.h" |
|
| 39 |
+#include "libavutil/mathematics.h" |
|
| 40 |
+ |
|
| 41 |
+#define INBUF_SIZE 4096 |
|
| 42 |
+#define AUDIO_INBUF_SIZE 20480 |
|
| 43 |
+#define AUDIO_REFILL_THRESH 4096 |
|
| 44 |
+ |
|
| 45 |
+/* |
|
| 46 |
+ * Audio encoding example |
|
| 47 |
+ */ |
|
| 48 |
+static void audio_encode_example(const char *filename) |
|
| 49 |
+{
|
|
| 50 |
+ AVCodec *codec; |
|
| 51 |
+ AVCodecContext *c= NULL; |
|
| 52 |
+ int frame_size, i, j, out_size, outbuf_size; |
|
| 53 |
+ FILE *f; |
|
| 54 |
+ short *samples; |
|
| 55 |
+ float t, tincr; |
|
| 56 |
+ uint8_t *outbuf; |
|
| 57 |
+ |
|
| 58 |
+ printf("Audio encoding\n");
|
|
| 59 |
+ |
|
| 60 |
+ /* find the MP2 encoder */ |
|
| 61 |
+ codec = avcodec_find_encoder(CODEC_ID_MP2); |
|
| 62 |
+ if (!codec) {
|
|
| 63 |
+ fprintf(stderr, "codec not found\n"); |
|
| 64 |
+ exit(1); |
|
| 65 |
+ } |
|
| 66 |
+ |
|
| 67 |
+ c= avcodec_alloc_context(); |
|
| 68 |
+ |
|
| 69 |
+ /* put sample parameters */ |
|
| 70 |
+ c->bit_rate = 64000; |
|
| 71 |
+ c->sample_rate = 44100; |
|
| 72 |
+ c->channels = 2; |
|
| 73 |
+ |
|
| 74 |
+ /* open it */ |
|
| 75 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 76 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 77 |
+ exit(1); |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ /* the codec gives us the frame size, in samples */ |
|
| 81 |
+ frame_size = c->frame_size; |
|
| 82 |
+ samples = malloc(frame_size * 2 * c->channels); |
|
| 83 |
+ outbuf_size = 10000; |
|
| 84 |
+ outbuf = malloc(outbuf_size); |
|
| 85 |
+ |
|
| 86 |
+ f = fopen(filename, "wb"); |
|
| 87 |
+ if (!f) {
|
|
| 88 |
+ fprintf(stderr, "could not open %s\n", filename); |
|
| 89 |
+ exit(1); |
|
| 90 |
+ } |
|
| 91 |
+ |
|
| 92 |
+ /* encode a single tone sound */ |
|
| 93 |
+ t = 0; |
|
| 94 |
+ tincr = 2 * M_PI * 440.0 / c->sample_rate; |
|
| 95 |
+ for(i=0;i<200;i++) {
|
|
| 96 |
+ for(j=0;j<frame_size;j++) {
|
|
| 97 |
+ samples[2*j] = (int)(sin(t) * 10000); |
|
| 98 |
+ samples[2*j+1] = samples[2*j]; |
|
| 99 |
+ t += tincr; |
|
| 100 |
+ } |
|
| 101 |
+ /* encode the samples */ |
|
| 102 |
+ out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples); |
|
| 103 |
+ fwrite(outbuf, 1, out_size, f); |
|
| 104 |
+ } |
|
| 105 |
+ fclose(f); |
|
| 106 |
+ free(outbuf); |
|
| 107 |
+ free(samples); |
|
| 108 |
+ |
|
| 109 |
+ avcodec_close(c); |
|
| 110 |
+ av_free(c); |
|
| 111 |
+} |
|
| 112 |
+ |
|
| 113 |
+/* |
|
| 114 |
+ * Audio decoding. |
|
| 115 |
+ */ |
|
| 116 |
+static void audio_decode_example(const char *outfilename, const char *filename) |
|
| 117 |
+{
|
|
| 118 |
+ AVCodec *codec; |
|
| 119 |
+ AVCodecContext *c= NULL; |
|
| 120 |
+ int out_size, len; |
|
| 121 |
+ FILE *f, *outfile; |
|
| 122 |
+ uint8_t *outbuf; |
|
| 123 |
+ uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; |
|
| 124 |
+ AVPacket avpkt; |
|
| 125 |
+ |
|
| 126 |
+ av_init_packet(&avpkt); |
|
| 127 |
+ |
|
| 128 |
+ printf("Audio decoding\n");
|
|
| 129 |
+ |
|
| 130 |
+ /* find the mpeg audio decoder */ |
|
| 131 |
+ codec = avcodec_find_decoder(CODEC_ID_MP2); |
|
| 132 |
+ if (!codec) {
|
|
| 133 |
+ fprintf(stderr, "codec not found\n"); |
|
| 134 |
+ exit(1); |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ c= avcodec_alloc_context(); |
|
| 138 |
+ |
|
| 139 |
+ /* open it */ |
|
| 140 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 141 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 142 |
+ exit(1); |
|
| 143 |
+ } |
|
| 144 |
+ |
|
| 145 |
+ outbuf = malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); |
|
| 146 |
+ |
|
| 147 |
+ f = fopen(filename, "rb"); |
|
| 148 |
+ if (!f) {
|
|
| 149 |
+ fprintf(stderr, "could not open %s\n", filename); |
|
| 150 |
+ exit(1); |
|
| 151 |
+ } |
|
| 152 |
+ outfile = fopen(outfilename, "wb"); |
|
| 153 |
+ if (!outfile) {
|
|
| 154 |
+ av_free(c); |
|
| 155 |
+ exit(1); |
|
| 156 |
+ } |
|
| 157 |
+ |
|
| 158 |
+ /* decode until eof */ |
|
| 159 |
+ avpkt.data = inbuf; |
|
| 160 |
+ avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); |
|
| 161 |
+ |
|
| 162 |
+ while (avpkt.size > 0) {
|
|
| 163 |
+ out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; |
|
| 164 |
+ len = avcodec_decode_audio3(c, (short *)outbuf, &out_size, &avpkt); |
|
| 165 |
+ if (len < 0) {
|
|
| 166 |
+ fprintf(stderr, "Error while decoding\n"); |
|
| 167 |
+ exit(1); |
|
| 168 |
+ } |
|
| 169 |
+ if (out_size > 0) {
|
|
| 170 |
+ /* if a frame has been decoded, output it */ |
|
| 171 |
+ fwrite(outbuf, 1, out_size, outfile); |
|
| 172 |
+ } |
|
| 173 |
+ avpkt.size -= len; |
|
| 174 |
+ avpkt.data += len; |
|
| 175 |
+ if (avpkt.size < AUDIO_REFILL_THRESH) {
|
|
| 176 |
+ /* Refill the input buffer, to avoid trying to decode |
|
| 177 |
+ * incomplete frames. Instead of this, one could also use |
|
| 178 |
+ * a parser, or use a proper container format through |
|
| 179 |
+ * libavformat. */ |
|
| 180 |
+ memmove(inbuf, avpkt.data, avpkt.size); |
|
| 181 |
+ avpkt.data = inbuf; |
|
| 182 |
+ len = fread(avpkt.data + avpkt.size, 1, |
|
| 183 |
+ AUDIO_INBUF_SIZE - avpkt.size, f); |
|
| 184 |
+ if (len > 0) |
|
| 185 |
+ avpkt.size += len; |
|
| 186 |
+ } |
|
| 187 |
+ } |
|
| 188 |
+ |
|
| 189 |
+ fclose(outfile); |
|
| 190 |
+ fclose(f); |
|
| 191 |
+ free(outbuf); |
|
| 192 |
+ |
|
| 193 |
+ avcodec_close(c); |
|
| 194 |
+ av_free(c); |
|
| 195 |
+} |
|
| 196 |
+ |
|
| 197 |
+/* |
|
| 198 |
+ * Video encoding example |
|
| 199 |
+ */ |
|
| 200 |
+static void video_encode_example(const char *filename) |
|
| 201 |
+{
|
|
| 202 |
+ AVCodec *codec; |
|
| 203 |
+ AVCodecContext *c= NULL; |
|
| 204 |
+ int i, out_size, size, x, y, outbuf_size; |
|
| 205 |
+ FILE *f; |
|
| 206 |
+ AVFrame *picture; |
|
| 207 |
+ uint8_t *outbuf, *picture_buf; |
|
| 208 |
+ |
|
| 209 |
+ printf("Video encoding\n");
|
|
| 210 |
+ |
|
| 211 |
+ /* find the mpeg1 video encoder */ |
|
| 212 |
+ codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO); |
|
| 213 |
+ if (!codec) {
|
|
| 214 |
+ fprintf(stderr, "codec not found\n"); |
|
| 215 |
+ exit(1); |
|
| 216 |
+ } |
|
| 217 |
+ |
|
| 218 |
+ c= avcodec_alloc_context(); |
|
| 219 |
+ picture= avcodec_alloc_frame(); |
|
| 220 |
+ |
|
| 221 |
+ /* put sample parameters */ |
|
| 222 |
+ c->bit_rate = 400000; |
|
| 223 |
+ /* resolution must be a multiple of two */ |
|
| 224 |
+ c->width = 352; |
|
| 225 |
+ c->height = 288; |
|
| 226 |
+ /* frames per second */ |
|
| 227 |
+ c->time_base= (AVRational){1,25};
|
|
| 228 |
+ c->gop_size = 10; /* emit one intra frame every ten frames */ |
|
| 229 |
+ c->max_b_frames=1; |
|
| 230 |
+ c->pix_fmt = PIX_FMT_YUV420P; |
|
| 231 |
+ |
|
| 232 |
+ /* open it */ |
|
| 233 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 234 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 235 |
+ exit(1); |
|
| 236 |
+ } |
|
| 237 |
+ |
|
| 238 |
+ f = fopen(filename, "wb"); |
|
| 239 |
+ if (!f) {
|
|
| 240 |
+ fprintf(stderr, "could not open %s\n", filename); |
|
| 241 |
+ exit(1); |
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ /* alloc image and output buffer */ |
|
| 245 |
+ outbuf_size = 100000; |
|
| 246 |
+ outbuf = malloc(outbuf_size); |
|
| 247 |
+ size = c->width * c->height; |
|
| 248 |
+ picture_buf = malloc((size * 3) / 2); /* size for YUV 420 */ |
|
| 249 |
+ |
|
| 250 |
+ picture->data[0] = picture_buf; |
|
| 251 |
+ picture->data[1] = picture->data[0] + size; |
|
| 252 |
+ picture->data[2] = picture->data[1] + size / 4; |
|
| 253 |
+ picture->linesize[0] = c->width; |
|
| 254 |
+ picture->linesize[1] = c->width / 2; |
|
| 255 |
+ picture->linesize[2] = c->width / 2; |
|
| 256 |
+ |
|
| 257 |
+ /* encode 1 second of video */ |
|
| 258 |
+ for(i=0;i<25;i++) {
|
|
| 259 |
+ fflush(stdout); |
|
| 260 |
+ /* prepare a dummy image */ |
|
| 261 |
+ /* Y */ |
|
| 262 |
+ for(y=0;y<c->height;y++) {
|
|
| 263 |
+ for(x=0;x<c->width;x++) {
|
|
| 264 |
+ picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; |
|
| 265 |
+ } |
|
| 266 |
+ } |
|
| 267 |
+ |
|
| 268 |
+ /* Cb and Cr */ |
|
| 269 |
+ for(y=0;y<c->height/2;y++) {
|
|
| 270 |
+ for(x=0;x<c->width/2;x++) {
|
|
| 271 |
+ picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; |
|
| 272 |
+ picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; |
|
| 273 |
+ } |
|
| 274 |
+ } |
|
| 275 |
+ |
|
| 276 |
+ /* encode the image */ |
|
| 277 |
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); |
|
| 278 |
+ printf("encoding frame %3d (size=%5d)\n", i, out_size);
|
|
| 279 |
+ fwrite(outbuf, 1, out_size, f); |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ /* get the delayed frames */ |
|
| 283 |
+ for(; out_size; i++) {
|
|
| 284 |
+ fflush(stdout); |
|
| 285 |
+ |
|
| 286 |
+ out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); |
|
| 287 |
+ printf("write frame %3d (size=%5d)\n", i, out_size);
|
|
| 288 |
+ fwrite(outbuf, 1, out_size, f); |
|
| 289 |
+ } |
|
| 290 |
+ |
|
| 291 |
+ /* add sequence end code to have a real mpeg file */ |
|
| 292 |
+ outbuf[0] = 0x00; |
|
| 293 |
+ outbuf[1] = 0x00; |
|
| 294 |
+ outbuf[2] = 0x01; |
|
| 295 |
+ outbuf[3] = 0xb7; |
|
| 296 |
+ fwrite(outbuf, 1, 4, f); |
|
| 297 |
+ fclose(f); |
|
| 298 |
+ free(picture_buf); |
|
| 299 |
+ free(outbuf); |
|
| 300 |
+ |
|
| 301 |
+ avcodec_close(c); |
|
| 302 |
+ av_free(c); |
|
| 303 |
+ av_free(picture); |
|
| 304 |
+ printf("\n");
|
|
| 305 |
+} |
|
| 306 |
+ |
|
| 307 |
+/* |
|
| 308 |
+ * Video decoding example |
|
| 309 |
+ */ |
|
| 310 |
+ |
|
| 311 |
+static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, |
|
| 312 |
+ char *filename) |
|
| 313 |
+{
|
|
| 314 |
+ FILE *f; |
|
| 315 |
+ int i; |
|
| 316 |
+ |
|
| 317 |
+ f=fopen(filename,"w"); |
|
| 318 |
+ fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255); |
|
| 319 |
+ for(i=0;i<ysize;i++) |
|
| 320 |
+ fwrite(buf + i * wrap,1,xsize,f); |
|
| 321 |
+ fclose(f); |
|
| 322 |
+} |
|
| 323 |
+ |
|
| 324 |
+static void video_decode_example(const char *outfilename, const char *filename) |
|
| 325 |
+{
|
|
| 326 |
+ AVCodec *codec; |
|
| 327 |
+ AVCodecContext *c= NULL; |
|
| 328 |
+ int frame, got_picture, len; |
|
| 329 |
+ FILE *f; |
|
| 330 |
+ AVFrame *picture; |
|
| 331 |
+ uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; |
|
| 332 |
+ char buf[1024]; |
|
| 333 |
+ AVPacket avpkt; |
|
| 334 |
+ |
|
| 335 |
+ av_init_packet(&avpkt); |
|
| 336 |
+ |
|
| 337 |
+ /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ |
|
| 338 |
+ memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
|
| 339 |
+ |
|
| 340 |
+ printf("Video decoding\n");
|
|
| 341 |
+ |
|
| 342 |
+ /* find the mpeg1 video decoder */ |
|
| 343 |
+ codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); |
|
| 344 |
+ if (!codec) {
|
|
| 345 |
+ fprintf(stderr, "codec not found\n"); |
|
| 346 |
+ exit(1); |
|
| 347 |
+ } |
|
| 348 |
+ |
|
| 349 |
+ c= avcodec_alloc_context(); |
|
| 350 |
+ picture= avcodec_alloc_frame(); |
|
| 351 |
+ |
|
| 352 |
+ if(codec->capabilities&CODEC_CAP_TRUNCATED) |
|
| 353 |
+ c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ |
|
| 354 |
+ |
|
| 355 |
+ /* For some codecs, such as msmpeg4 and mpeg4, width and height |
|
| 356 |
+ MUST be initialized there because this information is not |
|
| 357 |
+ available in the bitstream. */ |
|
| 358 |
+ |
|
| 359 |
+ /* open it */ |
|
| 360 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 361 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 362 |
+ exit(1); |
|
| 363 |
+ } |
|
| 364 |
+ |
|
| 365 |
+ /* the codec gives us the frame size, in samples */ |
|
| 366 |
+ |
|
| 367 |
+ f = fopen(filename, "rb"); |
|
| 368 |
+ if (!f) {
|
|
| 369 |
+ fprintf(stderr, "could not open %s\n", filename); |
|
| 370 |
+ exit(1); |
|
| 371 |
+ } |
|
| 372 |
+ |
|
| 373 |
+ frame = 0; |
|
| 374 |
+ for(;;) {
|
|
| 375 |
+ avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); |
|
| 376 |
+ if (avpkt.size == 0) |
|
| 377 |
+ break; |
|
| 378 |
+ |
|
| 379 |
+ /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) |
|
| 380 |
+ and this is the only method to use them because you cannot |
|
| 381 |
+ know the compressed data size before analysing it. |
|
| 382 |
+ |
|
| 383 |
+ BUT some other codecs (msmpeg4, mpeg4) are inherently frame |
|
| 384 |
+ based, so you must call them with all the data for one |
|
| 385 |
+ frame exactly. You must also initialize 'width' and |
|
| 386 |
+ 'height' before initializing them. */ |
|
| 387 |
+ |
|
| 388 |
+ /* NOTE2: some codecs allow the raw parameters (frame size, |
|
| 389 |
+ sample rate) to be changed at any frame. We handle this, so |
|
| 390 |
+ you should also take care of it */ |
|
| 391 |
+ |
|
| 392 |
+ /* here, we use a stream based decoder (mpeg1video), so we |
|
| 393 |
+ feed decoder and see if it could decode a frame */ |
|
| 394 |
+ avpkt.data = inbuf; |
|
| 395 |
+ while (avpkt.size > 0) {
|
|
| 396 |
+ len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); |
|
| 397 |
+ if (len < 0) {
|
|
| 398 |
+ fprintf(stderr, "Error while decoding frame %d\n", frame); |
|
| 399 |
+ exit(1); |
|
| 400 |
+ } |
|
| 401 |
+ if (got_picture) {
|
|
| 402 |
+ printf("saving frame %3d\n", frame);
|
|
| 403 |
+ fflush(stdout); |
|
| 404 |
+ |
|
| 405 |
+ /* the picture is allocated by the decoder. no need to |
|
| 406 |
+ free it */ |
|
| 407 |
+ snprintf(buf, sizeof(buf), outfilename, frame); |
|
| 408 |
+ pgm_save(picture->data[0], picture->linesize[0], |
|
| 409 |
+ c->width, c->height, buf); |
|
| 410 |
+ frame++; |
|
| 411 |
+ } |
|
| 412 |
+ avpkt.size -= len; |
|
| 413 |
+ avpkt.data += len; |
|
| 414 |
+ } |
|
| 415 |
+ } |
|
| 416 |
+ |
|
| 417 |
+ /* some codecs, such as MPEG, transmit the I and P frame with a |
|
| 418 |
+ latency of one frame. You must do the following to have a |
|
| 419 |
+ chance to get the last frame of the video */ |
|
| 420 |
+ avpkt.data = NULL; |
|
| 421 |
+ avpkt.size = 0; |
|
| 422 |
+ len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); |
|
| 423 |
+ if (got_picture) {
|
|
| 424 |
+ printf("saving last frame %3d\n", frame);
|
|
| 425 |
+ fflush(stdout); |
|
| 426 |
+ |
|
| 427 |
+ /* the picture is allocated by the decoder. no need to |
|
| 428 |
+ free it */ |
|
| 429 |
+ snprintf(buf, sizeof(buf), outfilename, frame); |
|
| 430 |
+ pgm_save(picture->data[0], picture->linesize[0], |
|
| 431 |
+ c->width, c->height, buf); |
|
| 432 |
+ frame++; |
|
| 433 |
+ } |
|
| 434 |
+ |
|
| 435 |
+ fclose(f); |
|
| 436 |
+ |
|
| 437 |
+ avcodec_close(c); |
|
| 438 |
+ av_free(c); |
|
| 439 |
+ av_free(picture); |
|
| 440 |
+ printf("\n");
|
|
| 441 |
+} |
|
| 442 |
+ |
|
| 443 |
+int main(int argc, char **argv) |
|
| 444 |
+{
|
|
| 445 |
+ const char *filename; |
|
| 446 |
+ |
|
| 447 |
+ /* must be called before using avcodec lib */ |
|
| 448 |
+ avcodec_init(); |
|
| 449 |
+ |
|
| 450 |
+ /* register all the codecs */ |
|
| 451 |
+ avcodec_register_all(); |
|
| 452 |
+ |
|
| 453 |
+ if (argc <= 1) {
|
|
| 454 |
+ audio_encode_example("/tmp/test.mp2");
|
|
| 455 |
+ audio_decode_example("/tmp/test.sw", "/tmp/test.mp2");
|
|
| 456 |
+ |
|
| 457 |
+ video_encode_example("/tmp/test.mpg");
|
|
| 458 |
+ filename = "/tmp/test.mpg"; |
|
| 459 |
+ } else {
|
|
| 460 |
+ filename = argv[1]; |
|
| 461 |
+ } |
|
| 462 |
+ |
|
| 463 |
+ // audio_decode_example("/tmp/test.sw", filename);
|
|
| 464 |
+ video_decode_example("/tmp/test%d.pgm", filename);
|
|
| 465 |
+ |
|
| 466 |
+ return 0; |
|
| 467 |
+} |
| 0 | 468 |
deleted file mode 100644 |
| ... | ... |
@@ -1,546 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
- * Copyright (c) 2003 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 |
- * libavformat API example. |
|
| 26 |
- * |
|
| 27 |
- * @example libavformat/output-example.c |
|
| 28 |
- * Output a media file in any supported libavformat format. |
|
| 29 |
- * The default codecs are used. |
|
| 30 |
- */ |
|
| 31 |
- |
|
| 32 |
-#include <stdlib.h> |
|
| 33 |
-#include <stdio.h> |
|
| 34 |
-#include <string.h> |
|
| 35 |
-#include <math.h> |
|
| 36 |
- |
|
| 37 |
-#include "libavutil/mathematics.h" |
|
| 38 |
-#include "libavformat/avformat.h" |
|
| 39 |
-#include "libswscale/swscale.h" |
|
| 40 |
- |
|
| 41 |
-#undef exit |
|
| 42 |
- |
|
| 43 |
-/* 5 seconds stream duration */ |
|
| 44 |
-#define STREAM_DURATION 5.0 |
|
| 45 |
-#define STREAM_FRAME_RATE 25 /* 25 images/s */ |
|
| 46 |
-#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE)) |
|
| 47 |
-#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */ |
|
| 48 |
- |
|
| 49 |
-static int sws_flags = SWS_BICUBIC; |
|
| 50 |
- |
|
| 51 |
-/**************************************************************/ |
|
| 52 |
-/* audio output */ |
|
| 53 |
- |
|
| 54 |
-float t, tincr, tincr2; |
|
| 55 |
-int16_t *samples; |
|
| 56 |
-uint8_t *audio_outbuf; |
|
| 57 |
-int audio_outbuf_size; |
|
| 58 |
-int audio_input_frame_size; |
|
| 59 |
- |
|
| 60 |
-/* |
|
| 61 |
- * add an audio output stream |
|
| 62 |
- */ |
|
| 63 |
-static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) |
|
| 64 |
-{
|
|
| 65 |
- AVCodecContext *c; |
|
| 66 |
- AVStream *st; |
|
| 67 |
- |
|
| 68 |
- st = av_new_stream(oc, 1); |
|
| 69 |
- if (!st) {
|
|
| 70 |
- fprintf(stderr, "Could not alloc stream\n"); |
|
| 71 |
- exit(1); |
|
| 72 |
- } |
|
| 73 |
- |
|
| 74 |
- c = st->codec; |
|
| 75 |
- c->codec_id = codec_id; |
|
| 76 |
- c->codec_type = AVMEDIA_TYPE_AUDIO; |
|
| 77 |
- |
|
| 78 |
- /* put sample parameters */ |
|
| 79 |
- c->sample_fmt = AV_SAMPLE_FMT_S16; |
|
| 80 |
- c->bit_rate = 64000; |
|
| 81 |
- c->sample_rate = 44100; |
|
| 82 |
- c->channels = 2; |
|
| 83 |
- |
|
| 84 |
- // some formats want stream headers to be separate |
|
| 85 |
- if(oc->oformat->flags & AVFMT_GLOBALHEADER) |
|
| 86 |
- c->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
| 87 |
- |
|
| 88 |
- return st; |
|
| 89 |
-} |
|
| 90 |
- |
|
| 91 |
-static void open_audio(AVFormatContext *oc, AVStream *st) |
|
| 92 |
-{
|
|
| 93 |
- AVCodecContext *c; |
|
| 94 |
- AVCodec *codec; |
|
| 95 |
- |
|
| 96 |
- c = st->codec; |
|
| 97 |
- |
|
| 98 |
- /* find the audio encoder */ |
|
| 99 |
- codec = avcodec_find_encoder(c->codec_id); |
|
| 100 |
- if (!codec) {
|
|
| 101 |
- fprintf(stderr, "codec not found\n"); |
|
| 102 |
- exit(1); |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- /* open it */ |
|
| 106 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 107 |
- fprintf(stderr, "could not open codec\n"); |
|
| 108 |
- exit(1); |
|
| 109 |
- } |
|
| 110 |
- |
|
| 111 |
- /* init signal generator */ |
|
| 112 |
- t = 0; |
|
| 113 |
- tincr = 2 * M_PI * 110.0 / c->sample_rate; |
|
| 114 |
- /* increment frequency by 110 Hz per second */ |
|
| 115 |
- tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; |
|
| 116 |
- |
|
| 117 |
- audio_outbuf_size = 10000; |
|
| 118 |
- audio_outbuf = av_malloc(audio_outbuf_size); |
|
| 119 |
- |
|
| 120 |
- /* ugly hack for PCM codecs (will be removed ASAP with new PCM |
|
| 121 |
- support to compute the input frame size in samples */ |
|
| 122 |
- if (c->frame_size <= 1) {
|
|
| 123 |
- audio_input_frame_size = audio_outbuf_size / c->channels; |
|
| 124 |
- switch(st->codec->codec_id) {
|
|
| 125 |
- case CODEC_ID_PCM_S16LE: |
|
| 126 |
- case CODEC_ID_PCM_S16BE: |
|
| 127 |
- case CODEC_ID_PCM_U16LE: |
|
| 128 |
- case CODEC_ID_PCM_U16BE: |
|
| 129 |
- audio_input_frame_size >>= 1; |
|
| 130 |
- break; |
|
| 131 |
- default: |
|
| 132 |
- break; |
|
| 133 |
- } |
|
| 134 |
- } else {
|
|
| 135 |
- audio_input_frame_size = c->frame_size; |
|
| 136 |
- } |
|
| 137 |
- samples = av_malloc(audio_input_frame_size * 2 * c->channels); |
|
| 138 |
-} |
|
| 139 |
- |
|
| 140 |
-/* prepare a 16 bit dummy audio frame of 'frame_size' samples and |
|
| 141 |
- 'nb_channels' channels */ |
|
| 142 |
-static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) |
|
| 143 |
-{
|
|
| 144 |
- int j, i, v; |
|
| 145 |
- int16_t *q; |
|
| 146 |
- |
|
| 147 |
- q = samples; |
|
| 148 |
- for(j=0;j<frame_size;j++) {
|
|
| 149 |
- v = (int)(sin(t) * 10000); |
|
| 150 |
- for(i = 0; i < nb_channels; i++) |
|
| 151 |
- *q++ = v; |
|
| 152 |
- t += tincr; |
|
| 153 |
- tincr += tincr2; |
|
| 154 |
- } |
|
| 155 |
-} |
|
| 156 |
- |
|
| 157 |
-static void write_audio_frame(AVFormatContext *oc, AVStream *st) |
|
| 158 |
-{
|
|
| 159 |
- AVCodecContext *c; |
|
| 160 |
- AVPacket pkt; |
|
| 161 |
- av_init_packet(&pkt); |
|
| 162 |
- |
|
| 163 |
- c = st->codec; |
|
| 164 |
- |
|
| 165 |
- get_audio_frame(samples, audio_input_frame_size, c->channels); |
|
| 166 |
- |
|
| 167 |
- pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples); |
|
| 168 |
- |
|
| 169 |
- if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) |
|
| 170 |
- pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); |
|
| 171 |
- pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 172 |
- pkt.stream_index= st->index; |
|
| 173 |
- pkt.data= audio_outbuf; |
|
| 174 |
- |
|
| 175 |
- /* write the compressed frame in the media file */ |
|
| 176 |
- if (av_interleaved_write_frame(oc, &pkt) != 0) {
|
|
| 177 |
- fprintf(stderr, "Error while writing audio frame\n"); |
|
| 178 |
- exit(1); |
|
| 179 |
- } |
|
| 180 |
-} |
|
| 181 |
- |
|
| 182 |
-static void close_audio(AVFormatContext *oc, AVStream *st) |
|
| 183 |
-{
|
|
| 184 |
- avcodec_close(st->codec); |
|
| 185 |
- |
|
| 186 |
- av_free(samples); |
|
| 187 |
- av_free(audio_outbuf); |
|
| 188 |
-} |
|
| 189 |
- |
|
| 190 |
-/**************************************************************/ |
|
| 191 |
-/* video output */ |
|
| 192 |
- |
|
| 193 |
-AVFrame *picture, *tmp_picture; |
|
| 194 |
-uint8_t *video_outbuf; |
|
| 195 |
-int frame_count, video_outbuf_size; |
|
| 196 |
- |
|
| 197 |
-/* add a video output stream */ |
|
| 198 |
-static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id) |
|
| 199 |
-{
|
|
| 200 |
- AVCodecContext *c; |
|
| 201 |
- AVStream *st; |
|
| 202 |
- |
|
| 203 |
- st = av_new_stream(oc, 0); |
|
| 204 |
- if (!st) {
|
|
| 205 |
- fprintf(stderr, "Could not alloc stream\n"); |
|
| 206 |
- exit(1); |
|
| 207 |
- } |
|
| 208 |
- |
|
| 209 |
- c = st->codec; |
|
| 210 |
- c->codec_id = codec_id; |
|
| 211 |
- c->codec_type = AVMEDIA_TYPE_VIDEO; |
|
| 212 |
- |
|
| 213 |
- /* put sample parameters */ |
|
| 214 |
- c->bit_rate = 400000; |
|
| 215 |
- /* resolution must be a multiple of two */ |
|
| 216 |
- c->width = 352; |
|
| 217 |
- c->height = 288; |
|
| 218 |
- /* time base: this is the fundamental unit of time (in seconds) in terms |
|
| 219 |
- of which frame timestamps are represented. for fixed-fps content, |
|
| 220 |
- timebase should be 1/framerate and timestamp increments should be |
|
| 221 |
- identically 1. */ |
|
| 222 |
- c->time_base.den = STREAM_FRAME_RATE; |
|
| 223 |
- c->time_base.num = 1; |
|
| 224 |
- c->gop_size = 12; /* emit one intra frame every twelve frames at most */ |
|
| 225 |
- c->pix_fmt = STREAM_PIX_FMT; |
|
| 226 |
- if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
|
|
| 227 |
- /* just for testing, we also add B frames */ |
|
| 228 |
- c->max_b_frames = 2; |
|
| 229 |
- } |
|
| 230 |
- if (c->codec_id == CODEC_ID_MPEG1VIDEO){
|
|
| 231 |
- /* Needed to avoid using macroblocks in which some coeffs overflow. |
|
| 232 |
- This does not happen with normal video, it just happens here as |
|
| 233 |
- the motion of the chroma plane does not match the luma plane. */ |
|
| 234 |
- c->mb_decision=2; |
|
| 235 |
- } |
|
| 236 |
- // some formats want stream headers to be separate |
|
| 237 |
- if(oc->oformat->flags & AVFMT_GLOBALHEADER) |
|
| 238 |
- c->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
| 239 |
- |
|
| 240 |
- return st; |
|
| 241 |
-} |
|
| 242 |
- |
|
| 243 |
-static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) |
|
| 244 |
-{
|
|
| 245 |
- AVFrame *picture; |
|
| 246 |
- uint8_t *picture_buf; |
|
| 247 |
- int size; |
|
| 248 |
- |
|
| 249 |
- picture = avcodec_alloc_frame(); |
|
| 250 |
- if (!picture) |
|
| 251 |
- return NULL; |
|
| 252 |
- size = avpicture_get_size(pix_fmt, width, height); |
|
| 253 |
- picture_buf = av_malloc(size); |
|
| 254 |
- if (!picture_buf) {
|
|
| 255 |
- av_free(picture); |
|
| 256 |
- return NULL; |
|
| 257 |
- } |
|
| 258 |
- avpicture_fill((AVPicture *)picture, picture_buf, |
|
| 259 |
- pix_fmt, width, height); |
|
| 260 |
- return picture; |
|
| 261 |
-} |
|
| 262 |
- |
|
| 263 |
-static void open_video(AVFormatContext *oc, AVStream *st) |
|
| 264 |
-{
|
|
| 265 |
- AVCodec *codec; |
|
| 266 |
- AVCodecContext *c; |
|
| 267 |
- |
|
| 268 |
- c = st->codec; |
|
| 269 |
- |
|
| 270 |
- /* find the video encoder */ |
|
| 271 |
- codec = avcodec_find_encoder(c->codec_id); |
|
| 272 |
- if (!codec) {
|
|
| 273 |
- fprintf(stderr, "codec not found\n"); |
|
| 274 |
- exit(1); |
|
| 275 |
- } |
|
| 276 |
- |
|
| 277 |
- /* open the codec */ |
|
| 278 |
- if (avcodec_open(c, codec) < 0) {
|
|
| 279 |
- fprintf(stderr, "could not open codec\n"); |
|
| 280 |
- exit(1); |
|
| 281 |
- } |
|
| 282 |
- |
|
| 283 |
- video_outbuf = NULL; |
|
| 284 |
- if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
|
|
| 285 |
- /* allocate output buffer */ |
|
| 286 |
- /* XXX: API change will be done */ |
|
| 287 |
- /* buffers passed into lav* can be allocated any way you prefer, |
|
| 288 |
- as long as they're aligned enough for the architecture, and |
|
| 289 |
- they're freed appropriately (such as using av_free for buffers |
|
| 290 |
- allocated with av_malloc) */ |
|
| 291 |
- video_outbuf_size = 200000; |
|
| 292 |
- video_outbuf = av_malloc(video_outbuf_size); |
|
| 293 |
- } |
|
| 294 |
- |
|
| 295 |
- /* allocate the encoded raw picture */ |
|
| 296 |
- picture = alloc_picture(c->pix_fmt, c->width, c->height); |
|
| 297 |
- if (!picture) {
|
|
| 298 |
- fprintf(stderr, "Could not allocate picture\n"); |
|
| 299 |
- exit(1); |
|
| 300 |
- } |
|
| 301 |
- |
|
| 302 |
- /* if the output format is not YUV420P, then a temporary YUV420P |
|
| 303 |
- picture is needed too. It is then converted to the required |
|
| 304 |
- output format */ |
|
| 305 |
- tmp_picture = NULL; |
|
| 306 |
- if (c->pix_fmt != PIX_FMT_YUV420P) {
|
|
| 307 |
- tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height); |
|
| 308 |
- if (!tmp_picture) {
|
|
| 309 |
- fprintf(stderr, "Could not allocate temporary picture\n"); |
|
| 310 |
- exit(1); |
|
| 311 |
- } |
|
| 312 |
- } |
|
| 313 |
-} |
|
| 314 |
- |
|
| 315 |
-/* prepare a dummy image */ |
|
| 316 |
-static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) |
|
| 317 |
-{
|
|
| 318 |
- int x, y, i; |
|
| 319 |
- |
|
| 320 |
- i = frame_index; |
|
| 321 |
- |
|
| 322 |
- /* Y */ |
|
| 323 |
- for(y=0;y<height;y++) {
|
|
| 324 |
- for(x=0;x<width;x++) {
|
|
| 325 |
- pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3; |
|
| 326 |
- } |
|
| 327 |
- } |
|
| 328 |
- |
|
| 329 |
- /* Cb and Cr */ |
|
| 330 |
- for(y=0;y<height/2;y++) {
|
|
| 331 |
- for(x=0;x<width/2;x++) {
|
|
| 332 |
- pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2; |
|
| 333 |
- pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5; |
|
| 334 |
- } |
|
| 335 |
- } |
|
| 336 |
-} |
|
| 337 |
- |
|
| 338 |
-static void write_video_frame(AVFormatContext *oc, AVStream *st) |
|
| 339 |
-{
|
|
| 340 |
- int out_size, ret; |
|
| 341 |
- AVCodecContext *c; |
|
| 342 |
- static struct SwsContext *img_convert_ctx; |
|
| 343 |
- |
|
| 344 |
- c = st->codec; |
|
| 345 |
- |
|
| 346 |
- if (frame_count >= STREAM_NB_FRAMES) {
|
|
| 347 |
- /* no more frame to compress. The codec has a latency of a few |
|
| 348 |
- frames if using B frames, so we get the last frames by |
|
| 349 |
- passing the same picture again */ |
|
| 350 |
- } else {
|
|
| 351 |
- if (c->pix_fmt != PIX_FMT_YUV420P) {
|
|
| 352 |
- /* as we only generate a YUV420P picture, we must convert it |
|
| 353 |
- to the codec pixel format if needed */ |
|
| 354 |
- if (img_convert_ctx == NULL) {
|
|
| 355 |
- img_convert_ctx = sws_getContext(c->width, c->height, |
|
| 356 |
- PIX_FMT_YUV420P, |
|
| 357 |
- c->width, c->height, |
|
| 358 |
- c->pix_fmt, |
|
| 359 |
- sws_flags, NULL, NULL, NULL); |
|
| 360 |
- if (img_convert_ctx == NULL) {
|
|
| 361 |
- fprintf(stderr, "Cannot initialize the conversion context\n"); |
|
| 362 |
- exit(1); |
|
| 363 |
- } |
|
| 364 |
- } |
|
| 365 |
- fill_yuv_image(tmp_picture, frame_count, c->width, c->height); |
|
| 366 |
- sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize, |
|
| 367 |
- 0, c->height, picture->data, picture->linesize); |
|
| 368 |
- } else {
|
|
| 369 |
- fill_yuv_image(picture, frame_count, c->width, c->height); |
|
| 370 |
- } |
|
| 371 |
- } |
|
| 372 |
- |
|
| 373 |
- |
|
| 374 |
- if (oc->oformat->flags & AVFMT_RAWPICTURE) {
|
|
| 375 |
- /* raw video case. The API will change slightly in the near |
|
| 376 |
- futur for that */ |
|
| 377 |
- AVPacket pkt; |
|
| 378 |
- av_init_packet(&pkt); |
|
| 379 |
- |
|
| 380 |
- pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 381 |
- pkt.stream_index= st->index; |
|
| 382 |
- pkt.data= (uint8_t *)picture; |
|
| 383 |
- pkt.size= sizeof(AVPicture); |
|
| 384 |
- |
|
| 385 |
- ret = av_interleaved_write_frame(oc, &pkt); |
|
| 386 |
- } else {
|
|
| 387 |
- /* encode the image */ |
|
| 388 |
- out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); |
|
| 389 |
- /* if zero size, it means the image was buffered */ |
|
| 390 |
- if (out_size > 0) {
|
|
| 391 |
- AVPacket pkt; |
|
| 392 |
- av_init_packet(&pkt); |
|
| 393 |
- |
|
| 394 |
- if (c->coded_frame->pts != AV_NOPTS_VALUE) |
|
| 395 |
- pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); |
|
| 396 |
- if(c->coded_frame->key_frame) |
|
| 397 |
- pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 398 |
- pkt.stream_index= st->index; |
|
| 399 |
- pkt.data= video_outbuf; |
|
| 400 |
- pkt.size= out_size; |
|
| 401 |
- |
|
| 402 |
- /* write the compressed frame in the media file */ |
|
| 403 |
- ret = av_interleaved_write_frame(oc, &pkt); |
|
| 404 |
- } else {
|
|
| 405 |
- ret = 0; |
|
| 406 |
- } |
|
| 407 |
- } |
|
| 408 |
- if (ret != 0) {
|
|
| 409 |
- fprintf(stderr, "Error while writing video frame\n"); |
|
| 410 |
- exit(1); |
|
| 411 |
- } |
|
| 412 |
- frame_count++; |
|
| 413 |
-} |
|
| 414 |
- |
|
| 415 |
-static void close_video(AVFormatContext *oc, AVStream *st) |
|
| 416 |
-{
|
|
| 417 |
- avcodec_close(st->codec); |
|
| 418 |
- av_free(picture->data[0]); |
|
| 419 |
- av_free(picture); |
|
| 420 |
- if (tmp_picture) {
|
|
| 421 |
- av_free(tmp_picture->data[0]); |
|
| 422 |
- av_free(tmp_picture); |
|
| 423 |
- } |
|
| 424 |
- av_free(video_outbuf); |
|
| 425 |
-} |
|
| 426 |
- |
|
| 427 |
-/**************************************************************/ |
|
| 428 |
-/* media file output */ |
|
| 429 |
- |
|
| 430 |
-int main(int argc, char **argv) |
|
| 431 |
-{
|
|
| 432 |
- const char *filename; |
|
| 433 |
- AVOutputFormat *fmt; |
|
| 434 |
- AVFormatContext *oc; |
|
| 435 |
- AVStream *audio_st, *video_st; |
|
| 436 |
- double audio_pts, video_pts; |
|
| 437 |
- int i; |
|
| 438 |
- |
|
| 439 |
- /* initialize libavcodec, and register all codecs and formats */ |
|
| 440 |
- av_register_all(); |
|
| 441 |
- |
|
| 442 |
- if (argc != 2) {
|
|
| 443 |
- printf("usage: %s output_file\n"
|
|
| 444 |
- "API example program to output a media file with libavformat.\n" |
|
| 445 |
- "The output format is automatically guessed according to the file extension.\n" |
|
| 446 |
- "Raw images can also be output by using '%%d' in the filename\n" |
|
| 447 |
- "\n", argv[0]); |
|
| 448 |
- exit(1); |
|
| 449 |
- } |
|
| 450 |
- |
|
| 451 |
- filename = argv[1]; |
|
| 452 |
- |
|
| 453 |
- /* allocate the output media context */ |
|
| 454 |
- avformat_alloc_output_context2(&oc, NULL, NULL, filename); |
|
| 455 |
- if (!oc) {
|
|
| 456 |
- printf("Could not deduce output format from file extension: using MPEG.\n");
|
|
| 457 |
- avformat_alloc_output_context2(&oc, NULL, "mpeg", filename); |
|
| 458 |
- } |
|
| 459 |
- if (!oc) {
|
|
| 460 |
- exit(1); |
|
| 461 |
- } |
|
| 462 |
- fmt= oc->oformat; |
|
| 463 |
- |
|
| 464 |
- /* add the audio and video streams using the default format codecs |
|
| 465 |
- and initialize the codecs */ |
|
| 466 |
- video_st = NULL; |
|
| 467 |
- audio_st = NULL; |
|
| 468 |
- if (fmt->video_codec != CODEC_ID_NONE) {
|
|
| 469 |
- video_st = add_video_stream(oc, fmt->video_codec); |
|
| 470 |
- } |
|
| 471 |
- if (fmt->audio_codec != CODEC_ID_NONE) {
|
|
| 472 |
- audio_st = add_audio_stream(oc, fmt->audio_codec); |
|
| 473 |
- } |
|
| 474 |
- |
|
| 475 |
- av_dump_format(oc, 0, filename, 1); |
|
| 476 |
- |
|
| 477 |
- /* now that all the parameters are set, we can open the audio and |
|
| 478 |
- video codecs and allocate the necessary encode buffers */ |
|
| 479 |
- if (video_st) |
|
| 480 |
- open_video(oc, video_st); |
|
| 481 |
- if (audio_st) |
|
| 482 |
- open_audio(oc, audio_st); |
|
| 483 |
- |
|
| 484 |
- /* open the output file, if needed */ |
|
| 485 |
- if (!(fmt->flags & AVFMT_NOFILE)) {
|
|
| 486 |
- if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
|
|
| 487 |
- fprintf(stderr, "Could not open '%s'\n", filename); |
|
| 488 |
- exit(1); |
|
| 489 |
- } |
|
| 490 |
- } |
|
| 491 |
- |
|
| 492 |
- /* write the stream header, if any */ |
|
| 493 |
- av_write_header(oc); |
|
| 494 |
- |
|
| 495 |
- for(;;) {
|
|
| 496 |
- /* compute current audio and video time */ |
|
| 497 |
- if (audio_st) |
|
| 498 |
- audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; |
|
| 499 |
- else |
|
| 500 |
- audio_pts = 0.0; |
|
| 501 |
- |
|
| 502 |
- if (video_st) |
|
| 503 |
- video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; |
|
| 504 |
- else |
|
| 505 |
- video_pts = 0.0; |
|
| 506 |
- |
|
| 507 |
- if ((!audio_st || audio_pts >= STREAM_DURATION) && |
|
| 508 |
- (!video_st || video_pts >= STREAM_DURATION)) |
|
| 509 |
- break; |
|
| 510 |
- |
|
| 511 |
- /* write interleaved audio and video frames */ |
|
| 512 |
- if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
|
|
| 513 |
- write_audio_frame(oc, audio_st); |
|
| 514 |
- } else {
|
|
| 515 |
- write_video_frame(oc, video_st); |
|
| 516 |
- } |
|
| 517 |
- } |
|
| 518 |
- |
|
| 519 |
- /* write the trailer, if any. the trailer must be written |
|
| 520 |
- * before you close the CodecContexts open when you wrote the |
|
| 521 |
- * header; otherwise write_trailer may try to use memory that |
|
| 522 |
- * was freed on av_codec_close() */ |
|
| 523 |
- av_write_trailer(oc); |
|
| 524 |
- |
|
| 525 |
- /* close each codec */ |
|
| 526 |
- if (video_st) |
|
| 527 |
- close_video(oc, video_st); |
|
| 528 |
- if (audio_st) |
|
| 529 |
- close_audio(oc, audio_st); |
|
| 530 |
- |
|
| 531 |
- /* free the streams */ |
|
| 532 |
- for(i = 0; i < oc->nb_streams; i++) {
|
|
| 533 |
- av_freep(&oc->streams[i]->codec); |
|
| 534 |
- av_freep(&oc->streams[i]); |
|
| 535 |
- } |
|
| 536 |
- |
|
| 537 |
- if (!(fmt->flags & AVFMT_NOFILE)) {
|
|
| 538 |
- /* close the output file */ |
|
| 539 |
- avio_close(oc->pb); |
|
| 540 |
- } |
|
| 541 |
- |
|
| 542 |
- /* free the stream */ |
|
| 543 |
- av_free(oc); |
|
| 544 |
- |
|
| 545 |
- return 0; |
|
| 546 |
-} |
| 547 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,546 @@ |
| 0 |
+/* |
|
| 1 |
+ * Copyright (c) 2003 Fabrice Bellard |
|
| 2 |
+ * |
|
| 3 |
+ * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
| 4 |
+ * of this software and associated documentation files (the "Software"), to deal |
|
| 5 |
+ * in the Software without restriction, including without limitation the rights |
|
| 6 |
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
| 7 |
+ * copies of the Software, and to permit persons to whom the Software is |
|
| 8 |
+ * furnished to do so, subject to the following conditions: |
|
| 9 |
+ * |
|
| 10 |
+ * The above copyright notice and this permission notice shall be included in |
|
| 11 |
+ * all copies or substantial portions of the Software. |
|
| 12 |
+ * |
|
| 13 |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 14 |
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
| 15 |
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
| 16 |
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
| 17 |
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
| 18 |
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
| 19 |
+ * THE SOFTWARE. |
|
| 20 |
+ */ |
|
| 21 |
+ |
|
| 22 |
+/** |
|
| 23 |
+ * @file |
|
| 24 |
+ * libavformat API example. |
|
| 25 |
+ * |
|
| 26 |
+ * @example libavformat/output-example.c |
|
| 27 |
+ * Output a media file in any supported libavformat format. |
|
| 28 |
+ * The default codecs are used. |
|
| 29 |
+ */ |
|
| 30 |
+ |
|
| 31 |
+#include <stdlib.h> |
|
| 32 |
+#include <stdio.h> |
|
| 33 |
+#include <string.h> |
|
| 34 |
+#include <math.h> |
|
| 35 |
+ |
|
| 36 |
+#include "libavutil/mathematics.h" |
|
| 37 |
+#include "libavformat/avformat.h" |
|
| 38 |
+#include "libswscale/swscale.h" |
|
| 39 |
+ |
|
| 40 |
+#undef exit |
|
| 41 |
+ |
|
| 42 |
+/* 5 seconds stream duration */ |
|
| 43 |
+#define STREAM_DURATION 5.0 |
|
| 44 |
+#define STREAM_FRAME_RATE 25 /* 25 images/s */ |
|
| 45 |
+#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE)) |
|
| 46 |
+#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */ |
|
| 47 |
+ |
|
| 48 |
+static int sws_flags = SWS_BICUBIC; |
|
| 49 |
+ |
|
| 50 |
+/**************************************************************/ |
|
| 51 |
+/* audio output */ |
|
| 52 |
+ |
|
| 53 |
+float t, tincr, tincr2; |
|
| 54 |
+int16_t *samples; |
|
| 55 |
+uint8_t *audio_outbuf; |
|
| 56 |
+int audio_outbuf_size; |
|
| 57 |
+int audio_input_frame_size; |
|
| 58 |
+ |
|
| 59 |
+/* |
|
| 60 |
+ * add an audio output stream |
|
| 61 |
+ */ |
|
| 62 |
+static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) |
|
| 63 |
+{
|
|
| 64 |
+ AVCodecContext *c; |
|
| 65 |
+ AVStream *st; |
|
| 66 |
+ |
|
| 67 |
+ st = av_new_stream(oc, 1); |
|
| 68 |
+ if (!st) {
|
|
| 69 |
+ fprintf(stderr, "Could not alloc stream\n"); |
|
| 70 |
+ exit(1); |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ c = st->codec; |
|
| 74 |
+ c->codec_id = codec_id; |
|
| 75 |
+ c->codec_type = AVMEDIA_TYPE_AUDIO; |
|
| 76 |
+ |
|
| 77 |
+ /* put sample parameters */ |
|
| 78 |
+ c->sample_fmt = AV_SAMPLE_FMT_S16; |
|
| 79 |
+ c->bit_rate = 64000; |
|
| 80 |
+ c->sample_rate = 44100; |
|
| 81 |
+ c->channels = 2; |
|
| 82 |
+ |
|
| 83 |
+ // some formats want stream headers to be separate |
|
| 84 |
+ if(oc->oformat->flags & AVFMT_GLOBALHEADER) |
|
| 85 |
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
| 86 |
+ |
|
| 87 |
+ return st; |
|
| 88 |
+} |
|
| 89 |
+ |
|
| 90 |
+static void open_audio(AVFormatContext *oc, AVStream *st) |
|
| 91 |
+{
|
|
| 92 |
+ AVCodecContext *c; |
|
| 93 |
+ AVCodec *codec; |
|
| 94 |
+ |
|
| 95 |
+ c = st->codec; |
|
| 96 |
+ |
|
| 97 |
+ /* find the audio encoder */ |
|
| 98 |
+ codec = avcodec_find_encoder(c->codec_id); |
|
| 99 |
+ if (!codec) {
|
|
| 100 |
+ fprintf(stderr, "codec not found\n"); |
|
| 101 |
+ exit(1); |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ /* open it */ |
|
| 105 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 106 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 107 |
+ exit(1); |
|
| 108 |
+ } |
|
| 109 |
+ |
|
| 110 |
+ /* init signal generator */ |
|
| 111 |
+ t = 0; |
|
| 112 |
+ tincr = 2 * M_PI * 110.0 / c->sample_rate; |
|
| 113 |
+ /* increment frequency by 110 Hz per second */ |
|
| 114 |
+ tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; |
|
| 115 |
+ |
|
| 116 |
+ audio_outbuf_size = 10000; |
|
| 117 |
+ audio_outbuf = av_malloc(audio_outbuf_size); |
|
| 118 |
+ |
|
| 119 |
+ /* ugly hack for PCM codecs (will be removed ASAP with new PCM |
|
| 120 |
+ support to compute the input frame size in samples */ |
|
| 121 |
+ if (c->frame_size <= 1) {
|
|
| 122 |
+ audio_input_frame_size = audio_outbuf_size / c->channels; |
|
| 123 |
+ switch(st->codec->codec_id) {
|
|
| 124 |
+ case CODEC_ID_PCM_S16LE: |
|
| 125 |
+ case CODEC_ID_PCM_S16BE: |
|
| 126 |
+ case CODEC_ID_PCM_U16LE: |
|
| 127 |
+ case CODEC_ID_PCM_U16BE: |
|
| 128 |
+ audio_input_frame_size >>= 1; |
|
| 129 |
+ break; |
|
| 130 |
+ default: |
|
| 131 |
+ break; |
|
| 132 |
+ } |
|
| 133 |
+ } else {
|
|
| 134 |
+ audio_input_frame_size = c->frame_size; |
|
| 135 |
+ } |
|
| 136 |
+ samples = av_malloc(audio_input_frame_size * 2 * c->channels); |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+/* prepare a 16 bit dummy audio frame of 'frame_size' samples and |
|
| 140 |
+ 'nb_channels' channels */ |
|
| 141 |
+static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) |
|
| 142 |
+{
|
|
| 143 |
+ int j, i, v; |
|
| 144 |
+ int16_t *q; |
|
| 145 |
+ |
|
| 146 |
+ q = samples; |
|
| 147 |
+ for(j=0;j<frame_size;j++) {
|
|
| 148 |
+ v = (int)(sin(t) * 10000); |
|
| 149 |
+ for(i = 0; i < nb_channels; i++) |
|
| 150 |
+ *q++ = v; |
|
| 151 |
+ t += tincr; |
|
| 152 |
+ tincr += tincr2; |
|
| 153 |
+ } |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+static void write_audio_frame(AVFormatContext *oc, AVStream *st) |
|
| 157 |
+{
|
|
| 158 |
+ AVCodecContext *c; |
|
| 159 |
+ AVPacket pkt; |
|
| 160 |
+ av_init_packet(&pkt); |
|
| 161 |
+ |
|
| 162 |
+ c = st->codec; |
|
| 163 |
+ |
|
| 164 |
+ get_audio_frame(samples, audio_input_frame_size, c->channels); |
|
| 165 |
+ |
|
| 166 |
+ pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples); |
|
| 167 |
+ |
|
| 168 |
+ if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) |
|
| 169 |
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); |
|
| 170 |
+ pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 171 |
+ pkt.stream_index= st->index; |
|
| 172 |
+ pkt.data= audio_outbuf; |
|
| 173 |
+ |
|
| 174 |
+ /* write the compressed frame in the media file */ |
|
| 175 |
+ if (av_interleaved_write_frame(oc, &pkt) != 0) {
|
|
| 176 |
+ fprintf(stderr, "Error while writing audio frame\n"); |
|
| 177 |
+ exit(1); |
|
| 178 |
+ } |
|
| 179 |
+} |
|
| 180 |
+ |
|
| 181 |
+static void close_audio(AVFormatContext *oc, AVStream *st) |
|
| 182 |
+{
|
|
| 183 |
+ avcodec_close(st->codec); |
|
| 184 |
+ |
|
| 185 |
+ av_free(samples); |
|
| 186 |
+ av_free(audio_outbuf); |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+/**************************************************************/ |
|
| 190 |
+/* video output */ |
|
| 191 |
+ |
|
| 192 |
+AVFrame *picture, *tmp_picture; |
|
| 193 |
+uint8_t *video_outbuf; |
|
| 194 |
+int frame_count, video_outbuf_size; |
|
| 195 |
+ |
|
| 196 |
+/* add a video output stream */ |
|
| 197 |
+static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id) |
|
| 198 |
+{
|
|
| 199 |
+ AVCodecContext *c; |
|
| 200 |
+ AVStream *st; |
|
| 201 |
+ |
|
| 202 |
+ st = av_new_stream(oc, 0); |
|
| 203 |
+ if (!st) {
|
|
| 204 |
+ fprintf(stderr, "Could not alloc stream\n"); |
|
| 205 |
+ exit(1); |
|
| 206 |
+ } |
|
| 207 |
+ |
|
| 208 |
+ c = st->codec; |
|
| 209 |
+ c->codec_id = codec_id; |
|
| 210 |
+ c->codec_type = AVMEDIA_TYPE_VIDEO; |
|
| 211 |
+ |
|
| 212 |
+ /* put sample parameters */ |
|
| 213 |
+ c->bit_rate = 400000; |
|
| 214 |
+ /* resolution must be a multiple of two */ |
|
| 215 |
+ c->width = 352; |
|
| 216 |
+ c->height = 288; |
|
| 217 |
+ /* time base: this is the fundamental unit of time (in seconds) in terms |
|
| 218 |
+ of which frame timestamps are represented. for fixed-fps content, |
|
| 219 |
+ timebase should be 1/framerate and timestamp increments should be |
|
| 220 |
+ identically 1. */ |
|
| 221 |
+ c->time_base.den = STREAM_FRAME_RATE; |
|
| 222 |
+ c->time_base.num = 1; |
|
| 223 |
+ c->gop_size = 12; /* emit one intra frame every twelve frames at most */ |
|
| 224 |
+ c->pix_fmt = STREAM_PIX_FMT; |
|
| 225 |
+ if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
|
|
| 226 |
+ /* just for testing, we also add B frames */ |
|
| 227 |
+ c->max_b_frames = 2; |
|
| 228 |
+ } |
|
| 229 |
+ if (c->codec_id == CODEC_ID_MPEG1VIDEO){
|
|
| 230 |
+ /* Needed to avoid using macroblocks in which some coeffs overflow. |
|
| 231 |
+ This does not happen with normal video, it just happens here as |
|
| 232 |
+ the motion of the chroma plane does not match the luma plane. */ |
|
| 233 |
+ c->mb_decision=2; |
|
| 234 |
+ } |
|
| 235 |
+ // some formats want stream headers to be separate |
|
| 236 |
+ if(oc->oformat->flags & AVFMT_GLOBALHEADER) |
|
| 237 |
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER; |
|
| 238 |
+ |
|
| 239 |
+ return st; |
|
| 240 |
+} |
|
| 241 |
+ |
|
| 242 |
+static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) |
|
| 243 |
+{
|
|
| 244 |
+ AVFrame *picture; |
|
| 245 |
+ uint8_t *picture_buf; |
|
| 246 |
+ int size; |
|
| 247 |
+ |
|
| 248 |
+ picture = avcodec_alloc_frame(); |
|
| 249 |
+ if (!picture) |
|
| 250 |
+ return NULL; |
|
| 251 |
+ size = avpicture_get_size(pix_fmt, width, height); |
|
| 252 |
+ picture_buf = av_malloc(size); |
|
| 253 |
+ if (!picture_buf) {
|
|
| 254 |
+ av_free(picture); |
|
| 255 |
+ return NULL; |
|
| 256 |
+ } |
|
| 257 |
+ avpicture_fill((AVPicture *)picture, picture_buf, |
|
| 258 |
+ pix_fmt, width, height); |
|
| 259 |
+ return picture; |
|
| 260 |
+} |
|
| 261 |
+ |
|
| 262 |
+static void open_video(AVFormatContext *oc, AVStream *st) |
|
| 263 |
+{
|
|
| 264 |
+ AVCodec *codec; |
|
| 265 |
+ AVCodecContext *c; |
|
| 266 |
+ |
|
| 267 |
+ c = st->codec; |
|
| 268 |
+ |
|
| 269 |
+ /* find the video encoder */ |
|
| 270 |
+ codec = avcodec_find_encoder(c->codec_id); |
|
| 271 |
+ if (!codec) {
|
|
| 272 |
+ fprintf(stderr, "codec not found\n"); |
|
| 273 |
+ exit(1); |
|
| 274 |
+ } |
|
| 275 |
+ |
|
| 276 |
+ /* open the codec */ |
|
| 277 |
+ if (avcodec_open(c, codec) < 0) {
|
|
| 278 |
+ fprintf(stderr, "could not open codec\n"); |
|
| 279 |
+ exit(1); |
|
| 280 |
+ } |
|
| 281 |
+ |
|
| 282 |
+ video_outbuf = NULL; |
|
| 283 |
+ if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
|
|
| 284 |
+ /* allocate output buffer */ |
|
| 285 |
+ /* XXX: API change will be done */ |
|
| 286 |
+ /* buffers passed into lav* can be allocated any way you prefer, |
|
| 287 |
+ as long as they're aligned enough for the architecture, and |
|
| 288 |
+ they're freed appropriately (such as using av_free for buffers |
|
| 289 |
+ allocated with av_malloc) */ |
|
| 290 |
+ video_outbuf_size = 200000; |
|
| 291 |
+ video_outbuf = av_malloc(video_outbuf_size); |
|
| 292 |
+ } |
|
| 293 |
+ |
|
| 294 |
+ /* allocate the encoded raw picture */ |
|
| 295 |
+ picture = alloc_picture(c->pix_fmt, c->width, c->height); |
|
| 296 |
+ if (!picture) {
|
|
| 297 |
+ fprintf(stderr, "Could not allocate picture\n"); |
|
| 298 |
+ exit(1); |
|
| 299 |
+ } |
|
| 300 |
+ |
|
| 301 |
+ /* if the output format is not YUV420P, then a temporary YUV420P |
|
| 302 |
+ picture is needed too. It is then converted to the required |
|
| 303 |
+ output format */ |
|
| 304 |
+ tmp_picture = NULL; |
|
| 305 |
+ if (c->pix_fmt != PIX_FMT_YUV420P) {
|
|
| 306 |
+ tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height); |
|
| 307 |
+ if (!tmp_picture) {
|
|
| 308 |
+ fprintf(stderr, "Could not allocate temporary picture\n"); |
|
| 309 |
+ exit(1); |
|
| 310 |
+ } |
|
| 311 |
+ } |
|
| 312 |
+} |
|
| 313 |
+ |
|
| 314 |
+/* prepare a dummy image */ |
|
| 315 |
+static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) |
|
| 316 |
+{
|
|
| 317 |
+ int x, y, i; |
|
| 318 |
+ |
|
| 319 |
+ i = frame_index; |
|
| 320 |
+ |
|
| 321 |
+ /* Y */ |
|
| 322 |
+ for(y=0;y<height;y++) {
|
|
| 323 |
+ for(x=0;x<width;x++) {
|
|
| 324 |
+ pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3; |
|
| 325 |
+ } |
|
| 326 |
+ } |
|
| 327 |
+ |
|
| 328 |
+ /* Cb and Cr */ |
|
| 329 |
+ for(y=0;y<height/2;y++) {
|
|
| 330 |
+ for(x=0;x<width/2;x++) {
|
|
| 331 |
+ pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2; |
|
| 332 |
+ pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5; |
|
| 333 |
+ } |
|
| 334 |
+ } |
|
| 335 |
+} |
|
| 336 |
+ |
|
| 337 |
+static void write_video_frame(AVFormatContext *oc, AVStream *st) |
|
| 338 |
+{
|
|
| 339 |
+ int out_size, ret; |
|
| 340 |
+ AVCodecContext *c; |
|
| 341 |
+ static struct SwsContext *img_convert_ctx; |
|
| 342 |
+ |
|
| 343 |
+ c = st->codec; |
|
| 344 |
+ |
|
| 345 |
+ if (frame_count >= STREAM_NB_FRAMES) {
|
|
| 346 |
+ /* no more frame to compress. The codec has a latency of a few |
|
| 347 |
+ frames if using B frames, so we get the last frames by |
|
| 348 |
+ passing the same picture again */ |
|
| 349 |
+ } else {
|
|
| 350 |
+ if (c->pix_fmt != PIX_FMT_YUV420P) {
|
|
| 351 |
+ /* as we only generate a YUV420P picture, we must convert it |
|
| 352 |
+ to the codec pixel format if needed */ |
|
| 353 |
+ if (img_convert_ctx == NULL) {
|
|
| 354 |
+ img_convert_ctx = sws_getContext(c->width, c->height, |
|
| 355 |
+ PIX_FMT_YUV420P, |
|
| 356 |
+ c->width, c->height, |
|
| 357 |
+ c->pix_fmt, |
|
| 358 |
+ sws_flags, NULL, NULL, NULL); |
|
| 359 |
+ if (img_convert_ctx == NULL) {
|
|
| 360 |
+ fprintf(stderr, "Cannot initialize the conversion context\n"); |
|
| 361 |
+ exit(1); |
|
| 362 |
+ } |
|
| 363 |
+ } |
|
| 364 |
+ fill_yuv_image(tmp_picture, frame_count, c->width, c->height); |
|
| 365 |
+ sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize, |
|
| 366 |
+ 0, c->height, picture->data, picture->linesize); |
|
| 367 |
+ } else {
|
|
| 368 |
+ fill_yuv_image(picture, frame_count, c->width, c->height); |
|
| 369 |
+ } |
|
| 370 |
+ } |
|
| 371 |
+ |
|
| 372 |
+ |
|
| 373 |
+ if (oc->oformat->flags & AVFMT_RAWPICTURE) {
|
|
| 374 |
+ /* raw video case. The API will change slightly in the near |
|
| 375 |
+ futur for that */ |
|
| 376 |
+ AVPacket pkt; |
|
| 377 |
+ av_init_packet(&pkt); |
|
| 378 |
+ |
|
| 379 |
+ pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 380 |
+ pkt.stream_index= st->index; |
|
| 381 |
+ pkt.data= (uint8_t *)picture; |
|
| 382 |
+ pkt.size= sizeof(AVPicture); |
|
| 383 |
+ |
|
| 384 |
+ ret = av_interleaved_write_frame(oc, &pkt); |
|
| 385 |
+ } else {
|
|
| 386 |
+ /* encode the image */ |
|
| 387 |
+ out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); |
|
| 388 |
+ /* if zero size, it means the image was buffered */ |
|
| 389 |
+ if (out_size > 0) {
|
|
| 390 |
+ AVPacket pkt; |
|
| 391 |
+ av_init_packet(&pkt); |
|
| 392 |
+ |
|
| 393 |
+ if (c->coded_frame->pts != AV_NOPTS_VALUE) |
|
| 394 |
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); |
|
| 395 |
+ if(c->coded_frame->key_frame) |
|
| 396 |
+ pkt.flags |= AV_PKT_FLAG_KEY; |
|
| 397 |
+ pkt.stream_index= st->index; |
|
| 398 |
+ pkt.data= video_outbuf; |
|
| 399 |
+ pkt.size= out_size; |
|
| 400 |
+ |
|
| 401 |
+ /* write the compressed frame in the media file */ |
|
| 402 |
+ ret = av_interleaved_write_frame(oc, &pkt); |
|
| 403 |
+ } else {
|
|
| 404 |
+ ret = 0; |
|
| 405 |
+ } |
|
| 406 |
+ } |
|
| 407 |
+ if (ret != 0) {
|
|
| 408 |
+ fprintf(stderr, "Error while writing video frame\n"); |
|
| 409 |
+ exit(1); |
|
| 410 |
+ } |
|
| 411 |
+ frame_count++; |
|
| 412 |
+} |
|
| 413 |
+ |
|
| 414 |
+static void close_video(AVFormatContext *oc, AVStream *st) |
|
| 415 |
+{
|
|
| 416 |
+ avcodec_close(st->codec); |
|
| 417 |
+ av_free(picture->data[0]); |
|
| 418 |
+ av_free(picture); |
|
| 419 |
+ if (tmp_picture) {
|
|
| 420 |
+ av_free(tmp_picture->data[0]); |
|
| 421 |
+ av_free(tmp_picture); |
|
| 422 |
+ } |
|
| 423 |
+ av_free(video_outbuf); |
|
| 424 |
+} |
|
| 425 |
+ |
|
| 426 |
+/**************************************************************/ |
|
| 427 |
+/* media file output */ |
|
| 428 |
+ |
|
| 429 |
+int main(int argc, char **argv) |
|
| 430 |
+{
|
|
| 431 |
+ const char *filename; |
|
| 432 |
+ AVOutputFormat *fmt; |
|
| 433 |
+ AVFormatContext *oc; |
|
| 434 |
+ AVStream *audio_st, *video_st; |
|
| 435 |
+ double audio_pts, video_pts; |
|
| 436 |
+ int i; |
|
| 437 |
+ |
|
| 438 |
+ /* initialize libavcodec, and register all codecs and formats */ |
|
| 439 |
+ av_register_all(); |
|
| 440 |
+ |
|
| 441 |
+ if (argc != 2) {
|
|
| 442 |
+ printf("usage: %s output_file\n"
|
|
| 443 |
+ "API example program to output a media file with libavformat.\n" |
|
| 444 |
+ "The output format is automatically guessed according to the file extension.\n" |
|
| 445 |
+ "Raw images can also be output by using '%%d' in the filename\n" |
|
| 446 |
+ "\n", argv[0]); |
|
| 447 |
+ exit(1); |
|
| 448 |
+ } |
|
| 449 |
+ |
|
| 450 |
+ filename = argv[1]; |
|
| 451 |
+ |
|
| 452 |
+ /* allocate the output media context */ |
|
| 453 |
+ avformat_alloc_output_context2(&oc, NULL, NULL, filename); |
|
| 454 |
+ if (!oc) {
|
|
| 455 |
+ printf("Could not deduce output format from file extension: using MPEG.\n");
|
|
| 456 |
+ avformat_alloc_output_context2(&oc, NULL, "mpeg", filename); |
|
| 457 |
+ } |
|
| 458 |
+ if (!oc) {
|
|
| 459 |
+ exit(1); |
|
| 460 |
+ } |
|
| 461 |
+ fmt= oc->oformat; |
|
| 462 |
+ |
|
| 463 |
+ /* add the audio and video streams using the default format codecs |
|
| 464 |
+ and initialize the codecs */ |
|
| 465 |
+ video_st = NULL; |
|
| 466 |
+ audio_st = NULL; |
|
| 467 |
+ if (fmt->video_codec != CODEC_ID_NONE) {
|
|
| 468 |
+ video_st = add_video_stream(oc, fmt->video_codec); |
|
| 469 |
+ } |
|
| 470 |
+ if (fmt->audio_codec != CODEC_ID_NONE) {
|
|
| 471 |
+ audio_st = add_audio_stream(oc, fmt->audio_codec); |
|
| 472 |
+ } |
|
| 473 |
+ |
|
| 474 |
+ av_dump_format(oc, 0, filename, 1); |
|
| 475 |
+ |
|
| 476 |
+ /* now that all the parameters are set, we can open the audio and |
|
| 477 |
+ video codecs and allocate the necessary encode buffers */ |
|
| 478 |
+ if (video_st) |
|
| 479 |
+ open_video(oc, video_st); |
|
| 480 |
+ if (audio_st) |
|
| 481 |
+ open_audio(oc, audio_st); |
|
| 482 |
+ |
|
| 483 |
+ /* open the output file, if needed */ |
|
| 484 |
+ if (!(fmt->flags & AVFMT_NOFILE)) {
|
|
| 485 |
+ if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
|
|
| 486 |
+ fprintf(stderr, "Could not open '%s'\n", filename); |
|
| 487 |
+ exit(1); |
|
| 488 |
+ } |
|
| 489 |
+ } |
|
| 490 |
+ |
|
| 491 |
+ /* write the stream header, if any */ |
|
| 492 |
+ av_write_header(oc); |
|
| 493 |
+ |
|
| 494 |
+ for(;;) {
|
|
| 495 |
+ /* compute current audio and video time */ |
|
| 496 |
+ if (audio_st) |
|
| 497 |
+ audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; |
|
| 498 |
+ else |
|
| 499 |
+ audio_pts = 0.0; |
|
| 500 |
+ |
|
| 501 |
+ if (video_st) |
|
| 502 |
+ video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; |
|
| 503 |
+ else |
|
| 504 |
+ video_pts = 0.0; |
|
| 505 |
+ |
|
| 506 |
+ if ((!audio_st || audio_pts >= STREAM_DURATION) && |
|
| 507 |
+ (!video_st || video_pts >= STREAM_DURATION)) |
|
| 508 |
+ break; |
|
| 509 |
+ |
|
| 510 |
+ /* write interleaved audio and video frames */ |
|
| 511 |
+ if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
|
|
| 512 |
+ write_audio_frame(oc, audio_st); |
|
| 513 |
+ } else {
|
|
| 514 |
+ write_video_frame(oc, video_st); |
|
| 515 |
+ } |
|
| 516 |
+ } |
|
| 517 |
+ |
|
| 518 |
+ /* write the trailer, if any. the trailer must be written |
|
| 519 |
+ * before you close the CodecContexts open when you wrote the |
|
| 520 |
+ * header; otherwise write_trailer may try to use memory that |
|
| 521 |
+ * was freed on av_codec_close() */ |
|
| 522 |
+ av_write_trailer(oc); |
|
| 523 |
+ |
|
| 524 |
+ /* close each codec */ |
|
| 525 |
+ if (video_st) |
|
| 526 |
+ close_video(oc, video_st); |
|
| 527 |
+ if (audio_st) |
|
| 528 |
+ close_audio(oc, audio_st); |
|
| 529 |
+ |
|
| 530 |
+ /* free the streams */ |
|
| 531 |
+ for(i = 0; i < oc->nb_streams; i++) {
|
|
| 532 |
+ av_freep(&oc->streams[i]->codec); |
|
| 533 |
+ av_freep(&oc->streams[i]); |
|
| 534 |
+ } |
|
| 535 |
+ |
|
| 536 |
+ if (!(fmt->flags & AVFMT_NOFILE)) {
|
|
| 537 |
+ /* close the output file */ |
|
| 538 |
+ avio_close(oc->pb); |
|
| 539 |
+ } |
|
| 540 |
+ |
|
| 541 |
+ /* free the stream */ |
|
| 542 |
+ av_free(oc); |
|
| 543 |
+ |
|
| 544 |
+ return 0; |
|
| 545 |
+} |