ffmpeg 解碼示例

相關(guān)

x264編碼
ffmpeg 編碼示例
碼流控制
h264編解碼末尾丟幀

示例

  1. 編碼前初始化,返回視頻寬高
    int* decode_init(char * in_filename)
    {
    avcodec_register_all();
    av_register_all();
    decode_frame = av_frame_alloc();
    AVPacket pkt;
    //獲取各種上下文
    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
    retu = -1;
    goto end;
    }
    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
    retu = -2;
    goto end;
    }
    //例遍流,找到流所對應(yīng)得下標(biāo)
    for (i = 0; i < ifmt_ctx->nb_streams; i++) {
    / /Create output AVStream according to input AVStream
    AVFormatContext *ofmt_ctx;
    AVStream *in_stream = ifmt_ctx->streams[i];
    AVStream *out_stream = NULL;

             if (ifmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
                 videoindex = i;
    
             }
         }
         //open decoder
         video_dec_ctx = ifmt_ctx->streams[videoindex]->codec;
         video_dec = avcodec_find_decoder(video_dec_ctx->codec_id);
         if(avcodec_open2(video_dec_ctx,video_dec,NULL)<0)
         {
             retu = -3;
             goto end;
         }
         double g_height = ifmt_ctx->streams[videoindex]->codec->height;
         double g_width = ifmt_ctx->streams[videoindex]->codec->width;
    
         int* wh = malloc(sizeof(int)*2);
         wh[0] = g_width;
         wh[1] = g_height;
     end: 
         if(retu != 0)
             return NULL;
         else
             return wh;
     }   
    
  2. 解碼一幀
    AVFrame* decode_next()
    {
    if(decode_frame!=NULL)
    av_frame_unref(decode_frame);
    int ret = 0;
    int got_frame = 0;
    int error_time = 0;
    while(1)
    {
    //Get an AVPacket
    if (av_read_frame(ifmt_ctx, &pkt) < 0)
    {
    av_free_packet(&pkt);
    goto decode_free;
    }
    if (pkt.stream_index == videoindex)
    {
    ret = avcodec_decode_video2(video_dec_ctx,decode_frame, &got_frame, &pkt);
    if(got_frame)
    goto decode_success;
    else
    {
    if(failed_times ++<30)
    continue;
    else
    goto decode_free;
    }
    }
    av_free_packet(&pkt);
    }
    decode_free:
    av_free_packet(&pkt);
    return NULL;

     decode_success:
         return decode_frame;
     }
    

僅僅是在讀取packet之后就停止解碼會丟幀,參看
所以要在讀取packet失敗之后接著調(diào)用解碼,獲取剩余的幀。使用一個變量failed_times 記錄編碼器中存在的幀數(shù)。在讀取結(jié)束之后接著調(diào)用failed_times 次avcodec_decode_video2
int failed_times = 0;
int read_packet_failed = 0;
AVFrame* decode_next()
{
if(decode_frame!=NULL;
av_frame_unref(decode_frame);
int ret = 0;
int got_frame = 0;
int error_time = 0;
while(1)
{
if (av_read_frame(ifmt_ctx, &pkt) < 0)
{
read_packet_failed = 1;
av_free_packet(&pkt);
if(failed_times > 0)
{
failed_times--;
goto decode;
}
else
goto decode_free;
}
if (pkt.stream_index == videoindex)
{
decode:
ret = avcodec_decode_video2(video_dec_ctx,decode_frame, &got_frame, &pkt);
if(got_frame)
goto decode_success;
else
{
if(read_packet_failed)
goto decode_free;
else
{
failed_times ++;
continue;
}
else
goto decode_free;
}
}
av_free_packet(&pkt);
}
decode_free:
av_free_packet(&pkt);
return NULL;
decode_success:
return decode_frame;
}

  1. 解碼完成之后釋放
    int decode_release() { avcodec_close(video_dec_ctx); avformat_close_input(&ifmt_ctx); if(decode_frame!=NULL) { av_frame_free(&decode_frame); decode_frame = NULL; } }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容