Vector ffmpeg H.264解码器中运动矢量的修改

Vector ffmpeg H.264解码器中运动矢量的修改,vector,ffmpeg,h.264,motion,decoder,Vector,Ffmpeg,H.264,Motion,Decoder,出于研究目的,我试图在解码过程中进行运动补偿之前,修改每个p帧和B帧的H.264运动矢量(MVs)。为此,我使用FFmpeg。修改的一个示例是将每个MV替换为其原始空间邻居,然后使用生成的MV进行运动补偿,而不是原始MV。请适当地指示我 到目前为止,我已经能够在文件/libavcodec/h264_cavlc.c中对MVs进行简单的修改。在函数中,ff_h264_decode_mb_cavlc(),修改mx和my变量,例如,通过增加它们的值来修改解码期间使用的MVs 例如,如下所示,mx和my值

出于研究目的,我试图在解码过程中进行运动补偿之前,修改每个p帧和B帧的H.264运动矢量(MVs)。为此,我使用FFmpeg。修改的一个示例是将每个MV替换为其原始空间邻居,然后使用生成的MV进行运动补偿,而不是原始MV。请适当地指示我

到目前为止,我已经能够在文件/libavcodec/h264_cavlc.c中对MVs进行简单的修改。在函数中,ff_h264_decode_mb_cavlc(),修改mxmy变量,例如,通过增加它们的值来修改解码期间使用的MVs

例如,如下所示,mxmy值增加50,从而延长解码器中使用的mv

mx += get_se_golomb(&s->gb)+50;
my += get_se_golomb(&s->gb)+50;
然而,在这方面,我不知道如何访问mxmy的邻居,以进行我在第一段中提到的空间平均值分析。我相信这样做的关键在于操纵数组,mv\u缓存

if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
       s->avctx->hwaccel ||
       s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
       s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
       s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) {
        //av_log(s->avctx, AV_LOG_DEBUG, "ff_er_frame_end in er.c\n"); //KG
        if(s->pict_type==AV_PICTURE_TYPE_P)
            mean_mv(s);
        return;
static void mean_mv(MpegEncContext *s){
    //uint8_t fixed[s->mb_stride * s->mb_height];
    //const int mb_stride = s->mb_stride;
    const int mb_width = s->mb_width;
    const int mb_height= s->mb_height;
    int mb_x, mb_y, mot_step, mot_stride;

    //av_log(s->avctx, AV_LOG_DEBUG, "mean_mv\n"); //KG

    set_mv_strides(s, &mot_step, &mot_stride);

    for(mb_y=0; mb_y<s->mb_height; mb_y++){
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
            const int mb_xy= mb_x + mb_y*s->mb_stride;
            const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
            int mv_predictor[4][2]={{0}};
            int ref[4]={0};
            int pred_count=0;
            int m, n;

            if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) continue;
            //if(!(s->error_status_table[mb_xy]&MV_ERROR)){
            //if (1){
            if(mb_x>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-1)];
                pred_count++;
            }

            if(mb_x+1<mb_width){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+1)];
                pred_count++;
            }

            if(mb_y>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_stride)];
                pred_count++;
            }

            if(mb_y+1<mb_height){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_stride)];
                pred_count++;
            }

            if(pred_count==0) continue;

            if(pred_count>=1){
                int sum_x=0, sum_y=0, sum_r=0;
                int k;

                for(k=0; k<pred_count; k++){
                    sum_x+= mv_predictor[k][0]; // Sum all the MVx from MVs avail. for EC
                    sum_y+= mv_predictor[k][1]; // Sum all the MVy from MVs avail. for EC
                    sum_r+= ref[k];
                    // if(k && ref[k] != ref[k-1])
                    // goto skip_mean_and_median;
                }

                mv_predictor[pred_count][0] = sum_x/k;
                mv_predictor[pred_count][1] = sum_y/k;
                ref         [pred_count]    = sum_r/k;
            }

            s->mv[0][0][0] = mv_predictor[pred_count][0];
            s->mv[0][0][1] = mv_predictor[pred_count][1];

            for(m=0; m<mot_step; m++){
                for(n=0; n<mot_step; n++){
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][0] = s->mv[0][0][0];
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][1] = s->mv[0][0][1];
                }
            }

            decode_mb(s, ref[pred_count]);

            //}
        }
    }
}
我执行的另一个实验在文件中,libavcodec/error\u resilience.c。基于guess\u mv()函数,我创建了一个新函数,mean\u mv(),它在第一个if语句的ff\u er\u frame\u end()中执行。如果其中一个条件是零错误计数(s->error\u count==0),则第一个if语句退出函数ff\u er\u frame\u end()。但是,我决定在此时插入我的mean_mv()函数,以便在错误计数为零时始终执行该函数。这个实验在某种程度上产生了我想要的结果,因为我可以开始在视频的顶部看到瑕疵,但它们仅限于右上角。我猜我插入的函数没有完成,以满足播放期限或其他要求

下面是修改后的if语句。唯一增加的是我的函数,平均值

if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
       s->avctx->hwaccel ||
       s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
       s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
       s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) {
        //av_log(s->avctx, AV_LOG_DEBUG, "ff_er_frame_end in er.c\n"); //KG
        if(s->pict_type==AV_PICTURE_TYPE_P)
            mean_mv(s);
        return;
static void mean_mv(MpegEncContext *s){
    //uint8_t fixed[s->mb_stride * s->mb_height];
    //const int mb_stride = s->mb_stride;
    const int mb_width = s->mb_width;
    const int mb_height= s->mb_height;
    int mb_x, mb_y, mot_step, mot_stride;

    //av_log(s->avctx, AV_LOG_DEBUG, "mean_mv\n"); //KG

    set_mv_strides(s, &mot_step, &mot_stride);

    for(mb_y=0; mb_y<s->mb_height; mb_y++){
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
            const int mb_xy= mb_x + mb_y*s->mb_stride;
            const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
            int mv_predictor[4][2]={{0}};
            int ref[4]={0};
            int pred_count=0;
            int m, n;

            if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) continue;
            //if(!(s->error_status_table[mb_xy]&MV_ERROR)){
            //if (1){
            if(mb_x>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-1)];
                pred_count++;
            }

            if(mb_x+1<mb_width){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+1)];
                pred_count++;
            }

            if(mb_y>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_stride)];
                pred_count++;
            }

            if(mb_y+1<mb_height){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_stride)];
                pred_count++;
            }

            if(pred_count==0) continue;

            if(pred_count>=1){
                int sum_x=0, sum_y=0, sum_r=0;
                int k;

                for(k=0; k<pred_count; k++){
                    sum_x+= mv_predictor[k][0]; // Sum all the MVx from MVs avail. for EC
                    sum_y+= mv_predictor[k][1]; // Sum all the MVy from MVs avail. for EC
                    sum_r+= ref[k];
                    // if(k && ref[k] != ref[k-1])
                    // goto skip_mean_and_median;
                }

                mv_predictor[pred_count][0] = sum_x/k;
                mv_predictor[pred_count][1] = sum_y/k;
                ref         [pred_count]    = sum_r/k;
            }

            s->mv[0][0][0] = mv_predictor[pred_count][0];
            s->mv[0][0][1] = mv_predictor[pred_count][1];

            for(m=0; m<mot_step; m++){
                for(n=0; n<mot_step; n++){
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][0] = s->mv[0][0][0];
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][1] = s->mv[0][0][1];
                }
            }

            decode_mb(s, ref[pred_count]);

            //}
        }
    }
}
下面是我基于猜测创建的平均值函数

if(!s->error_recognition || s->error_count==0 || s->avctx->lowres ||
       s->avctx->hwaccel ||
       s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ||
       s->picture_structure != PICT_FRAME || // we dont support ER of field pictures yet, though it should not crash if enabled
       s->error_count==3*s->mb_width*(s->avctx->skip_top + s->avctx->skip_bottom)) {
        //av_log(s->avctx, AV_LOG_DEBUG, "ff_er_frame_end in er.c\n"); //KG
        if(s->pict_type==AV_PICTURE_TYPE_P)
            mean_mv(s);
        return;
static void mean_mv(MpegEncContext *s){
    //uint8_t fixed[s->mb_stride * s->mb_height];
    //const int mb_stride = s->mb_stride;
    const int mb_width = s->mb_width;
    const int mb_height= s->mb_height;
    int mb_x, mb_y, mot_step, mot_stride;

    //av_log(s->avctx, AV_LOG_DEBUG, "mean_mv\n"); //KG

    set_mv_strides(s, &mot_step, &mot_stride);

    for(mb_y=0; mb_y<s->mb_height; mb_y++){
        for(mb_x=0; mb_x<s->mb_width; mb_x++){
            const int mb_xy= mb_x + mb_y*s->mb_stride;
            const int mot_index= (mb_x + mb_y*mot_stride) * mot_step;
            int mv_predictor[4][2]={{0}};
            int ref[4]={0};
            int pred_count=0;
            int m, n;

            if(IS_INTRA(s->current_picture.f.mb_type[mb_xy])) continue;
            //if(!(s->error_status_table[mb_xy]&MV_ERROR)){
            //if (1){
            if(mb_x>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-1)];
                pred_count++;
            }

            if(mb_x+1<mb_width){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+1)];
                pred_count++;
            }

            if(mb_y>0){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index - mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_stride)];
                pred_count++;
            }

            if(mb_y+1<mb_height){
                mv_predictor[pred_count][0]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][0];
                mv_predictor[pred_count][1]= s->current_picture.f.motion_val[0][mot_index + mot_stride*mot_step][1];
                ref         [pred_count]   = s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_stride)];
                pred_count++;
            }

            if(pred_count==0) continue;

            if(pred_count>=1){
                int sum_x=0, sum_y=0, sum_r=0;
                int k;

                for(k=0; k<pred_count; k++){
                    sum_x+= mv_predictor[k][0]; // Sum all the MVx from MVs avail. for EC
                    sum_y+= mv_predictor[k][1]; // Sum all the MVy from MVs avail. for EC
                    sum_r+= ref[k];
                    // if(k && ref[k] != ref[k-1])
                    // goto skip_mean_and_median;
                }

                mv_predictor[pred_count][0] = sum_x/k;
                mv_predictor[pred_count][1] = sum_y/k;
                ref         [pred_count]    = sum_r/k;
            }

            s->mv[0][0][0] = mv_predictor[pred_count][0];
            s->mv[0][0][1] = mv_predictor[pred_count][1];

            for(m=0; m<mot_step; m++){
                for(n=0; n<mot_step; n++){
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][0] = s->mv[0][0][0];
                    s->current_picture.f.motion_val[0][mot_index + m + n * mot_stride][1] = s->mv[0][0][1];
                }
            }

            decode_mb(s, ref[pred_count]);

            //}
        }
    }
}
static void mean_mv(MpegEncContext*s){
//uint8_t固定[s->mb_跨步*s->mb_高度];
//常量int mb_步长=s->mb_步长;
const int mb_width=s->mb_width;
const int mb_height=s->mb_height;
int mb_x,mb_y,mot_step,mot_step;
//av_log(s->avctx,av_log_DEBUG,“mean_mv\n”);//KG
设置移动步幅(s、移动步幅和移动步幅);
对于(mb_y=0;mb_ymb_高度;mb_y++){
对于(mb_x=0;mb_xmb_宽度;mb_x++){
常量int mb_xy=mb_x+mb_y*s->mb_步长;
常数int mot_索引=(mb_x+mb_y*mot_步长)*mot_步长;
int mv_预测器[4][2]={{0};
int ref[4]={0};
int pred_计数=0;
int m,n;
如果(是帧内->当前图片.f.mb\u类型[mb\u xy])继续;
//如果(!(s->错误\状态\表[mb\U xy]&MV\U错误)){
//如果(1){
如果(mb_x>0){
mv_预测器[pred_count][0]=s->current_picture.f.motion_val[0][mot_index-mot_step][0];
mv_预测器[pred_count][1]=s->current_picture.f.motion_val[0][mot_index-mot_step][1];
ref[pred_count]=s->current_picture.f.ref_index[0][4*(mb_xy-1)];
pred_count++;
}
如果(mb_x+1当前图片f.motion_val[0][mot_index+mot_step][0];
mv_预测器[pred_count][1]=s->current_picture.f.motion_val[0][mot_index+mot_step][1];
ref[pred_count]=s->current_picture.f.ref_index[0][4*(mb_xy+1)];
pred_count++;
}
如果(mb_y>0){
mv_预测器[pred_count][0]=s->current_picture.f.motion_val[0][mot_index-mot_step*mot_step][0];
mv_预测器[pred_count][1]=s->current_picture.f.motion_val[0][mot_index-mot_step*mot_step][1];
ref[pred_count]=s->current_picture.f.ref_index[0][4*(mb_xy-s->mb_步长)];
pred_count++;
}
如果(mb_y+1当前图片f.motion_val[0][mot_index+mot_step*mot_step][0];
mv_预测器[pred_count][1]=s->current_picture.f.motion_val[0][mot_index+mot_step*mot_step][1];
ref[pred_count]=s->current_picture.f.ref_index[0][4*(mb_xy+s->mb_步长)];
pred_count++;
}
如果(pred_count==0)继续;
如果(预测计数>=1){
int sum_x=0,sum_y=0,sum_r=0;
int k;
对于(k=0;kmv[0][0][0]=mv_预测器[pred_count][0];
s->mv[0][0][1]=mv_预测器[pred_count][1];
(m=0;mmv[0][0][0];
s->current_picture.f.motion_val[0][mot_index+m+n*mot_stride][1]=s->mv[0][0][1];
}
}
解码mb(s,ref[pred_count]);
//}
}
}
}

我真的非常感谢您能为我提供一些帮助,帮助我正确地完成这项工作。

我已经很久没有在内部接触FFMPEG的代码了

然而,鉴于我对内部恐怖的经验(你会知道我的意思),我宁愿给你一个简单实用的建议

建议#1
最好的可能性是,当识别每个块的运动矢量时,您可以在FFMPEG编码器上下文(也称为
s
)中创建自己的附加数组,该数组将存储所有块。当算法运行时,它将从中提取值

建议#2
我读的另一件事(我不确定我是否读对了)

mx和my值增加50

我认为50是一个非常大的运动矢量。通常,mo的F值范围