美文网首页
ijkplayer 马赛克 丢帧处理

ijkplayer 马赛克 丢帧处理

作者: dozenx | 来源:发表于2020-06-10 14:33 被阅读0次

    大致思路是所有引起的包异常 都需要 设置标志位 frame_err 为1

    libavcodec/avcodec.h

    增加 extern int frame_err;

    
    +#ifndef _TEST_H
    +#define _TEST_H
    + extern int frame_err;   
    +extern int decode_err;
    +#endif
    

    libavcodec/error_resilience.c

    av_log(s->avctx, AV_LOG_INFO, "concealing %d DC, %d AC, %d MV errors in %c frame\n",
    后面加 
    frame_err=1;
    
    

    libavcodec/h264_cavlc.c

         if(zeros_left<0){
    -        av_log(h->avctx, AV_LOG_ERROR, "negative number of zero coeffs at %d %d\n", sl->mb_x, sl->mb_y);
    +        av_log(h->avctx, AV_LOG_ERROR, "frame_err=1; negative number of zero coeffs at %d %d\n", sl->mb_x, sl->mb_y);
    +       frame_err=1;
             return -1;
         }
    
    
    @@ -1110,8 +1113,9 @@ decode_intra_mb:
                 if (sl->qscale < 0) sl->qscale += max_qp + 1;
                 else                sl->qscale -= max_qp+1;
                 if (((unsigned)sl->qscale) > max_qp){
    -                av_log(h->avctx, AV_LOG_ERROR, "dquant out of range (%d) at %d %d\n", dquant, sl->mb_x, sl->mb_y);
    -                return -1;
    +                av_log(h->avctx, AV_LOG_ERROR, "frame_err=1; dquant out of range (%d) at %d %d\n", dquant, sl->mb_x, sl->mb_y);
    +frame_err=1;                
    +return -1;
                 }
             }
    
    

    libavcodec/h264_parse.c

    @@ -199,7 +199,8 @@ int ff_h264_check_intra_pred_mode(void *logctx, int top_samples_available,
             mode = left[mode];
             if (mode < 0) {
                 av_log(logctx, AV_LOG_ERROR,
    -                   "left block unavailable for requested intra mode\n");
    +                   "frame_err left block unavailable for requested intra mode\n");
    +            frame_err = 1;
                 return AVERROR_INVALIDDATA;
             }
    
    
    

    libavcodec/h264_slice.c

    +int decode_err=0;
     static const uint8_t field_scan[16+1] = {
         0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4,
         0 + 3 * 4, 1 + 1 * 4, 1 + 2 * 4, 1 + 3 * 4,
    @@ -1502,8 +1502,9 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl,
         while (h->poc.frame_num != h->poc.prev_frame_num && !h->first_field &&
                h->poc.frame_num != (h->poc.prev_frame_num + 1) % (1 << sps->log2_max_frame_num)) {
             H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
    -        av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
    +        av_log(h->avctx, AV_LOG_DEBUG, "frameerr Frame num gap %d %d\n",
                    h->poc.frame_num, h->poc.prev_frame_num);
    +        frame_err=1;
             if (!sps->gaps_in_frame_num_allowed_flag)
                 for(i=0; i<FF_ARRAY_ELEMS(h->last_pocs); i++)
                     h->last_pocs[i] = INT_MIN;
    @@ -1726,8 +1727,10 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
         sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
         if (!first_slice) {
             if (h->poc.frame_num != sl->frame_num) {
    -            av_log(h->avctx, AV_LOG_ERROR, "Frame num change from %d to %d\n",
    +            av_log(h->avctx, AV_LOG_ERROR, "frame_err Frame num change from %d to %d\n",
                        h->poc.frame_num, sl->frame_num);
    +            frame_err=1;
    +             decode_err=1;
                 return AVERROR_INVALIDDATA;
             }
         }
    @@ -2603,11 +2606,13 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
                     av_log(h->avctx, AV_LOG_DEBUG, "bytestream overread %"PTRDIFF_SPECIFIER"\n", sl->cabac.bytestream_end - sl->cabac.bytestream);
                 if (ret < 0 || sl->cabac.bytestream > sl->cabac.bytestream_end + 4) {
                     av_log(h->avctx, AV_LOG_ERROR,
    -                       "error while decoding MB %d %d, bytestream %"PTRDIFF_SPECIFIER"\n",
    +                       "errframe error while decoding MB %d %d, bytestream %"PTRDIFF_SPECIFIER"\n",
                            sl->mb_x, sl->mb_y,
                            sl->cabac.bytestream_end - sl->cabac.bytestream);
                     er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                                  sl->mb_y, ER_MB_ERROR);
    + frame_err = 1;
    +
                     return AVERROR_INVALIDDATA;
                 }
     
    @@ -2662,7 +2667,9 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
     
                 if (ret < 0) {
                     av_log(h->avctx, AV_LOG_ERROR,
    -                       "error while decoding MB %d %d\n", sl->mb_x, sl->mb_y);
    +                       " errframe decode_err error while decoding MB %d %d\n", sl->mb_x, sl->mb_y);
    +                  frame_err = 1;
    +                  decode_err = 1;
                     er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                                  sl->mb_y, ER_MB_ERROR);
                     return ret;
    

    libavcodec/svq3.c

    @@ -1565,7 +1565,8 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data,
                     mb_type += 4;
                 if (mb_type > 33 || svq3_decode_mb(s, mb_type)) {
                     av_log(s->avctx, AV_LOG_ERROR,
    -                       "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
    +                       "frameerr error while decoding MB %d %d\n", s->mb_x, s->mb_y);
    +                frame_err=1;
                     return -1;
                 }
    

    最后 在 ffplay.c处理丢帧操作
    修改 static int read_thread(void *arg)方法

     // 每次读取一个pkt,都去判断处理
            // TODO:优化,不用每次都调用
            //if (is->max_cached_duration > 0) {
             //   control_queue_duration(ffp, is);
            //}
            if (pkt->stream_index == is->audio_stream && pkt_in_play_range) {
                packet_queue_put(&is->audioq, pkt);
            } else if (pkt->stream_index == is->video_stream && pkt_in_play_range
                       && !(is->video_st && (is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC))) {
                //packet_queue_put(&is->videoq, pkt);
                if(!frame_err){
                   packet_queue_put(&is->videoq, pkt);
                  //av_log(NULL, AV_LOG_ERROR, "packet_queue_put frame_err \n");   
                }else {//release the packet when frame error during total GOP
                   av_packet_unref(pkt);
                }
                //frame_err=0;
            } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) {
                packet_queue_put(&is->subtitleq, pkt);
            } else {
                av_packet_unref(pkt);
            }
    
            ffp_statistic_l(ffp);
    
          pkt->flags = 0;
    
    
            ret = av_read_frame(ic, pkt);
    
    if(pkt->stream_index == AVMEDIA_TYPE_VIDEO&& (pkt->flags & AV_PKT_FLAG_KEY)){
                 av_log(ffp, AV_LOG_INFO, " it's i frame \n");
               frame_err=0;//这里复位
               decode_err=0;
       }
    
    
    
    

    libavformat/rtpdec.c

         if (!has_next_packet(s))
    -        av_log(s->ic, AV_LOG_WARNING,
    -               "RTP: missed %d packets\n", s->queue->seq - s->seq - 1);
    -
    +      {  av_log(s->ic, AV_LOG_WARNING,
    +               "frame_err RTP: missed %d packets\n", s->queue->seq - s->seq - 1);
    +       frame_err=1;
    +}
    
    

    统计下所有的修改地方为以下位置

    root@alpha-facekaoqin-3:/service/software/ijkplayer/android/contrib/ffmpeg-arm64# find ./ -name "*.c"   -exec grep -C 2  'frame_err' {} \; -print
        if (!has_next_packet(s))
          {  av_log(s->ic, AV_LOG_WARNING,
                   "frame_err RTP: missed %d packets\n", s->queue->seq - s->seq - 1);
        frame_err=1;
    }
        /* Parse the first packet in the queue, and dequeue it */
    ./libavformat/rtpdec.c
                    av_log(s->avctx, AV_LOG_ERROR,
                           "frameerr error while decoding MB %d %d\n", s->mb_x, s->mb_y);
                    frame_err=1;
                    return -1;
                }
    ./libavcodec/svq3.c
        if(total_coeff > (unsigned)max_coeff) {
            av_log(h->avctx, AV_LOG_ERROR, "corrupted macroblock %d %d (total_coeff=%d)\n", sl->mb_x, sl->mb_y, total_coeff);
            frame_err=1;
            return -1;
        }
    --
                            if(prefix > 25+3){
                                av_log(h->avctx, AV_LOG_ERROR, "Invalid level prefix\n");
                                frame_err=1;
                                return AVERROR_INVALIDDATA;
                            }
    --
    
        if(zeros_left<0){
            av_log(h->avctx, AV_LOG_ERROR, "frame_err=1; negative number of zero coeffs at %d %d\n", sl->mb_x, sl->mb_y);
           frame_err=1;
            return -1;
        }
    --
                else                sl->qscale -= max_qp+1;
                if (((unsigned)sl->qscale) > max_qp){
                    av_log(h->avctx, AV_LOG_ERROR, "frame_err=1; dquant out of range (%d) at %d %d\n", dquant, sl->mb_x, sl->mb_y);
    frame_err=1;                
    return -1;
                }
    ./libavcodec/h264_cavlc.c
            av_log(h->avctx, AV_LOG_DEBUG, "frameerr Frame num gap %d %d\n",
                   h->poc.frame_num, h->poc.prev_frame_num);
            frame_err=1;
            if (!sps->gaps_in_frame_num_allowed_flag)
                for(i=0; i<FF_ARRAY_ELEMS(h->last_pocs); i++)
    --
        if (!first_slice) {
            if (h->poc.frame_num != sl->frame_num) {
                av_log(h->avctx, AV_LOG_ERROR, "frame_err Frame num change from %d to %d\n",
                       h->poc.frame_num, sl->frame_num);
                frame_err=1;
                 decode_err=1;
                return AVERROR_INVALIDDATA;
    --
                    er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
                                 sl->mb_y, ER_MB_ERROR);
     frame_err = 1;
    
                    return AVERROR_INVALIDDATA;
    --
                    av_log(h->avctx, AV_LOG_ERROR,
                           " errframe decode_err error while decoding MB %d %d\n", sl->mb_x, sl->mb_y);
                      frame_err = 1;
                      decode_err = 1;
                    er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
    ./libavcodec/h264_slice.c
                mv_error++;
        }
        av_log(s->avctx, AV_LOG_INFO, "frame_err concealing %d DC, %d AC, %d MV errors in %c frame\n",
               dc_error, ac_error, mv_error, av_get_picture_type_char(s->cur_pic.f->pict_type));
        frame_err=1;
        is_intra_likely = is_intra_more_likely(s);
    
    ./libavcodec/error_resilience.c
    #include "h264_parse.h"
    #include "h264_ps.h"
    int frame_err=0;
    int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps,
                                  const int *ref_count, int slice_type_nos,
    --
            if (mode < 0) {
                av_log(logctx, AV_LOG_ERROR,
                       "frame_err left block unavailable for requested intra mode\n");
                frame_err = 1;
                return AVERROR_INVALIDDATA;
            }
    ./libavcodec/h264_parse.c
    
    
    

    相关文章

      网友评论

          本文标题:ijkplayer 马赛克 丢帧处理

          本文链接:https://www.haomeiwen.com/subject/ogfptktx.html