00001 /* 00002 * Copyright (c) 2001 Fabrice Bellard 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00017 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00032 #include "libavutil/imgutils.h" 00033 #include "libavutil/opt.h" 00034 #include "libavcodec/avcodec.h" 00035 #include "libavutil/mathematics.h" 00036 #include "libavutil/samplefmt.h" 00037 00038 #define INBUF_SIZE 4096 00039 #define AUDIO_INBUF_SIZE 20480 00040 #define AUDIO_REFILL_THRESH 4096 00041 00042 /* 00043 * Audio encoding example 00044 */ 00045 static void audio_encode_example(const char *filename) 00046 { 00047 AVCodec *codec; 00048 AVCodecContext *c= NULL; 00049 int frame_size, i, j, out_size, outbuf_size; 00050 FILE *f; 00051 short *samples; 00052 float t, tincr; 00053 uint8_t *outbuf; 00054 00055 printf("Audio encoding\n"); 00056 00057 /* find the MP2 encoder */ 00058 codec = avcodec_find_encoder(CODEC_ID_MP2); 00059 if (!codec) { 00060 fprintf(stderr, "codec not found\n"); 00061 exit(1); 00062 } 00063 00064 c = avcodec_alloc_context3(codec); 00065 00066 /* put sample parameters */ 00067 c->bit_rate = 64000; 00068 c->sample_rate = 44100; 00069 c->channels = 2; 00070 c->sample_fmt = AV_SAMPLE_FMT_S16; 00071 00072 /* open it */ 00073 if (avcodec_open(c, codec) < 0) { 00074 fprintf(stderr, "could not open codec\n"); 00075 exit(1); 00076 } 00077 00078 /* the codec gives us the frame size, in samples */ 00079 frame_size = c->frame_size; 00080 samples = malloc(frame_size * 2 * c->channels); 00081 outbuf_size = 10000; 00082 outbuf = malloc(outbuf_size); 00083 00084 f = fopen(filename, "wb"); 00085 if (!f) { 00086 fprintf(stderr, "could not open %s\n", filename); 00087 exit(1); 00088 } 00089 00090 /* encode a single tone sound */ 00091 t = 0; 00092 tincr = 2 * M_PI * 440.0 / c->sample_rate; 00093 for(i=0;i<200;i++) { 00094 for(j=0;j<frame_size;j++) { 00095 samples[2*j] = (int)(sin(t) * 10000); 00096 samples[2*j+1] = samples[2*j]; 00097 t += tincr; 00098 } 00099 /* encode the samples */ 00100 out_size = avcodec_encode_audio(c, outbuf, outbuf_size, samples); 00101 fwrite(outbuf, 1, out_size, f); 00102 } 00103 fclose(f); 00104 free(outbuf); 00105 free(samples); 00106 00107 avcodec_close(c); 00108 av_free(c); 00109 } 00110 00111 /* 00112 * Audio decoding. 00113 */ 00114 static void audio_decode_example(const char *outfilename, const char *filename) 00115 { 00116 AVCodec *codec; 00117 AVCodecContext *c= NULL; 00118 int len; 00119 FILE *f, *outfile; 00120 uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 00121 AVPacket avpkt; 00122 AVFrame *decoded_frame = NULL; 00123 00124 av_init_packet(&avpkt); 00125 00126 printf("Audio decoding\n"); 00127 00128 /* find the mpeg audio decoder */ 00129 codec = avcodec_find_decoder(CODEC_ID_MP2); 00130 if (!codec) { 00131 fprintf(stderr, "codec not found\n"); 00132 exit(1); 00133 } 00134 00135 c = avcodec_alloc_context3(codec); 00136 00137 /* open it */ 00138 if (avcodec_open(c, codec) < 0) { 00139 fprintf(stderr, "could not open codec\n"); 00140 exit(1); 00141 } 00142 00143 f = fopen(filename, "rb"); 00144 if (!f) { 00145 fprintf(stderr, "could not open %s\n", filename); 00146 exit(1); 00147 } 00148 outfile = fopen(outfilename, "wb"); 00149 if (!outfile) { 00150 av_free(c); 00151 exit(1); 00152 } 00153 00154 /* decode until eof */ 00155 avpkt.data = inbuf; 00156 avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); 00157 00158 while (avpkt.size > 0) { 00159 int got_frame = 0; 00160 00161 if (!decoded_frame) { 00162 if (!(decoded_frame = avcodec_alloc_frame())) { 00163 fprintf(stderr, "out of memory\n"); 00164 exit(1); 00165 } 00166 } else 00167 avcodec_get_frame_defaults(decoded_frame); 00168 00169 len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); 00170 if (len < 0) { 00171 fprintf(stderr, "Error while decoding\n"); 00172 exit(1); 00173 } 00174 if (got_frame) { 00175 /* if a frame has been decoded, output it */ 00176 int data_size = av_samples_get_buffer_size(NULL, c->channels, 00177 decoded_frame->nb_samples, 00178 c->sample_fmt, 1); 00179 fwrite(decoded_frame->data[0], 1, data_size, outfile); 00180 } 00181 avpkt.size -= len; 00182 avpkt.data += len; 00183 avpkt.dts = 00184 avpkt.pts = AV_NOPTS_VALUE; 00185 if (avpkt.size < AUDIO_REFILL_THRESH) { 00186 /* Refill the input buffer, to avoid trying to decode 00187 * incomplete frames. Instead of this, one could also use 00188 * a parser, or use a proper container format through 00189 * libavformat. */ 00190 memmove(inbuf, avpkt.data, avpkt.size); 00191 avpkt.data = inbuf; 00192 len = fread(avpkt.data + avpkt.size, 1, 00193 AUDIO_INBUF_SIZE - avpkt.size, f); 00194 if (len > 0) 00195 avpkt.size += len; 00196 } 00197 } 00198 00199 fclose(outfile); 00200 fclose(f); 00201 00202 avcodec_close(c); 00203 av_free(c); 00204 av_free(decoded_frame); 00205 } 00206 00207 /* 00208 * Video encoding example 00209 */ 00210 static void video_encode_example(const char *filename, int codec_id) 00211 { 00212 AVCodec *codec; 00213 AVCodecContext *c= NULL; 00214 int i, out_size, size, x, y, outbuf_size; 00215 FILE *f; 00216 AVFrame *picture; 00217 uint8_t *outbuf; 00218 00219 printf("Video encoding\n"); 00220 00221 /* find the mpeg1 video encoder */ 00222 codec = avcodec_find_encoder(codec_id); 00223 if (!codec) { 00224 fprintf(stderr, "codec not found\n"); 00225 exit(1); 00226 } 00227 00228 c = avcodec_alloc_context3(codec); 00229 picture= avcodec_alloc_frame(); 00230 00231 /* put sample parameters */ 00232 c->bit_rate = 400000; 00233 /* resolution must be a multiple of two */ 00234 c->width = 352; 00235 c->height = 288; 00236 /* frames per second */ 00237 c->time_base= (AVRational){1,25}; 00238 c->gop_size = 10; /* emit one intra frame every ten frames */ 00239 c->max_b_frames=1; 00240 c->pix_fmt = PIX_FMT_YUV420P; 00241 00242 if(codec_id == CODEC_ID_H264) 00243 av_opt_set(c->priv_data, "preset", "slow", 0); 00244 00245 /* open it */ 00246 if (avcodec_open(c, codec) < 0) { 00247 fprintf(stderr, "could not open codec\n"); 00248 exit(1); 00249 } 00250 00251 f = fopen(filename, "wb"); 00252 if (!f) { 00253 fprintf(stderr, "could not open %s\n", filename); 00254 exit(1); 00255 } 00256 00257 /* alloc image and output buffer */ 00258 outbuf_size = 100000; 00259 outbuf = malloc(outbuf_size); 00260 00261 /* the image can be allocated by any means and av_image_alloc() is 00262 * just the most convenient way if av_malloc() is to be used */ 00263 av_image_alloc(picture->data, picture->linesize, 00264 c->width, c->height, c->pix_fmt, 1); 00265 00266 /* encode 1 second of video */ 00267 for(i=0;i<25;i++) { 00268 fflush(stdout); 00269 /* prepare a dummy image */ 00270 /* Y */ 00271 for(y=0;y<c->height;y++) { 00272 for(x=0;x<c->width;x++) { 00273 picture->data[0][y * picture->linesize[0] + x] = x + y + i * 3; 00274 } 00275 } 00276 00277 /* Cb and Cr */ 00278 for(y=0;y<c->height/2;y++) { 00279 for(x=0;x<c->width/2;x++) { 00280 picture->data[1][y * picture->linesize[1] + x] = 128 + y + i * 2; 00281 picture->data[2][y * picture->linesize[2] + x] = 64 + x + i * 5; 00282 } 00283 } 00284 00285 /* encode the image */ 00286 out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); 00287 printf("encoding frame %3d (size=%5d)\n", i, out_size); 00288 fwrite(outbuf, 1, out_size, f); 00289 } 00290 00291 /* get the delayed frames */ 00292 for(; out_size; i++) { 00293 fflush(stdout); 00294 00295 out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); 00296 printf("write frame %3d (size=%5d)\n", i, out_size); 00297 fwrite(outbuf, 1, out_size, f); 00298 } 00299 00300 /* add sequence end code to have a real mpeg file */ 00301 outbuf[0] = 0x00; 00302 outbuf[1] = 0x00; 00303 outbuf[2] = 0x01; 00304 outbuf[3] = 0xb7; 00305 fwrite(outbuf, 1, 4, f); 00306 fclose(f); 00307 free(outbuf); 00308 00309 avcodec_close(c); 00310 av_free(c); 00311 av_free(picture->data[0]); 00312 av_free(picture); 00313 printf("\n"); 00314 } 00315 00316 /* 00317 * Video decoding example 00318 */ 00319 00320 static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize, 00321 char *filename) 00322 { 00323 FILE *f; 00324 int i; 00325 00326 f=fopen(filename,"w"); 00327 fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255); 00328 for(i=0;i<ysize;i++) 00329 fwrite(buf + i * wrap,1,xsize,f); 00330 fclose(f); 00331 } 00332 00333 static void video_decode_example(const char *outfilename, const char *filename) 00334 { 00335 AVCodec *codec; 00336 AVCodecContext *c= NULL; 00337 int frame, got_picture, len; 00338 FILE *f; 00339 AVFrame *picture; 00340 uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 00341 char buf[1024]; 00342 AVPacket avpkt; 00343 00344 av_init_packet(&avpkt); 00345 00346 /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ 00347 memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); 00348 00349 printf("Video decoding\n"); 00350 00351 /* find the mpeg1 video decoder */ 00352 codec = avcodec_find_decoder(CODEC_ID_MPEG1VIDEO); 00353 if (!codec) { 00354 fprintf(stderr, "codec not found\n"); 00355 exit(1); 00356 } 00357 00358 c = avcodec_alloc_context3(codec); 00359 picture= avcodec_alloc_frame(); 00360 00361 if(codec->capabilities&CODEC_CAP_TRUNCATED) 00362 c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */ 00363 00364 /* For some codecs, such as msmpeg4 and mpeg4, width and height 00365 MUST be initialized there because this information is not 00366 available in the bitstream. */ 00367 00368 /* open it */ 00369 if (avcodec_open(c, codec) < 0) { 00370 fprintf(stderr, "could not open codec\n"); 00371 exit(1); 00372 } 00373 00374 /* the codec gives us the frame size, in samples */ 00375 00376 f = fopen(filename, "rb"); 00377 if (!f) { 00378 fprintf(stderr, "could not open %s\n", filename); 00379 exit(1); 00380 } 00381 00382 frame = 0; 00383 for(;;) { 00384 avpkt.size = fread(inbuf, 1, INBUF_SIZE, f); 00385 if (avpkt.size == 0) 00386 break; 00387 00388 /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio) 00389 and this is the only method to use them because you cannot 00390 know the compressed data size before analysing it. 00391 00392 BUT some other codecs (msmpeg4, mpeg4) are inherently frame 00393 based, so you must call them with all the data for one 00394 frame exactly. You must also initialize 'width' and 00395 'height' before initializing them. */ 00396 00397 /* NOTE2: some codecs allow the raw parameters (frame size, 00398 sample rate) to be changed at any frame. We handle this, so 00399 you should also take care of it */ 00400 00401 /* here, we use a stream based decoder (mpeg1video), so we 00402 feed decoder and see if it could decode a frame */ 00403 avpkt.data = inbuf; 00404 while (avpkt.size > 0) { 00405 len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); 00406 if (len < 0) { 00407 fprintf(stderr, "Error while decoding frame %d\n", frame); 00408 exit(1); 00409 } 00410 if (got_picture) { 00411 printf("saving frame %3d\n", frame); 00412 fflush(stdout); 00413 00414 /* the picture is allocated by the decoder. no need to 00415 free it */ 00416 snprintf(buf, sizeof(buf), outfilename, frame); 00417 pgm_save(picture->data[0], picture->linesize[0], 00418 c->width, c->height, buf); 00419 frame++; 00420 } 00421 avpkt.size -= len; 00422 avpkt.data += len; 00423 } 00424 } 00425 00426 /* some codecs, such as MPEG, transmit the I and P frame with a 00427 latency of one frame. You must do the following to have a 00428 chance to get the last frame of the video */ 00429 avpkt.data = NULL; 00430 avpkt.size = 0; 00431 len = avcodec_decode_video2(c, picture, &got_picture, &avpkt); 00432 if (got_picture) { 00433 printf("saving last frame %3d\n", frame); 00434 fflush(stdout); 00435 00436 /* the picture is allocated by the decoder. no need to 00437 free it */ 00438 snprintf(buf, sizeof(buf), outfilename, frame); 00439 pgm_save(picture->data[0], picture->linesize[0], 00440 c->width, c->height, buf); 00441 frame++; 00442 } 00443 00444 fclose(f); 00445 00446 avcodec_close(c); 00447 av_free(c); 00448 av_free(picture); 00449 printf("\n"); 00450 } 00451 00452 int main(int argc, char **argv) 00453 { 00454 const char *filename; 00455 00456 /* must be called before using avcodec lib */ 00457 avcodec_init(); 00458 00459 /* register all the codecs */ 00460 avcodec_register_all(); 00461 00462 if (argc <= 1) { 00463 audio_encode_example("/tmp/test.mp2"); 00464 audio_decode_example("/tmp/test.sw", "/tmp/test.mp2"); 00465 00466 video_encode_example("/tmp/test.h264", CODEC_ID_H264); 00467 video_encode_example("/tmp/test.mpg", CODEC_ID_MPEG1VIDEO); 00468 filename = "/tmp/test.mpg"; 00469 } else { 00470 filename = argv[1]; 00471 } 00472 00473 // audio_decode_example("/tmp/test.sw", filename); 00474 video_decode_example("/tmp/test%d.pgm", filename); 00475 00476 return 0; 00477 }