📄 rwmh.c
字号:
switch (subpixel_accuracy)
{
case QCCVID_ME_FULLPIXEL:
final_search_step = 1.0;
break;
case QCCVID_ME_HALFPIXEL:
final_search_step = 0.5;
break;
case QCCVID_ME_QUARTERPIXEL:
final_search_step = 0.25;
break;
case QCCVID_ME_EIGHTHPIXEL:
final_search_step = 0.125;
break;
default:
QccErrorAddMessage("(QccVIDRWMHMotionEstimation): Unrecognized subpixel accuracy");
goto Error;
}
for (row = 0; row < num_rows; row += blocksize)
for (col = 0; col < num_cols; col += blocksize)
{
if (QccVIDRWMHBlockExtract(¤t_block,
current_frame_rdwt,
num_rows,
num_cols,
num_levels,
(double)row,
(double)col,
QCCVID_ME_FULLPIXEL))
{
QccErrorAddMessage("(QccVIDRWMHMotionEstimation): Error calling QccVIDRWMHBlockExtract()");
goto Error;
}
mv_row = row / blocksize;
mv_col = col / blocksize;
horizontal_motion->image[mv_row][mv_col] = 0.0;
vertical_motion->image[mv_row][mv_col] = 0.0;
for (current_search_step = 1.0;
current_search_step >= final_search_step;
current_search_step /= 2)
{
search_row = row +
vertical_motion->image[mv_row][mv_col];
search_col = col +
horizontal_motion->image[mv_row][mv_col];
current_window_size =
(current_search_step == 1.0) ?
(double)QCCVIDRWMH_WINDOWSIZE : current_search_step;
if (QccVIDRWMHMotionEstimationSearch(reference_frame_rdwt,
reference_num_rows,
reference_num_cols,
num_levels,
¤t_block,
&reference_block,
search_row,
search_col,
current_window_size,
current_search_step,
subpixel_accuracy,
&u,
&v))
{
QccErrorAddMessage("(QccVIDRWMHMotionEstimation): Error calling QccVIRWMHMotionEstimationSearch()");
goto Error;
}
horizontal_motion->image[mv_row][mv_col] += u;
vertical_motion->image[mv_row][mv_col] += v;
}
}
return_value = 0;
goto Return;
Error:
return_value = 1;
Return:
QccVIDRWMHBlockFree(¤t_block);
QccVIDRWMHBlockFree(&reference_block);
return(return_value);
}
static
int QccVIDRWMHMotionCompensation(QccMatrix *reference_frame_rdwt,
QccMatrix *compensated_frame_rdwt,
int num_rows,
int num_cols,
int reference_num_rows,
int reference_num_cols,
int num_levels,
int blocksize,
int subpixel_accuracy,
QccIMGImageComponent *horizontal_motion,
QccIMGImageComponent *vertical_motion)
{
int return_value;
int row, col;
int mv_row, mv_col;
double reference_row, reference_col;
QccVIDRWMHBlock reference_block;
QccVIDRWMHBlockInitialize(&reference_block);
reference_block.blocksize = blocksize;
reference_block.num_levels = num_levels;
if (QccVIDRWMHBlockAlloc(&reference_block))
{
QccErrorAddMessage("(QccVIDRWMHMotionCompensation): Error calling QccVIDRWMHBlockAlloc()");
goto Error;
}
for (row = 0; row < num_rows; row += blocksize)
for (col = 0; col < num_cols; col += blocksize)
{
mv_row = row / blocksize;
mv_col = col / blocksize;
reference_row = row + vertical_motion->image[mv_row][mv_col];
reference_col = col + horizontal_motion->image[mv_row][mv_col];
if (QccVIDRWMHBlockExtract(&reference_block,
reference_frame_rdwt,
reference_num_rows,
reference_num_cols,
num_levels,
reference_row,
reference_col,
subpixel_accuracy))
{
QccErrorAddMessage("(QccVIDRWMHMotionCompensation): Error calling QccVIDRWMHBlockExtract()");
goto Error;
}
if (QccVIDRWMHBlockInsert(&reference_block,
compensated_frame_rdwt,
num_rows,
num_cols,
num_levels,
row,
col))
{
QccErrorAddMessage("(QccVIDRWMHMotionCompensation): Error calling QccVIDRWMHBlockInsert()");
goto Error;
}
}
return_value = 0;
goto Return;
Error:
return_value = 1;
Return:
QccVIDRWMHBlockFree(&reference_block);
return(return_value);
}
static int QccVIDRWMHEncodeHeader(QccBitBuffer *output_buffer,
int num_rows,
int num_cols,
int start_frame_num,
int end_frame_num,
int num_levels,
int blocksize,
int target_bit_cnt)
{
if (QccBitBufferPutInt(output_buffer, num_rows))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, num_cols))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, start_frame_num))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, end_frame_num))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, num_levels))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, blocksize))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferPutInt(output_buffer, target_bit_cnt))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferPutInt()");
return(1);
}
if (QccBitBufferFlush(output_buffer))
{
QccErrorAddMessage("(QccVIDRWMHEncodeHeader): Error calling QccBitBufferFlush()");
return(1);
}
return(0);
}
#if 0
static int QccWAVRWMHCorrelation(QccMatrix *current_frame_rdwt,
QccMatrix *compensated_frame_rdwt,
int num_rows,
int num_cols,
int num_levels)
{
int num_subbands;
int subband1;
int subband2;
int row, col;
double difference1;
double difference2;
double correlation;
double variance1;
double variance2;
num_subbands = QccWAVSubbandPyramidNumLevelsToNumSubbands(num_levels);
for (subband1 = 0; subband1 < num_subbands; subband1++)
{
for (subband2 = 0; subband2 < num_subbands; subband2++)
{
correlation = 0;
variance1 = 0;
variance2 = 0;
for (row = 0; row < num_rows; row++)
for (col = 0; col < num_cols; col++)
{
difference1 =
current_frame_rdwt[subband1][row][col] -
compensated_frame_rdwt[subband1][row][col];
difference2 =
current_frame_rdwt[subband2][row][col] -
compensated_frame_rdwt[subband2][row][col];
correlation +=
difference1 * difference2;
variance1 +=
difference1 * difference1;
variance2 +=
difference2 * difference2;
}
variance1 /= num_rows * num_cols;
variance2 /= num_rows * num_cols;
correlation /= num_rows * num_cols;
correlation /= sqrt(variance1 * variance2);
printf("% 0.2f ",
correlation);
}
printf("\n");
}
return(0);
}
#endif
static int QccVIDRWMHDecodeFrame();
static
int QccVIDRWMHEncodeFrame(QccIMGImageComponent *current_frame,
QccIMGImageComponent *reconstructed_frame,
QccMatrix *current_frame_rdwt,
QccMatrix *reference_frame_rdwt,
int num_levels,
int blocksize,
int subpixel_accuracy,
const QccFilter *filter1,
const QccFilter *filter2,
const QccFilter *filter3,
const QccWAVWavelet *wavelet,
QccBitBuffer *output_buffer,
QccBitBuffer *input_buffer,
QccIMGImageComponent *motion_vector_horizontal,
QccIMGImageComponent *motion_vector_vertical,
int read_motion_vectors,
int target_bit_cnt,
QccVIDRWMHStatistics *statistics)
{
int return_value;
int row, col;
int num_rows, num_cols;
int reference_num_rows, reference_num_cols;
int intraframe;
double image_mean;
int start_position;
QccMatrix compensated_frame = NULL;
QccMatrix *compensated_frame_rdwt = NULL;
start_position = output_buffer->bit_cnt;
num_rows = current_frame->num_rows;
num_cols = current_frame->num_cols;
if (QccVIDMotionEstimationCalcReferenceFrameSize(num_rows,
num_cols,
&reference_num_rows,
&reference_num_cols,
subpixel_accuracy))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccVIDMotionEstimationCalcReferenceFrameSize()");
goto Error;
}
intraframe =
(motion_vector_horizontal == NULL) || (motion_vector_vertical == NULL);
if (statistics != NULL)
statistics->intraframe = intraframe;
if ((compensated_frame = QccMatrixAlloc(num_rows, num_cols)) == NULL)
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error allocating memory");
goto Error;
}
if ((compensated_frame_rdwt =
QccWAVWaveletRedundantDWT2DAlloc(num_rows, num_cols, num_levels)) ==
NULL)
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccWAVWaveletRedundantDWT2DAlloc()");
goto Error;
}
if (!intraframe)
{
if (!read_motion_vectors)
{
if (QccWAVWaveletRedundantDWT2D(current_frame->image,
current_frame_rdwt,
num_rows,
num_cols,
num_levels,
wavelet))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccWAVWaveletRedundantDWT2D()");
goto Error;
}
if (QccVIDRWMHMotionEstimation(current_frame_rdwt,
reference_frame_rdwt,
num_rows,
num_cols,
reference_num_rows,
reference_num_cols,
blocksize,
num_levels,
subpixel_accuracy,
motion_vector_horizontal,
motion_vector_vertical))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccVIDRWMHMotionEstimation()");
goto Error;
}
}
if (QccVIDRWMHMotionCompensation(reference_frame_rdwt,
compensated_frame_rdwt,
num_rows,
num_cols,
reference_num_rows,
reference_num_cols,
num_levels,
blocksize,
subpixel_accuracy,
motion_vector_horizontal,
motion_vector_vertical))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccVIDRWMHMotionCompensation()");
goto Error;
}
if (QccWAVWaveletInverseRedundantDWT2D(compensated_frame_rdwt,
compensated_frame,
num_rows,
num_cols,
num_levels,
wavelet))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccWAVWaveletInverseRedundantDWT2D()");
goto Error;
}
for (row = 0; row < num_rows; row++)
for (col = 0; col < num_cols; col++)
current_frame->image[row][col] -= compensated_frame[row][col];
if (!read_motion_vectors)
if (QccVIDMotionVectorsEncode(motion_vector_horizontal,
motion_vector_vertical,
NULL,
subpixel_accuracy,
output_buffer))
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Error calling QccVIDMotionVectorsEncode()");
goto Error;
}
if (statistics != NULL)
statistics->motion_vector_bits =
output_buffer->bit_cnt - start_position;
if (output_buffer->bit_cnt > start_position + target_bit_cnt)
{
QccErrorAddMessage("(QccVIDRWMHEncodeFrame): Rate is not sufficient to store all motion vectors for frame");
goto Error;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -