В исследовательских целях я пытаюсь изменить векторы движения H.264 (MV) для каждого P- и B-кадра до компенсации движения во время процесса декодирования.Я использую FFmpeg для этой цели.Примером модификации является замена каждого MV его исходными пространственными соседями, а затем использование результирующих MV для компенсации движения, а не исходных.Пожалуйста, направьте меня соответствующим образом.
До сих пор я смог сделать простую модификацию MV в файле / libavcodec / h264_cavlc.c .В функции ff_h264_decode_mb_cavlc () , модифицируя переменные mx и my , например, путем увеличения их значений, модифицирует MV, используемые при декодировании.
Например, как показано ниже, значения mx и my увеличиваются на 50, что удлиняет MV, используемые в декодере.
mx += get_se_golomb(&s->gb)+50;
my += get_se_golomb(&s->gb)+50;
Однако в этом отношении я не знаю, как получить доступ к соседям mx и my для моего анализа пространственного среднего, который я упоминал в первом абзаце.Я полагаю, что ключ к этому лежит в манипулировании массивом, mv_cache .
Другой эксперимент, который я провел, был в файле, libavcodec / error_resilience.c .На основе функции guess_mv () я создал новую функцию, mean_mv () , которая выполняется в ff_er_frame_end () в первом операторе if.Этот первый оператор if выходит из функции ff_er_frame_end () , если одним из условий является нулевой счетчик ошибок (s-> error_count == 0).Однако в этот момент я решил вставить свою функцию mean_mv () , чтобы она всегда выполнялась при нулевом количестве ошибок.Этот эксперимент несколько дал желаемые результаты, так как я мог начать видеть артефакты в верхних частях видео, но они были ограничены только правым верхним углом.Я предполагаю, что моя вставленная функция не завершена, чтобы уложиться в сроки воспроизведения или что-то в этом роде.
Ниже приведен модифицированный оператор if.Единственным дополнением является моя функция, mean_mv (s) .
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;
А вот функция mean_mv () , которую я создал на основе guess_mv ().
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]);
//}
}
}
}
Буду очень признателен за помощь в правильном подходе.