/*
* H.265 video codec.
* Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de>
*
* Authors: struktur AG, Dirk Farin <farin@struktur.de>
*
* This file is part of libde265.
*
* libde265 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libde265 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libde265. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libde265/encoder/algo/cb-mergeindex.h"
#include "libde265/encoder/encoder-context.h"
#include "libde265/encoder/encoder-syntax.h"
#include <assert.h>
#include <limits>
#include <math.h>
enc_cb* Algo_CB_MergeIndex_Fixed::analyze(encoder_context* ectx,
context_model_table& ctxModel,
enc_cb* cb)
{
assert(cb->split_cu_flag==false);
assert(cb->PredMode==MODE_SKIP); // TODO: || (cb->PredMode==MODE_INTER && cb->inter.skip_flag));
PBMotion mergeCandList[5];
int partIdx = 0;
int cbSize = 1 << cb->log2Size;
get_merge_candidate_list_from_tree(ectx, ectx->shdr,
cb->x, cb->y, // xC/yC
cb->x, cb->y, // xP/yP
cbSize, // nCS
cbSize,cbSize, // nPbW/nPbH
partIdx, // partIdx
mergeCandList);
PBMotionCoding& spec = cb->inter.pb[partIdx].spec;
spec.merge_flag = 1; // we use merge mode
spec.merge_idx = 0;
// build prediction
// previous frame (TODO)
const de265_image* refimg = ectx->get_image(ectx->imgdata->frame_number -1);
//printf("prev frame: %p %d\n",refimg,ectx->imgdata->frame_number);
/*
printf("#l0: %d\n",ectx->imgdata->shdr.num_ref_idx_l0_active);
printf("#l1: %d\n",ectx->imgdata->shdr.num_ref_idx_l1_active);
for (int i=0;i<ectx->imgdata->shdr.num_ref_idx_l0_active;i++)
printf("RefPixList[0][%d] = %d\n", i, ectx->imgdata->shdr.RefPicList[0][i]);
*/
// TODO: fake motion data
const PBMotion& vec = mergeCandList[spec.merge_idx];
cb->inter.pb[partIdx].motion = vec;
//ectx->img->set_mv_info(cb->x,cb->y, 1<<cb->log2Size,1<<cb->log2Size, vec);
/*
generate_inter_prediction_samples(ectx, ectx->shdr, ectx->prediction,
cb->x,cb->y, // int xC,int yC,
0,0, // int xB,int yB,
1<<cb->log2Size, // int nCS,
1<<cb->log2Size,
1<<cb->log2Size, // int nPbW,int nPbH,
&vec);
*/
generate_inter_prediction_samples(ectx, ectx->shdr, ectx->img,
cb->x,cb->y, // int xC,int yC,
0,0, // int xB,int yB,
1<<cb->log2Size, // int nCS,
1<<cb->log2Size,
1<<cb->log2Size, // int nPbW,int nPbH,
&vec);
/*
printBlk("merge prediction:",
ectx->img->get_image_plane_at_pos(0, cb->x,cb->y), 1<<cb->log2Size,
ectx->img->get_image_stride(0),
"merge ");
*/
// estimate rate for sending merge index
//CABAC_encoder_estim cabac;
//cabac.write_bits();
int IntraSplitFlag = 0;
int MaxTrafoDepth = ectx->get_sps().max_transform_hierarchy_depth_inter;
if (mCodeResidual) {
assert(false);
descend(cb,"with residual");
assert(false);
/* TODO
cb->transform_tree = mTBSplit->analyze(ectx,ctxModel, ectx->imgdata->input, NULL, cb,
cb->x,cb->y,cb->x,cb->y, cb->log2Size,0,
0, MaxTrafoDepth, IntraSplitFlag);
*/
ascend();
cb->inter.rqt_root_cbf = ! cb->transform_tree->isZeroBlock();
cb->distortion = cb->transform_tree->distortion;
cb->rate = cb->transform_tree->rate;
}
else {
const de265_image* input = ectx->imgdata->input;
//de265_image* img = ectx->prediction;
int x0 = cb->x;
int y0 = cb->y;
int tbSize = 1<<cb->log2Size;
CABAC_encoder_estim cabac;
cabac.set_context_models(&ctxModel);
encode_merge_idx(ectx, &cabac, spec.merge_idx);
leaf(cb,"no residual");
cb->rate = cabac.getRDBits();
cb->inter.rqt_root_cbf = 0;
enc_tb* tb = new enc_tb(x0,y0,cb->log2Size,cb);
tb->downPtr = &cb->transform_tree;
cb->transform_tree = tb;
tb->reconstruct(ectx, ectx->img); // reconstruct luma
/*
printBlk("distortion input:",
input->get_image_plane_at_pos(0,x0,y0), 1<<cb->log2Size,
input->get_image_stride(0),
"input ");
printBlk("distortion prediction:",
ectx->img->get_image_plane_at_pos(0,x0,y0), 1<<cb->log2Size,
ectx->img->get_image_stride(0),
"pred ");
*/
cb->distortion = compute_distortion_ssd(input, ectx->img, x0,y0, cb->log2Size, 0);
}
//printf("%d;%d rqt_root_cbf=%d\n",cb->x,cb->y,cb->inter.rqt_root_cbf);
return cb;
}