ffmpeg encode/decode example

来源:互联网 发布:易语言播放音乐源码 编辑:程序博客网 时间:2024/05/18 09:29
00001 /*00002  * Copyright (c) 2001 Fabrice Bellard00003  *00004  * Permission is hereby granted, free of charge, to any person obtaining a copy00005  * of this software and associated documentation files (the "Software"), to deal00006  * in the Software without restriction, including without limitation the rights00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell00008  * copies of the Software, and to permit persons to whom the Software is00009  * furnished to do so, subject to the following conditions:00010  *00011  * The above copyright notice and this permission notice shall be included in00012  * all copies or substantial portions of the Software.00013  *00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL00017  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER00018  * 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 IN00020  * THE SOFTWARE.00021  */00022 00033 #include <math.h>00034 00035 #include <libavutil/opt.h>00036 #include <libavcodec/avcodec.h>00037 #include <libavutil/channel_layout.h>00038 #include <libavutil/common.h>00039 #include <libavutil/imgutils.h>00040 #include <libavutil/mathematics.h>00041 #include <libavutil/samplefmt.h>00042 00043 #define INBUF_SIZE 409600044 #define AUDIO_INBUF_SIZE 2048000045 #define AUDIO_REFILL_THRESH 409600046 00047 /* check that a given sample format is supported by the encoder */00048 static int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt)00049 {00050     const enum AVSampleFormat *p = codec->sample_fmts;00051 00052     while (*p != AV_SAMPLE_FMT_NONE) {00053         if (*p == sample_fmt)00054             return 1;00055         p++;00056     }00057     return 0;00058 }00059 00060 /* just pick the highest supported samplerate */00061 static int select_sample_rate(AVCodec *codec)00062 {00063     const int *p;00064     int best_samplerate = 0;00065 00066     if (!codec->supported_samplerates)00067         return 44100;00068 00069     p = codec->supported_samplerates;00070     while (*p) {00071         best_samplerate = FFMAX(*p, best_samplerate);00072         p++;00073     }00074     return best_samplerate;00075 }00076 00077 /* select layout with the highest channel count */00078 static int select_channel_layout(AVCodec *codec)00079 {00080     const uint64_t *p;00081     uint64_t best_ch_layout = 0;00082     int best_nb_channells   = 0;00083 00084     if (!codec->channel_layouts)00085         return AV_CH_LAYOUT_STEREO;00086 00087     p = codec->channel_layouts;00088     while (*p) {00089         int nb_channels = av_get_channel_layout_nb_channels(*p);00090 00091         if (nb_channels > best_nb_channells) {00092             best_ch_layout    = *p;00093             best_nb_channells = nb_channels;00094         }00095         p++;00096     }00097     return best_ch_layout;00098 }00099 00100 /*00101  * Audio encoding example00102  */00103 static void audio_encode_example(const char *filename)00104 {00105     AVCodec *codec;00106     AVCodecContext *c= NULL;00107     AVFrame *frame;00108     AVPacket pkt;00109     int i, j, k, ret, got_output;00110     int buffer_size;00111     FILE *f;00112     uint16_t *samples;00113     float t, tincr;00114 00115     printf("Encode audio file %s\n", filename);00116 00117     /* find the MP2 encoder */00118     codec = avcodec_find_encoder(AV_CODEC_ID_MP2);00119     if (!codec) {00120         fprintf(stderr, "Codec not found\n");00121         exit(1);00122     }00123 00124     c = avcodec_alloc_context3(codec);00125     if (!c) {00126         fprintf(stderr, "Could not allocate audio codec context\n");00127         exit(1);00128     }00129 00130     /* put sample parameters */00131     c->bit_rate = 64000;00132 00133     /* check that the encoder supports s16 pcm input */00134     c->sample_fmt = AV_SAMPLE_FMT_S16;00135     if (!check_sample_fmt(codec, c->sample_fmt)) {00136         fprintf(stderr, "Encoder does not support sample format %s",00137                 av_get_sample_fmt_name(c->sample_fmt));00138         exit(1);00139     }00140 00141     /* select other audio parameters supported by the encoder */00142     c->sample_rate    = select_sample_rate(codec);00143     c->channel_layout = select_channel_layout(codec);00144     c->channels       = av_get_channel_layout_nb_channels(c->channel_layout);00145 00146     /* open it */00147     if (avcodec_open2(c, codec, NULL) < 0) {00148         fprintf(stderr, "Could not open codec\n");00149         exit(1);00150     }00151 00152     f = fopen(filename, "wb");00153     if (!f) {00154         fprintf(stderr, "Could not open %s\n", filename);00155         exit(1);00156     }00157 00158     /* frame containing input raw audio */00159     frame = avcodec_alloc_frame();00160     if (!frame) {00161         fprintf(stderr, "Could not allocate audio frame\n");00162         exit(1);00163     }00164 00165     frame->nb_samples     = c->frame_size;00166     frame->format         = c->sample_fmt;00167     frame->channel_layout = c->channel_layout;00168 00169     /* the codec gives us the frame size, in samples,00170      * we calculate the size of the samples buffer in bytes */00171     buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size,00172                                              c->sample_fmt, 0);00173     samples = av_malloc(buffer_size);00174     if (!samples) {00175         fprintf(stderr, "Could not allocate %d bytes for samples buffer\n",00176                 buffer_size);00177         exit(1);00178     }00179     /* setup the data pointers in the AVFrame */00180     ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,00181                                    (const uint8_t*)samples, buffer_size, 0);00182     if (ret < 0) {00183         fprintf(stderr, "Could not setup audio frame\n");00184         exit(1);00185     }00186 00187     /* encode a single tone sound */00188     t = 0;00189     tincr = 2 * M_PI * 440.0 / c->sample_rate;00190     for(i=0;i<200;i++) {00191         av_init_packet(&pkt);00192         pkt.data = NULL; // packet data will be allocated by the encoder00193         pkt.size = 0;00194 00195         for (j = 0; j < c->frame_size; j++) {00196             samples[2*j] = (int)(sin(t) * 10000);00197 00198             for (k = 1; k < c->channels; k++)00199                 samples[2*j + k] = samples[2*j];00200             t += tincr;00201         }00202         /* encode the samples */00203         ret = avcodec_encode_audio2(c, &pkt, frame, &got_output);00204         if (ret < 0) {00205             fprintf(stderr, "Error encoding audio frame\n");00206             exit(1);00207         }00208         if (got_output) {00209             fwrite(pkt.data, 1, pkt.size, f);00210             av_free_packet(&pkt);00211         }00212     }00213 00214     /* get the delayed frames */00215     for (got_output = 1; got_output; i++) {00216         ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output);00217         if (ret < 0) {00218             fprintf(stderr, "Error encoding frame\n");00219             exit(1);00220         }00221 00222         if (got_output) {00223             fwrite(pkt.data, 1, pkt.size, f);00224             av_free_packet(&pkt);00225         }00226     }00227     fclose(f);00228 00229     av_freep(&samples);00230     avcodec_free_frame(&frame);00231     avcodec_close(c);00232     av_free(c);00233 }00234 00235 /*00236  * Audio decoding.00237  */00238 static void audio_decode_example(const char *outfilename, const char *filename)00239 {00240     AVCodec *codec;00241     AVCodecContext *c= NULL;00242     int len;00243     FILE *f, *outfile;00244     uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];00245     AVPacket avpkt;00246     AVFrame *decoded_frame = NULL;00247 00248     av_init_packet(&avpkt);00249 00250     printf("Decode audio file %s to %s\n", filename, outfilename);00251 00252     /* find the mpeg audio decoder */00253     codec = avcodec_find_decoder(AV_CODEC_ID_MP2);00254     if (!codec) {00255         fprintf(stderr, "Codec not found\n");00256         exit(1);00257     }00258 00259     c = avcodec_alloc_context3(codec);00260     if (!c) {00261         fprintf(stderr, "Could not allocate audio codec context\n");00262         exit(1);00263     }00264 00265     /* open it */00266     if (avcodec_open2(c, codec, NULL) < 0) {00267         fprintf(stderr, "Could not open codec\n");00268         exit(1);00269     }00270 00271     f = fopen(filename, "rb");00272     if (!f) {00273         fprintf(stderr, "Could not open %s\n", filename);00274         exit(1);00275     }00276     outfile = fopen(outfilename, "wb");00277     if (!outfile) {00278         av_free(c);00279         exit(1);00280     }00281 00282     /* decode until eof */00283     avpkt.data = inbuf;00284     avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f);00285 00286     while (avpkt.size > 0) {00287         int got_frame = 0;00288 00289         if (!decoded_frame) {00290             if (!(decoded_frame = avcodec_alloc_frame())) {00291                 fprintf(stderr, "Could not allocate audio frame\n");00292                 exit(1);00293             }00294         } else00295             avcodec_get_frame_defaults(decoded_frame);00296 00297         len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt);00298         if (len < 0) {00299             fprintf(stderr, "Error while decoding\n");00300             exit(1);00301         }00302         if (got_frame) {00303             /* if a frame has been decoded, output it */00304             int data_size = av_samples_get_buffer_size(NULL, c->channels,00305                                                        decoded_frame->nb_samples,00306                                                        c->sample_fmt, 1);00307             fwrite(decoded_frame->data[0], 1, data_size, outfile);00308         }00309         avpkt.size -= len;00310         avpkt.data += len;00311         avpkt.dts =00312         avpkt.pts = AV_NOPTS_VALUE;00313         if (avpkt.size < AUDIO_REFILL_THRESH) {00314             /* Refill the input buffer, to avoid trying to decode00315              * incomplete frames. Instead of this, one could also use00316              * a parser, or use a proper container format through00317              * libavformat. */00318             memmove(inbuf, avpkt.data, avpkt.size);00319             avpkt.data = inbuf;00320             len = fread(avpkt.data + avpkt.size, 1,00321                         AUDIO_INBUF_SIZE - avpkt.size, f);00322             if (len > 0)00323                 avpkt.size += len;00324         }00325     }00326 00327     fclose(outfile);00328     fclose(f);00329 00330     avcodec_close(c);00331     av_free(c);00332     avcodec_free_frame(&decoded_frame);00333 }00334 00335 /*00336  * Video encoding example00337  */00338 static void video_encode_example(const char *filename, int codec_id)00339 {00340     AVCodec *codec;00341     AVCodecContext *c= NULL;00342     int i, ret, x, y, got_output;00343     FILE *f;00344     AVFrame *frame;00345     AVPacket pkt;00346     uint8_t endcode[] = { 0, 0, 1, 0xb7 };00347 00348     printf("Encode video file %s\n", filename);00349 00350     /* find the mpeg1 video encoder */00351     codec = avcodec_find_encoder(codec_id);00352     if (!codec) {00353         fprintf(stderr, "Codec not found\n");00354         exit(1);00355     }00356 00357     c = avcodec_alloc_context3(codec);00358     if (!c) {00359         fprintf(stderr, "Could not allocate video codec context\n");00360         exit(1);00361     }00362 00363     /* put sample parameters */00364     c->bit_rate = 400000;00365     /* resolution must be a multiple of two */00366     c->width = 352;00367     c->height = 288;00368     /* frames per second */00369     c->time_base= (AVRational){1,25};00370     c->gop_size = 10; /* emit one intra frame every ten frames */00371     c->max_b_frames=1;00372     c->pix_fmt = AV_PIX_FMT_YUV420P;00373 00374     if(codec_id == AV_CODEC_ID_H264)00375         av_opt_set(c->priv_data, "preset", "slow", 0);00376 00377     /* open it */00378     if (avcodec_open2(c, codec, NULL) < 0) {00379         fprintf(stderr, "Could not open codec\n");00380         exit(1);00381     }00382 00383     f = fopen(filename, "wb");00384     if (!f) {00385         fprintf(stderr, "Could not open %s\n", filename);00386         exit(1);00387     }00388 00389     frame = avcodec_alloc_frame();00390     if (!frame) {00391         fprintf(stderr, "Could not allocate video frame\n");00392         exit(1);00393     }00394     frame->format = c->pix_fmt;00395     frame->width  = c->width;00396     frame->height = c->height;00397 00398     /* the image can be allocated by any means and av_image_alloc() is00399      * just the most convenient way if av_malloc() is to be used */00400     ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,00401                          c->pix_fmt, 32);00402     if (ret < 0) {00403         fprintf(stderr, "Could not allocate raw picture buffer\n");00404         exit(1);00405     }00406 00407     /* encode 1 second of video */00408     for(i=0;i<25;i++) {00409         av_init_packet(&pkt);00410         pkt.data = NULL;    // packet data will be allocated by the encoder00411         pkt.size = 0;00412 00413         fflush(stdout);00414         /* prepare a dummy image */00415         /* Y */00416         for(y=0;y<c->height;y++) {00417             for(x=0;x<c->width;x++) {00418                 frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;00419             }00420         }00421 00422         /* Cb and Cr */00423         for(y=0;y<c->height/2;y++) {00424             for(x=0;x<c->width/2;x++) {00425                 frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;00426                 frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;00427             }00428         }00429 00430         frame->pts = i;00431 00432         /* encode the image */00433         ret = avcodec_encode_video2(c, &pkt, frame, &got_output);00434         if (ret < 0) {00435             fprintf(stderr, "Error encoding frame\n");00436             exit(1);00437         }00438 00439         if (got_output) {00440             printf("Write frame %3d (size=%5d)\n", i, pkt.size);00441             fwrite(pkt.data, 1, pkt.size, f);00442             av_free_packet(&pkt);00443         }00444     }00445 00446     /* get the delayed frames */00447     for (got_output = 1; got_output; i++) {00448         fflush(stdout);00449 00450         ret = avcodec_encode_video2(c, &pkt, NULL, &got_output);00451         if (ret < 0) {00452             fprintf(stderr, "Error encoding frame\n");00453             exit(1);00454         }00455 00456         if (got_output) {00457             printf("Write frame %3d (size=%5d)\n", i, pkt.size);00458             fwrite(pkt.data, 1, pkt.size, f);00459             av_free_packet(&pkt);00460         }00461     }00462 00463     /* add sequence end code to have a real mpeg file */00464     fwrite(endcode, 1, sizeof(endcode), f);00465     fclose(f);00466 00467     avcodec_close(c);00468     av_free(c);00469     av_freep(&frame->data[0]);00470     avcodec_free_frame(&frame);00471     printf("\n");00472 }00473 00474 /*00475  * Video decoding example00476  */00477 00478 static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,00479                      char *filename)00480 {00481     FILE *f;00482     int i;00483 00484     f=fopen(filename,"w");00485     fprintf(f,"P5\n%d %d\n%d\n",xsize,ysize,255);00486     for(i=0;i<ysize;i++)00487         fwrite(buf + i * wrap,1,xsize,f);00488     fclose(f);00489 }00490 00491 static int decode_write_frame(const char *outfilename, AVCodecContext *avctx,00492                               AVFrame *frame, int *frame_count, AVPacket *pkt, int last)00493 {00494     int len, got_frame;00495     char buf[1024];00496 00497     len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);00498     if (len < 0) {00499         fprintf(stderr, "Error while decoding frame %d\n", *frame_count);00500         return len;00501     }00502     if (got_frame) {00503         printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count);00504         fflush(stdout);00505 00506         /* the picture is allocated by the decoder, no need to free it */00507         snprintf(buf, sizeof(buf), outfilename, *frame_count);00508         pgm_save(frame->data[0], frame->linesize[0],00509                  avctx->width, avctx->height, buf);00510         (*frame_count)++;00511     }00512     if (pkt->data) {00513         pkt->size -= len;00514         pkt->data += len;00515     }00516     return 0;00517 }00518 00519 static void video_decode_example(const char *outfilename, const char *filename)00520 {00521     AVCodec *codec;00522     AVCodecContext *c= NULL;00523     int frame_count;00524     FILE *f;00525     AVFrame *frame;00526     uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];00527     AVPacket avpkt;00528 00529     av_init_packet(&avpkt);00530 00531     /* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */00532     memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);00533 00534     printf("Decode video file %s to %s\n", filename, outfilename);00535 00536     /* find the mpeg1 video decoder */00537     codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);00538     if (!codec) {00539         fprintf(stderr, "Codec not found\n");00540         exit(1);00541     }00542 00543     c = avcodec_alloc_context3(codec);00544     if (!c) {00545         fprintf(stderr, "Could not allocate video codec context\n");00546         exit(1);00547     }00548 00549     if(codec->capabilities&CODEC_CAP_TRUNCATED)00550         c->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */00551 00552     /* For some codecs, such as msmpeg4 and mpeg4, width and height00553        MUST be initialized there because this information is not00554        available in the bitstream. */00555 00556     /* open it */00557     if (avcodec_open2(c, codec, NULL) < 0) {00558         fprintf(stderr, "Could not open codec\n");00559         exit(1);00560     }00561 00562     f = fopen(filename, "rb");00563     if (!f) {00564         fprintf(stderr, "Could not open %s\n", filename);00565         exit(1);00566     }00567 00568     frame = avcodec_alloc_frame();00569     if (!frame) {00570         fprintf(stderr, "Could not allocate video frame\n");00571         exit(1);00572     }00573 00574     frame_count = 0;00575     for(;;) {00576         avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);00577         if (avpkt.size == 0)00578             break;00579 00580         /* NOTE1: some codecs are stream based (mpegvideo, mpegaudio)00581            and this is the only method to use them because you cannot00582            know the compressed data size before analysing it.00583 00584            BUT some other codecs (msmpeg4, mpeg4) are inherently frame00585            based, so you must call them with all the data for one00586            frame exactly. You must also initialize 'width' and00587            'height' before initializing them. */00588 00589         /* NOTE2: some codecs allow the raw parameters (frame size,00590            sample rate) to be changed at any frame. We handle this, so00591            you should also take care of it */00592 00593         /* here, we use a stream based decoder (mpeg1video), so we00594            feed decoder and see if it could decode a frame */00595         avpkt.data = inbuf;00596         while (avpkt.size > 0)00597             if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0)00598                 exit(1);00599     }00600 00601     /* some codecs, such as MPEG, transmit the I and P frame with a00602        latency of one frame. You must do the following to have a00603        chance to get the last frame of the video */00604     avpkt.data = NULL;00605     avpkt.size = 0;00606     decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1);00607 00608     fclose(f);00609 00610     avcodec_close(c);00611     av_free(c);00612     avcodec_free_frame(&frame);00613     printf("\n");00614 }00615 00616 int main(int argc, char **argv)00617 {00618     const char *output_type;00619 00620     /* register all the codecs */00621     avcodec_register_all();00622 00623     if (argc < 2) {00624         printf("usage: %s output_type\n"00625                "API example program to decode/encode a media stream with libavcodec.\n"00626                "This program generates a synthetic stream and encodes it to a file\n"00627                "named test.h264, test.mp2 or test.mpg depending on output_type.\n"00628                "The encoded stream is then decoded and written to a raw data output.\n"00629                "output_type must be choosen between 'h264', 'mp2', 'mpg'.\n",00630                argv[0]);00631         return 1;00632     }00633     output_type = argv[1];00634 00635     if (!strcmp(output_type, "h264")) {00636         video_encode_example("test.h264", AV_CODEC_ID_H264);00637     } else if (!strcmp(output_type, "mp2")) {00638         audio_encode_example("test.mp2");00639         audio_decode_example("test.sw", "test.mp2");00640     } else if (!strcmp(output_type, "mpg")) {00641         video_encode_example("test.mpg", AV_CODEC_ID_MPEG1VIDEO);00642         video_decode_example("test%02d.pgm", "test.mpg");00643     } else {00644         fprintf(stderr, "Invalid output type '%s', choose between 'h264', 'mp2', or 'mpg'\n",00645                 output_type);00646         return 1;00647     }00648 00649     return 0;00650 }