码迷,mamicode.com
首页 > 其他好文 > 详细

FFMPEG实现的转码程序

时间:2017-08-09 20:06:23      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:rewrite   show   buffers   leave   without   could   pad   output   context   

本例子是由FFEMPG的doc/example例子transcode.c修改而来,可以根据需求任意转换音视频的编码。

 

原来的例子的作用更类似于remux,并没有实现转码的功能,只是实现了格式转换,比如ts转avi等。并不能实现音视频编码格式的转换,比如将h264转为mpeg2。

 

FFMPEG转码的实现有多种方式:

一种方式是:流解复用->视频+音频流->解码->YUV/PCM等->视音频编码->重新生成的音视频流->复用->流

另一种方式依赖AVFilter,这一部分在另外的几篇文章中解释怎么用。虽然AVFilter学习起来可能比较困难,但是在实际的编程应用中,依靠AVFilter做转码效率比第一种方式高,并且解码的CPU和时间消耗也少的多。所以,还是建议好好学习这部分的,毕竟我一直觉得FFMPEG的强项就是解码和转码。

 

 

本例子是视频mpeg2转h264,音频mpegaudio转g711。

 

[cpp] view plain copy
 
 print?
  1. <span style="font-family:SimHei;font-size:18px;">/* 
  2. * based on FFMPEG transcode.c 
  3. * modified by tongli 
  4. */  
  5. #include <stdio.h>  
  6. #include "snprintf.h"  
  7. extern "C"  
  8. {  
  9. #include <libavcodec/avcodec.h>  
  10. #include <libavformat/avformat.h>  
  11. #include <libavfilter/avfiltergraph.h>  
  12. #include <libavfilter/avcodec.h>  
  13. #include <libavfilter/buffersink.h>  
  14. #include <libavfilter/buffersrc.h>  
  15. #include <libavutil/opt.h>  
  16. #include <libavutil/pixdesc.h>  
  17. }  
  18. static AVFormatContext *ifmt_ctx;  
  19. static AVFormatContext *ofmt_ctx;  
  20. typedef struct FilteringContext {  
  21.     AVFilterContext *buffersink_ctx;  
  22.     AVFilterContext *buffersrc_ctx;  
  23.     AVFilterGraph *filter_graph;  
  24. } FilteringContext;  
  25. static FilteringContext *filter_ctx;  
  26.   
  27. static int open_input_file(const char *filename)  
  28. {  
  29.     int ret;  
  30.     unsigned int i;  
  31.   
  32.     ifmt_ctx = NULL;  
  33.     if ((ret = avformat_open_input(&ifmt_ctx, filename, NULL, NULL)) < 0) {  
  34.         av_log(NULL, AV_LOG_ERROR, "Cannot open input file\n");  
  35.         return ret;  
  36.     }  
  37.   
  38.     if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) {  
  39.         av_log(NULL, AV_LOG_ERROR, "Cannot find stream information\n");  
  40.         return ret;  
  41.     }  
  42.   
  43.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
  44.         AVStream *stream;  
  45.         AVCodecContext *codec_ctx;  
  46.         stream = ifmt_ctx->streams[i];  
  47.         codec_ctx = stream->codec;  
  48.         /* Reencode video & audio and remux subtitles etc. */  
  49.         if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO  
  50.             || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {  
  51.             /* Open decoder */  
  52.             ret = avcodec_open2(codec_ctx,  
  53.                 avcodec_find_decoder(codec_ctx->codec_id), NULL);  
  54.             if (ret < 0) {  
  55.                 av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);  
  56.                 return ret;  
  57.             }  
  58.         }  
  59.     }  
  60.   
  61.     av_dump_format(ifmt_ctx, 0, filename, 0);  
  62.     return 0;  
  63. }  
  64.   
  65. static int open_output_file(const char *filename)  
  66. {  
  67.     AVStream *out_stream;  
  68.     AVStream *in_stream;  
  69.     AVCodecContext *dec_ctx, *enc_ctx;  
  70.     AVCodec *encoder;  
  71.     int ret;  
  72.     unsigned int i;  
  73.   
  74.     ofmt_ctx = NULL;  
  75.     avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);  
  76.     if (!ofmt_ctx) {  
  77.         av_log(NULL, AV_LOG_ERROR, "Could not create output context\n");  
  78.         return AVERROR_UNKNOWN;  
  79.     }  
  80.   
  81.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
  82.         out_stream = avformat_new_stream(ofmt_ctx, NULL);  
  83.         if (!out_stream) {  
  84.             av_log(NULL, AV_LOG_ERROR, "Failed allocating output stream\n");  
  85.             return AVERROR_UNKNOWN;  
  86.         }  
  87.   
  88.         in_stream = ifmt_ctx->streams[i];  
  89.         dec_ctx = in_stream->codec;  
  90.         enc_ctx = out_stream->codec;  
  91.   
  92.         if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)   
  93.         {  
  94.             encoder = avcodec_find_encoder(AV_CODEC_ID_H264);  
  95.             if (!encoder) {  
  96.                 av_log(NULL, AV_LOG_FATAL, "Neccessary encoder not found\n");  
  97.                 return AVERROR_INVALIDDATA;  
  98.             }  
  99.   
  100.             enc_ctx->height = dec_ctx->height;  
  101.             enc_ctx->width = dec_ctx->width;  
  102.             enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio;  
  103.                   
  104.             enc_ctx->pix_fmt = encoder->pix_fmts[0];  
  105.                   
  106.             enc_ctx->time_base = dec_ctx->time_base;  
  107.   
  108.             enc_ctx->me_range = 16;  
  109.             enc_ctx->max_qdiff = 4;  
  110.             enc_ctx->qmin = 10;  
  111.             enc_ctx->qmax = 51;  
  112.             enc_ctx->qcompress = 0.6;  
  113.             enc_ctx->refs = 3;  
  114.             enc_ctx->bit_rate = 500000;  
  115.               
  116.             ret = avcodec_open2(enc_ctx, encoder, NULL);  
  117.             if (ret < 0) {  
  118.                 av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);  
  119.                 return ret;  
  120.             }  
  121.         }  
  122.         else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) {  
  123.             av_log(NULL, AV_LOG_FATAL, "Elementary stream #%d is of unknown type, cannot proceed\n", i);  
  124.             return AVERROR_INVALIDDATA;  
  125.         }  
  126.         else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO)  
  127.         {  
  128.             encoder = avcodec_find_encoder(AV_CODEC_ID_PCM_ALAW);  
  129.             enc_ctx->sample_rate = dec_ctx->sample_rate;  
  130.             enc_ctx->channel_layout = dec_ctx->channel_layout;  
  131.             enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout);  
  132.             enc_ctx->sample_fmt = encoder->sample_fmts[0];  
  133.             AVRational ar = { 1, enc_ctx->sample_rate };  
  134.             enc_ctx->time_base = ar;  
  135.   
  136.             ret = avcodec_open2(enc_ctx, encoder, NULL);  
  137.             if (ret < 0) {  
  138.                 av_log(NULL, AV_LOG_ERROR, "Cannot open video encoder for stream #%u\n", i);  
  139.                 return ret;  
  140.             }  
  141.         }  
  142.         else {  
  143.             ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec,  
  144.                 ifmt_ctx->streams[i]->codec);  
  145.             if (ret < 0) {  
  146.                 av_log(NULL, AV_LOG_ERROR, "Copying stream context failed\n");  
  147.                 return ret;  
  148.             }  
  149.         }  
  150.   
  151.         if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)  
  152.             enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  153.   
  154.     }  
  155.     av_dump_format(ofmt_ctx, 0, filename, 1);  
  156.   
  157.     if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) {  
  158.         ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);  
  159.         if (ret < 0) {  
  160.             av_log(NULL, AV_LOG_ERROR, "Could not open output file ‘%s‘", filename);  
  161.             return ret;  
  162.         }  
  163.     }  
  164.   
  165.     /* init muxer, write output file header */  
  166.     ret = avformat_write_header(ofmt_ctx, NULL);  
  167.     if (ret < 0) {  
  168.         av_log(NULL, AV_LOG_ERROR, "Error occurred when opening output file\n");  
  169.         return ret;  
  170.     }  
  171.   
  172.     return 0;  
  173. }  
  174.   
  175. static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx,  
  176.     AVCodecContext *enc_ctx, const char *filter_spec)  
  177. {  
  178.     char args[512];  
  179.     int ret = 0;  
  180.     AVFilter *buffersrc = NULL;  
  181.     AVFilter *buffersink = NULL;  
  182.     AVFilterContext *buffersrc_ctx = NULL;  
  183.     AVFilterContext *buffersink_ctx = NULL;  
  184.     AVFilterInOut *outputs = avfilter_inout_alloc();  
  185.     AVFilterInOut *inputs = avfilter_inout_alloc();  
  186.     AVFilterGraph *filter_graph = avfilter_graph_alloc();  
  187.   
  188.     if (!outputs || !inputs || !filter_graph) {  
  189.         ret = AVERROR(ENOMEM);  
  190.         goto end;  
  191.     }  
  192.   
  193.     if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {  
  194.         buffersrc = avfilter_get_by_name("buffer");  
  195.         buffersink = avfilter_get_by_name("buffersink");  
  196.         if (!buffersrc || !buffersink) {  
  197.             av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");  
  198.             ret = AVERROR_UNKNOWN;  
  199.             goto end;  
  200.         }  
  201.   
  202.         snprintf(args, sizeof(args),  
  203.             "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",  
  204.             dec_ctx->width, dec_ctx->height, dec_ctx->pix_fmt,  
  205.             dec_ctx->time_base.num, dec_ctx->time_base.den,  
  206.             dec_ctx->sample_aspect_ratio.num,  
  207.             dec_ctx->sample_aspect_ratio.den);  
  208.   
  209.         ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",  
  210.             args, NULL, filter_graph);  
  211.         if (ret < 0) {  
  212.             av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");  
  213.             goto end;  
  214.         }  
  215.   
  216.         ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",  
  217.             NULL, NULL, filter_graph);  
  218.         if (ret < 0) {  
  219.             av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");  
  220.             goto end;  
  221.         }  
  222.   
  223.         ret = av_opt_set_bin(buffersink_ctx, "pix_fmts",  
  224.             (uint8_t*)&enc_ctx->pix_fmt, sizeof(enc_ctx->pix_fmt),  
  225.             AV_OPT_SEARCH_CHILDREN);  
  226.         if (ret < 0) {  
  227.             av_log(NULL, AV_LOG_ERROR, "Cannot set output pixel format\n");  
  228.             goto end;  
  229.         }  
  230.     }  
  231.     else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {  
  232.         buffersrc = avfilter_get_by_name("abuffer");  
  233.         buffersink = avfilter_get_by_name("abuffersink");  
  234.         if (!buffersrc || !buffersink) {  
  235.             av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");  
  236.             ret = AVERROR_UNKNOWN;  
  237.             goto end;  
  238.         }  
  239.   
  240.         if (!dec_ctx->channel_layout)  
  241.             dec_ctx->channel_layout =  
  242.             av_get_default_channel_layout(dec_ctx->channels);  
  243.         snprintf(args, sizeof(args),  
  244.             "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64,  
  245.             dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate,  
  246.             av_get_sample_fmt_name(dec_ctx->sample_fmt),  
  247.             dec_ctx->channel_layout);  
  248.         ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",  
  249.             args, NULL, filter_graph);  
  250.         if (ret < 0) {  
  251.             av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer source\n");  
  252.             goto end;  
  253.         }  
  254.   
  255.         ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",  
  256.             NULL, NULL, filter_graph);  
  257.         if (ret < 0) {  
  258.             av_log(NULL, AV_LOG_ERROR, "Cannot create audio buffer sink\n");  
  259.             goto end;  
  260.         }  
  261.   
  262.         ret = av_opt_set_bin(buffersink_ctx, "sample_fmts",  
  263.             (uint8_t*)&enc_ctx->sample_fmt, sizeof(enc_ctx->sample_fmt),  
  264.             AV_OPT_SEARCH_CHILDREN);  
  265.         if (ret < 0) {  
  266.             av_log(NULL, AV_LOG_ERROR, "Cannot set output sample format\n");  
  267.             goto end;  
  268.         }  
  269.   
  270.         ret = av_opt_set_bin(buffersink_ctx, "channel_layouts",  
  271.             (uint8_t*)&enc_ctx->channel_layout,  
  272.             sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN);  
  273.         if (ret < 0) {  
  274.             av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n");  
  275.             goto end;  
  276.         }  
  277.   
  278.         ret = av_opt_set_bin(buffersink_ctx, "sample_rates",  
  279.             (uint8_t*)&enc_ctx->sample_rate, sizeof(enc_ctx->sample_rate),  
  280.             AV_OPT_SEARCH_CHILDREN);  
  281.         if (ret < 0) {  
  282.             av_log(NULL, AV_LOG_ERROR, "Cannot set output sample rate\n");  
  283.             goto end;  
  284.         }  
  285.     }  
  286.     else {  
  287.         ret = AVERROR_UNKNOWN;  
  288.         goto end;  
  289.     }  
  290.   
  291.     /* Endpoints for the filter graph. */  
  292.     outputs->name = av_strdup("in");  
  293.     outputs->filter_ctx = buffersrc_ctx;  
  294.     outputs->pad_idx = 0;  
  295.     outputs->next = NULL;  
  296.   
  297.     inputs->name = av_strdup("out");  
  298.     inputs->filter_ctx = buffersink_ctx;  
  299.     inputs->pad_idx = 0;  
  300.     inputs->next = NULL;  
  301.   
  302.     if (!outputs->name || !inputs->name) {  
  303.         ret = AVERROR(ENOMEM);  
  304.         goto end;  
  305.     }  
  306.   
  307.     if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_spec,  
  308.         &inputs, &outputs, NULL)) < 0)  
  309.         goto end;  
  310.   
  311.     if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)  
  312.         goto end;  
  313.   
  314.     /* Fill FilteringContext */  
  315.     fctx->buffersrc_ctx = buffersrc_ctx;  
  316.     fctx->buffersink_ctx = buffersink_ctx;  
  317.     fctx->filter_graph = filter_graph;  
  318.   
  319. end:  
  320.     avfilter_inout_free(&inputs);  
  321.     avfilter_inout_free(&outputs);  
  322.   
  323.     return ret;  
  324. }  
  325.   
  326. static int init_filters(void)  
  327. {  
  328.     const char *filter_spec;  
  329.     unsigned int i;  
  330.     int ret;  
  331.     filter_ctx = (FilteringContext*)av_malloc_array(ifmt_ctx->nb_streams, sizeof(*filter_ctx));  
  332.     if (!filter_ctx)  
  333.         return AVERROR(ENOMEM);  
  334.   
  335.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
  336.         filter_ctx[i].buffersrc_ctx = NULL;  
  337.         filter_ctx[i].buffersink_ctx = NULL;  
  338.         filter_ctx[i].filter_graph = NULL;  
  339.         if (!(ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO  
  340.             || ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO))  
  341.             continue;  
  342.   
  343.   
  344.         if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)  
  345.             filter_spec = "null"; /* passthrough (dummy) filter for video */  
  346.         else  
  347.             filter_spec = "anull"; /* passthrough (dummy) filter for audio */  
  348.         ret = init_filter(&filter_ctx[i], ifmt_ctx->streams[i]->codec,  
  349.             ofmt_ctx->streams[i]->codec, filter_spec);  
  350.         if (ret)  
  351.             return ret;  
  352.     }  
  353.     return 0;  
  354. }  
  355.   
  356. static int encode_write_frame(AVFrame *filt_frame, unsigned int stream_index, int *got_frame) {  
  357.     int ret;  
  358.     int got_frame_local;  
  359.     AVPacket enc_pkt;  
  360.     int(*enc_func)(AVCodecContext *, AVPacket *, const AVFrame *, int *) =  
  361.         (ifmt_ctx->streams[stream_index]->codec->codec_type ==  
  362.         AVMEDIA_TYPE_VIDEO) ? avcodec_encode_video2 : avcodec_encode_audio2;  
  363.   
  364.     if (!got_frame)  
  365.         got_frame = &got_frame_local;  
  366.   
  367.     av_log(NULL, AV_LOG_INFO, "Encoding frame\n");  
  368.     /* encode filtered frame */  
  369.     enc_pkt.data = NULL;  
  370.     enc_pkt.size = 0;  
  371.     av_init_packet(&enc_pkt);  
  372.     ret = enc_func(ofmt_ctx->streams[stream_index]->codec, &enc_pkt,  
  373.         filt_frame, got_frame);  
  374.     av_frame_free(&filt_frame);  
  375.     if (ret < 0)  
  376.         return ret;  
  377.     if (!(*got_frame))  
  378.         return 0;  
  379.   
  380.     /* prepare packet for muxing */  
  381.     enc_pkt.stream_index = stream_index;  
  382.     av_packet_rescale_ts(&enc_pkt,  
  383.         ofmt_ctx->streams[stream_index]->codec->time_base,  
  384.         ofmt_ctx->streams[stream_index]->time_base);  
  385.   
  386.     av_log(NULL, AV_LOG_DEBUG, "Muxing frame\n");  
  387.     /* mux encoded frame */  
  388.     ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);  
  389.     return ret;  
  390. }  
  391.   
  392. static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)  
  393. {  
  394.     int ret;  
  395.     AVFrame *filt_frame;  
  396.   
  397.     av_log(NULL, AV_LOG_INFO, "Pushing decoded frame to filters\n");  
  398.     /* push the decoded frame into the filtergraph */  
  399.     ret = av_buffersrc_add_frame_flags(filter_ctx[stream_index].buffersrc_ctx,  
  400.         frame, 0);  
  401.     if (ret < 0) {  
  402.         av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n");  
  403.         return ret;  
  404.     }  
  405.   
  406.     /* pull filtered frames from the filtergraph */  
  407.     while (1) {  
  408.         filt_frame = av_frame_alloc();  
  409.         if (!filt_frame) {  
  410.             ret = AVERROR(ENOMEM);  
  411.             break;  
  412.         }  
  413.         av_log(NULL, AV_LOG_INFO, "Pulling filtered frame from filters\n");  
  414.         ret = av_buffersink_get_frame(filter_ctx[stream_index].buffersink_ctx,  
  415.             filt_frame);  
  416.         if (ret < 0) {  
  417.             /* if no more frames for output - returns AVERROR(EAGAIN) 
  418.             * if flushed and no more frames for output - returns AVERROR_EOF 
  419.             * rewrite retcode to 0 to show it as normal procedure completion 
  420.             */  
  421.             if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)  
  422.                 ret = 0;  
  423.             av_frame_free(&filt_frame);  
  424.             break;  
  425.         }  
  426.   
  427.         filt_frame->pict_type = AV_PICTURE_TYPE_NONE;  
  428.         ret = encode_write_frame(filt_frame, stream_index, NULL);  
  429.         if (ret < 0)  
  430.             break;  
  431.     }  
  432.   
  433.     return ret;  
  434. }  
  435.   
  436. static int flush_encoder(unsigned int stream_index)  
  437. {  
  438.     int ret;  
  439.     int got_frame;  
  440.   
  441.     if (!(ofmt_ctx->streams[stream_index]->codec->codec->capabilities &  
  442.         CODEC_CAP_DELAY))  
  443.         return 0;  
  444.   
  445.     while (1) {  
  446.         av_log(NULL, AV_LOG_INFO, "Flushing stream #%u encoder\n", stream_index);  
  447.         ret = encode_write_frame(NULL, stream_index, &got_frame);  
  448.         if (ret < 0)  
  449.             break;  
  450.         if (!got_frame)  
  451.             return 0;  
  452.     }  
  453.     return ret;  
  454. }  
  455.   
  456. int main(int argc, char **argv)  
  457. {  
  458.     int ret;  
  459.     AVPacket packet; //= { .data = NULL, .size = 0 };  
  460.     packet.data = NULL;  
  461.     packet.size = 0;  
  462.     AVFrame *frame = NULL;  
  463.     enum AVMediaType type;  
  464.     unsigned int stream_index;  
  465.     unsigned int i;  
  466.     int got_frame;  
  467.     int(*dec_func)(AVCodecContext *, AVFrame *, int *, const AVPacket *);  
  468.   
  469.     av_register_all();  
  470.     avfilter_register_all();  
  471.   
  472.     if ((ret = open_input_file("test.ts")) < 0)  
  473.         goto end;  
  474.     if ((ret = open_output_file("test.avi")) < 0)  
  475.         goto end;  
  476.     if ((ret = init_filters()) < 0)  
  477.         goto end;  
  478.   
  479.     /* read all packets */  
  480.     while (1) {  
  481.         if ((ret = av_read_frame(ifmt_ctx, &packet)) < 0)  
  482.             break;  
  483.         stream_index = packet.stream_index;  
  484.         type = ifmt_ctx->streams[packet.stream_index]->codec->codec_type;  
  485.         av_log(NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index %u\n",  
  486.             stream_index);  
  487.   
  488.         if (filter_ctx[stream_index].filter_graph) {  
  489.             av_log(NULL, AV_LOG_DEBUG, "Going to reencode&filter the frame\n");  
  490.             frame = av_frame_alloc();  
  491.             if (!frame) {  
  492.                 ret = AVERROR(ENOMEM);  
  493.                 break;  
  494.             }  
  495.             av_packet_rescale_ts(&packet,  
  496.                 ifmt_ctx->streams[stream_index]->time_base,  
  497.                 ifmt_ctx->streams[stream_index]->codec->time_base);  
  498.             dec_func = (type == AVMEDIA_TYPE_VIDEO) ? avcodec_decode_video2 :  
  499.                 avcodec_decode_audio4;  
  500.             ret = dec_func(ifmt_ctx->streams[stream_index]->codec, frame,  
  501.                 &got_frame, &packet);  
  502.             if (ret < 0) {  
  503.                 av_frame_free(&frame);  
  504.                 av_log(NULL, AV_LOG_ERROR, "Decoding failed\n");  
  505.                 break;  
  506.             }  
  507.   
  508.             if (got_frame) {  
  509.                 frame->pts = av_frame_get_best_effort_timestamp(frame);  
  510.                 ret = filter_encode_write_frame(frame, stream_index);  
  511.                 av_frame_free(&frame);  
  512.                 if (ret < 0)  
  513.                     goto end;  
  514.             }  
  515.             else {  
  516.                 av_frame_free(&frame);  
  517.             }  
  518.         }  
  519.         else {  
  520.             /* remux this frame without reencoding */  
  521.             av_packet_rescale_ts(&packet,  
  522.                 ifmt_ctx->streams[stream_index]->time_base,  
  523.                 ofmt_ctx->streams[stream_index]->time_base);  
  524.   
  525.             ret = av_interleaved_write_frame(ofmt_ctx, &packet);  
  526.             if (ret < 0)  
  527.                 goto end;  
  528.         }  
  529.         av_free_packet(&packet);  
  530.     }  
  531.   
  532.     /* flush filters and encoders */  
  533.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
  534.         /* flush filter */  
  535.         if (!filter_ctx[i].filter_graph)  
  536.             continue;  
  537.         ret = filter_encode_write_frame(NULL, i);  
  538.         if (ret < 0) {  
  539.             av_log(NULL, AV_LOG_ERROR, "Flushing filter failed\n");  
  540.             goto end;  
  541.         }  
  542.   
  543.         /* flush encoder */  
  544.         ret = flush_encoder(i);  
  545.         if (ret < 0) {  
  546.             av_log(NULL, AV_LOG_ERROR, "Flushing encoder failed\n");  
  547.             goto end;  
  548.         }  
  549.     }  
  550.   
  551.     av_write_trailer(ofmt_ctx);  
  552. end:  
  553.     av_free_packet(&packet);  
  554.     av_frame_free(&frame);  
  555.     for (i = 0; i < ifmt_ctx->nb_streams; i++) {  
  556.         avcodec_close(ifmt_ctx->streams[i]->codec);  
  557.         if (ofmt_ctx && ofmt_ctx->nb_streams > i && ofmt_ctx->streams[i] && ofmt_ctx->streams[i]->codec)  
  558.             avcodec_close(ofmt_ctx->streams[i]->codec);  
  559.         if (filter_ctx && filter_ctx[i].filter_graph)  
  560.             avfilter_graph_free(&filter_ctx[i].filter_graph);  
  561.     }  
  562.     av_free(filter_ctx);  
  563.     avformat_close_input(&ifmt_ctx);  
  564.     if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))  
  565.         avio_closep(&ofmt_ctx->pb);  
  566.     avformat_free_context(ofmt_ctx);  
  567.   
  568.     if (ret < 0)  
  569.         av_log(NULL, AV_LOG_ERROR, "Error occurred: %s\n"); //av_err2str(ret));  
  570.   
  571.     return ret ? 1 : 0;  
  572. }  
  573.   
  574. </span>  

 

 

源代码下载:

csdn工程:http://download.csdn.NET/detail/rootusers/8425619

from:http://blog.csdn.net/rootusers/article/details/43488827

FFMPEG实现的转码程序

标签:rewrite   show   buffers   leave   without   could   pad   output   context   

原文地址:http://www.cnblogs.com/lidabo/p/7327113.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!