研究目的で、デコード処理中の動き補償の前に、各 P フレームと B フレームの H.264 動きベクトル (MV) を変更しようとしています。この目的のためにFFmpegを使用しています。変更の例としては、各 MV を元の空間近傍に置き換えてから、元の MV ではなく、結果の MV を動き補償に使用します。適当に誘導してください。
これまでのところ、ファイル/libavcodec/h264_cavlc.c内の MV を簡単に変更することができました。関数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()関数に基づいて、最初の if ステートメント内のff_er_frame_end()で実行される新しい関数mean_mv()を作成しました。その最初の if ステートメントは、条件の 1 つがエラー カウントがゼロの場合 (s->error_count == 0) 、関数ff_er_frame_end()を終了します。ただし、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;
そしてこれが、 guess_mv()に基づいて作成したmean_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]);
//}
}
}
}
これを適切に行う方法について、いくつかの支援をいただければ幸いです。