blob: 85102e94bba5441f8a4a1278d7fce482e30bf049 [file] [log] [blame]
/*!
**************************************************************************************
* \file
* slice.c
* \brief
* generate the slice header, setup the bit buffer for slices,
* and generates the slice NALU(s)
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Thomas Stockhammer <stockhammer@ei.tum.de>
* - Detlev Marpe <marpe@hhi.de>
* - Stephan Wenger <stewe@cs.tu-berlin.de>
* - Alexis Michael Tourapis <alexismt@ieee.org>
***************************************************************************************
*/
#include "contributors.h"
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include "global.h"
#include "header.h"
#include "rtp.h"
#include "fmo.h"
#include "vlc.h"
#include "image.h"
#include "cabac.h"
#include "elements.h"
#include "me_epzs.h"
#include "ratectl.h"
#include "rc_quadratic.h"
#include "macroblock.h"
#include "symbol.h"
// Local declarations
static Slice *malloc_slice();
static void free_slice(Slice *slice);
static void init_slice(int start_mb_addr);
static void set_ref_pic_num();
extern ColocatedParams *Co_located;
extern StorablePicture **listX[6];
void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no);
void SetLagrangianMultipliers();
/*!
************************************************************************
* \brief
* init_ref_pic_list_reordering initializations should go here
************************************************************************
*/
void init_ref_pic_list_reordering()
{
Slice* currSlice = img->currentSlice;
currSlice->ref_pic_list_reordering_flag_l0 = 0;
currSlice->ref_pic_list_reordering_flag_l1 = 0;
}
/*!
************************************************************************
* \brief
* This function generates the slice (and partition) header(s)
*
* \return number of bits used for the slice (and partition) header(s)
*
* \par Side effects:
* Adds slice/partition header symbols to the symbol buffer
* increments Picture->no_slices, allocates memory for the
* slice, sets img->currSlice
************************************************************************
*/
int start_slice()
{
EncodingEnvironmentPtr eep;
Slice *currSlice = img->currentSlice;
Bitstream *currStream;
int header_len = 0;
int i;
int NumberOfPartitions = (input->partition_mode == PAR_DP_1?1:3);
//one partition for IDR img
if(img->currentPicture->idr_flag)
{
NumberOfPartitions = 1;
}
RTPUpdateTimestamp (img->tr); // this has no side effects, just leave it for all NALs
for (i=0; i<NumberOfPartitions; i++)
{
currStream = (currSlice->partArr[i]).bitstream;
currStream->write_flag = 0;
if (i==0) // First partition
header_len += SliceHeader (0);
else // Second/Third partition
header_len += Partition_BC_Header(i);
//! Initialize CABAC
if (input->symbol_mode == CABAC)
{
eep = &((currSlice->partArr[i]).ee_cabac);
if (currStream->bits_to_go != 8)
header_len+=currStream->bits_to_go;
writeVlcByteAlign(currStream);
arienco_start_encoding(eep, currStream->streamBuffer, &(currStream->byte_pos));
cabac_new_slice();
}
else
{
// Initialize CA-VLC
CAVLC_init();
}
}
if(input->symbol_mode == CABAC)
{
init_contexts();
}
return header_len;
}
/*!
************************************************************************
* \brief
* This function terminates a slice (but doesn't write it out),
* the old terminate_slice (0)
* \return
* 0 if OK, \n
* 1 in case of error
*
************************************************************************
*/
int terminate_slice(int lastslice)
{
static int MbWidthC [4]= { 0, 8, 8, 16};
static int MbHeightC [4]= { 0, 8, 16, 16};
int bytes_written;
Bitstream *currStream;
Slice *currSlice = img->currentSlice;
EncodingEnvironmentPtr eep;
int i;
int byte_pos_before_startcode_emu_prevention;
int min_num_bytes=0;
int stuffing_bytes=0;
int RawMbBits;
if (input->symbol_mode == CABAC)
write_terminating_bit (1); // only once, not for all partitions
for (i=0; i<currSlice->max_part_nr; i++)
{
currStream = (currSlice->partArr[i]).bitstream;
if (input->symbol_mode == UVLC)
{
SODBtoRBSP(currStream);
byte_pos_before_startcode_emu_prevention = currStream->byte_pos;
currStream->byte_pos = RBSPtoEBSP(currStream->streamBuffer, 0 , currStream->byte_pos, 0);
*(stats->em_prev_bits) += (currStream->byte_pos - byte_pos_before_startcode_emu_prevention) * 8;
}
else // CABAC
{
eep = &((currSlice->partArr[i]).ee_cabac);
// terminate the arithmetic code
arienco_done_encoding(eep);
currStream->bits_to_go = eep->Ebits_to_go;
currStream->byte_buf = 0;
bytes_written = currStream->byte_pos;
img->bytes_in_picture += currStream->byte_pos;
byte_pos_before_startcode_emu_prevention= currStream->byte_pos;
if (lastslice && i==((currSlice->max_part_nr-1)))
{
RawMbBits = 256 * img->bitdepth_luma + 2 * MbWidthC[active_sps->chroma_format_idc] * MbHeightC[active_sps->chroma_format_idc] * img->bitdepth_chroma;
min_num_bytes = ((96 * get_pic_bin_count()) - (RawMbBits * (int)img->PicSizeInMbs *3) + 1023) / 1024;
if (min_num_bytes>img->bytes_in_picture)
{
stuffing_bytes = min_num_bytes - img->bytes_in_picture;
printf ("CABAC stuffing words = %6d\n", stuffing_bytes/3);
}
}
// printf ("bytepos: %d\n", currStream->byte_pos);
currStream->byte_pos = RBSPtoEBSP(currStream->streamBuffer, 0, currStream->byte_pos, currStream->byte_pos + stuffing_bytes);
*(stats->em_prev_bits) += (currStream->byte_pos - byte_pos_before_startcode_emu_prevention) * 8;
} // CABAC
} // partition loop
if( input->symbol_mode == CABAC )
{
store_contexts();
}
if (img->type != I_SLICE || img->type != SI_SLICE)
free_ref_pic_list_reordering_buffer (currSlice);
return 0;
}
/*!
************************************************************************
* \brief
* Encodes one slice
* \par
* returns the number of coded MBs in the SLice
************************************************************************
*/
int encode_one_slice (int SliceGroupId, Picture *pic, int TotalCodedMBs)
{
Boolean end_of_slice = FALSE;
Boolean recode_macroblock;
int len;
int NumberOfCodedMBs = 0;
int CurrentMbAddr;
double FrameRDCost = DBL_MAX, FieldRDCost = DBL_MAX;
img->cod_counter = 0;
CurrentMbAddr = FmoGetFirstMacroblockInSlice (SliceGroupId);
// printf ("\n\nEncode_one_slice: PictureID %d SliceGroupId %d SliceID %d FirstMB %d \n", img->tr, SliceGroupId, img->current_slice_nr, CurrentMbInScanOrder);
init_slice (CurrentMbAddr);
Bytes_After_Header = img->currentSlice->partArr[0].bitstream->byte_pos;
SetLagrangianMultipliers();
if (input->symbol_mode==CABAC)
{
SetCtxModelNumber ();
}
img->checkref = (input->rdopt && input->RestrictRef && (img->type==P_SLICE || img->type==SP_SLICE));
/*
// Tian Dong: June 7, 2002 JVT-B042
// When the pictures are put into different layers and subseq, not all the reference frames
// in multi-frame buffer are valid for prediction. The acutual number of the valid reference
// frames, fb->num_short_used, will be given by start_slice(sym).
// Save the fb->short_used.
if (input->NumFramesInELSubSeq)
{
short_used = fb->short_used;
}
*/
len = start_slice ();
// Rate control
if (input->RCEnable)
{
generic_RC->NumberofHeaderBits +=len;
// basic unit layer rate control
if(img->BasicUnit < img->FrameSizeInMbs)
generic_RC->NumberofBasicUnitHeaderBits +=len;
}
// printf("short size, used, num-used: (%d,%d,%d)\n", fb->short_size, fb->short_used, fb->num_short_used);
/*
// Tian Dong: June 7, 2002 JVT-B042
if (input->NumFramesInELSubSeq)
{
fb->short_used = fb->num_short_used;
}
*/
// Update statistics
stats->bit_slice += len;
stats->bit_use_header[img->type] += len;
// printf ("\n\n");
while (end_of_slice == FALSE) // loop over macroblocks
{
if (img->AdaptiveRounding && input->AdaptRndPeriod && (img->current_mb_nr % input->AdaptRndPeriod == 0))
{
CalculateOffsetParam();
if(input->Transform8x8Mode)
{
CalculateOffset8Param();
}
}
//sw paff
if (!img->MbaffFrameFlag)
{
recode_macroblock = FALSE;
rdopt = &rddata_top_frame_mb; // store data in top frame MB
start_macroblock (CurrentMbAddr, FALSE);
encode_one_macroblock ();
write_one_macroblock (1);
terminate_macroblock (&end_of_slice, &recode_macroblock);
// printf ("encode_one_slice: mb %d, slice %d, bitbuf bytepos %d EOS %d\n",
// img->current_mb_nr, img->current_slice_nr,
// img->currentSlice->partArr[0].bitstream->byte_pos, end_of_slice);
if (recode_macroblock == FALSE) // The final processing of the macroblock has been done
{
CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr);
if (CurrentMbAddr == -1) // end of slice
{
// printf ("FMO End of Slice Group detected, current MBs %d, force end of slice\n", NumberOfCodedMBs+1);
end_of_slice = TRUE;
}
NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice
proceed2nextMacroblock ();
}
else
{
//!Go back to the previous MB to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
if(img->current_mb_nr == -1 ) // The first MB of the slice group is too big,
// which means it's impossible to encode picture using current slice bits restriction
{
snprintf (errortext, ET_SIZE, "Error encoding first MB with specified parameter, bits of current MB may be too big");
error (errortext, 300);
}
}
}
else // TBD -- Addition of FMO
{
//! This following ugly code breaks slices, at least for a slice mode that accumulates a certain
//! number of bits into one slice.
//! The suggested algorithm is as follows:
//!
//! SaveState (Bitstream, stats, etc. etc.);
//! BitsForThisMBPairInFrameMode = CodeMB (Upper, FRAME_MODE) + CodeMB (Lower, FRAME_MODE);
//! DistortionForThisMBPairInFrameMode = CalculateDistortion(Upper) + CalculateDistortion (Lower);
//! RestoreState();
//! BitsForThisMBPairInFieldMode = CodeMB (Upper, FIELD_MODE) + CodeMB (Lower, FIELD_MODE);
//! DistortionForThisMBPairInFrameMode = CalculateDistortion(Upper) + CalculateDistortion (Lower);
//! FrameFieldMode = Decision (...)
//! RestoreState()
//! if (FrameFieldMode == FRAME) {
//! CodeMB (Upper, FRAME); CodeMB (Lower, FRAME);
//! } else {
//! CodeMB (Upper FIELD); CodeMB (Lower, FIELD);
//! }
//!
//! Open questions/issues:
//! 1. CABAC/CA-VLC state: It seems that the CABAC/CA_VLC states are changed during the
//! dummy encoding processes (for the R-D based selection), but that they are never
//! reset, once the selection is made. I believe that this breaks the MB-adaptive
//! frame/field coding. The necessary code for the state saves is readily available
//! in macroblock.c, start_macroblock() and terminate_macroblock() (this code needs
//! to be double checked that it works with CA-VLC as well
//! 2. would it be an option to allocate Bitstreams with zero data in them (or copy the
//! already generated bitstream) for the "test coding"?
img->write_macroblock = 0;
if (input->MbInterlace == ADAPTIVE_CODING || input->MbInterlace == FRAME_MB_PAIR_CODING)
{
//================ code MB pair as frame MB ================
//----------------------------------------------------------
recode_macroblock = FALSE;
img->field_mode = 0; // MB coded as frame
img->top_field = 0; // Set top field to 0
//Rate control
img->write_macroblock = 0;
img->bot_MB = 0;
// save RC state only when it is going to change
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
copy_rc_jvt( quadratic_RC_init, quadratic_RC ); // save initial RC status
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING )
copy_rc_generic( generic_RC_init, generic_RC ); // save initial RC status
start_macroblock (CurrentMbAddr, FALSE);
rdopt = &rddata_top_frame_mb; // store data in top frame MB
encode_one_macroblock (); // code the MB as frame
FrameRDCost = rdopt->min_rdcost;
//*** Top MB coded as frame MB ***//
//Rate control
img->bot_MB = 1; //for Rate control
// go to the bottom MB in the MB pair
img->field_mode = 0; // MB coded as frame //GB
start_macroblock (CurrentMbAddr+1, FALSE);
rdopt = &rddata_bot_frame_mb; // store data in top frame MB
encode_one_macroblock (); // code the MB as frame
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
copy_rc_jvt( quadratic_RC_best, quadratic_RC ); // restore initial RC status
if (input->RCEnable && input->MbInterlace == ADAPTIVE_CODING )
copy_rc_generic( generic_RC_best, generic_RC ); // save frame RC stats
FrameRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as frame MB ***//
}
if ((input->MbInterlace == ADAPTIVE_CODING) || (input->MbInterlace == FIELD_CODING))
{
//Rate control
img->bot_MB = 0;
//=========== start coding the MB pair as a field MB pair =============
//---------------------------------------------------------------------
img->field_mode = 1; // MB coded as field
img->top_field = 1; // Set top field to 1
img->buf_cycle <<= 1;
input->num_ref_frames <<= 1;
img->num_ref_idx_l0_active <<= 1;
img->num_ref_idx_l0_active += 1;
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
copy_rc_jvt( quadratic_RC, quadratic_RC_init ); // restore initial RC status
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING )
copy_rc_generic( generic_RC, generic_RC_init ); // reset RC stats
start_macroblock (CurrentMbAddr, TRUE);
rdopt = &rddata_top_field_mb; // store data in top frame MB
// TopFieldIsSkipped = 0; // set the top field MB skipped flag to 0
encode_one_macroblock (); // code the MB as field
FieldRDCost = rdopt->min_rdcost;
//*** Top MB coded as field MB ***//
//Rate control
img->bot_MB = 1;//for Rate control
img->top_field = 0; // Set top field to 0
start_macroblock (CurrentMbAddr+1, TRUE);
rdopt = &rddata_bot_field_mb; // store data in top frame MB
encode_one_macroblock (); // code the MB as field
FieldRDCost += rdopt->min_rdcost;
//*** Bottom MB coded as field MB ***//
}
//Rate control
img->write_mbaff_frame = 0; //Rate control
//=========== decide between frame/field MB pair ============
//-----------------------------------------------------------
if ( ((input->MbInterlace == ADAPTIVE_CODING) && (FrameRDCost < FieldRDCost)) || input->MbInterlace == FRAME_MB_PAIR_CODING )
{
img->field_mode = 0;
MBPairIsField = 0;
if ( input->MbInterlace != FRAME_MB_PAIR_CODING )
{
img->buf_cycle >>= 1;
input->num_ref_frames >>= 1;
img->num_ref_idx_l0_active -= 1;
img->num_ref_idx_l0_active >>= 1;
}
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING
&& img->NumberofCodedMacroBlocks > 0 && (img->NumberofCodedMacroBlocks % img->BasicUnit) == 0 )
copy_rc_jvt( quadratic_RC, quadratic_RC_best ); // restore initial RC status
if ( input->RCEnable && input->MbInterlace == ADAPTIVE_CODING )
copy_rc_generic( generic_RC, generic_RC_best ); // restore frame RC stats
//Rate control
img->write_mbaff_frame = 1; //for Rate control
}
else
{
img->field_mode = 1;
MBPairIsField = 1;
}
//Rate control
img->write_macroblock = 1;//Rate control
if (MBPairIsField)
img->top_field = 1;
else
img->top_field = 0;
//Rate control
img->bot_MB = 0;// for Rate control
// go back to the Top MB in the MB pair
start_macroblock (CurrentMbAddr, img->field_mode);
rdopt = img->field_mode ? &rddata_top_field_mb : &rddata_top_frame_mb;
copy_rdopt_data (0); // copy the MB data for Top MB from the temp buffers
write_one_macroblock (1); // write the Top MB data to the bitstream
terminate_macroblock (&end_of_slice, &recode_macroblock); // done coding the Top MB
if (recode_macroblock == FALSE) // The final processing of the macroblock has been done
{
CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr);
if (CurrentMbAddr == -1) // end of slice
{
end_of_slice = TRUE;
}
NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice
proceed2nextMacroblock ();
//Rate control
img->bot_MB = 1;//for Rate control
// go to the Bottom MB in the MB pair
img->top_field = 0;
start_macroblock (CurrentMbAddr, img->field_mode);
rdopt = img->field_mode ? &rddata_bot_field_mb : &rddata_bot_frame_mb;
copy_rdopt_data (1); // copy the MB data for Bottom MB from the temp buffers
write_one_macroblock (0); // write the Bottom MB data to the bitstream
terminate_macroblock (&end_of_slice, &recode_macroblock); // done coding the Top MB
if (recode_macroblock == FALSE) // The final processing of the macroblock has been done
{
CurrentMbAddr = FmoGetNextMBNr (CurrentMbAddr);
if (CurrentMbAddr == -1) // end of slice
{
end_of_slice = TRUE;
}
NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice
proceed2nextMacroblock ();
}
else
{
//Go back to the beginning of the macroblock pair to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
if(img->current_mb_nr == -1 ) // The first MB of the slice group is too big,
// which means it's impossible to encode picture using current slice bits restriction
{
snprintf (errortext, ET_SIZE, "Error encoding first MB with specified parameter, bits of current MB may be too big");
error (errortext, 300);
}
}
}
else
{
//!Go back to the previous MB to recode it
img->current_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
if(img->current_mb_nr == -1 ) // The first MB of the slice group is too big,
// which means it's impossible to encode picture using current slice bits restriction
{
snprintf (errortext, ET_SIZE, "Error encoding first MB with specified parameter, bits of current MB may be too big");
error (errortext, 300);
}
}
if (MBPairIsField) // if MB Pair was coded as field the buffer size variables back to frame mode
{
img->buf_cycle >>= 1;
input->num_ref_frames >>= 1;
img->num_ref_idx_l0_active -= 1;
img->num_ref_idx_l0_active >>= 1;
}
img->field_mode = img->top_field = 0; // reset to frame mode
if ( !end_of_slice )
{
assert( CurrentMbAddr < (int)img->PicSizeInMbs );
assert( CurrentMbAddr >= 0 );
if (CurrentMbAddr == FmoGetLastCodedMBOfSliceGroup (FmoMB2SliceGroup (CurrentMbAddr)))
end_of_slice = TRUE; // just in case it doesn't get set in terminate_macroblock
}
}
}
/*
// Tian Dong: June 7, 2002 JVT-B042
// Restore the short_used
if (input->NumFramesInELSubSeq)
{
fb->short_used = short_used;
}
*/
terminate_slice ( (NumberOfCodedMBs+TotalCodedMBs >= (int)img->PicSizeInMbs) );
return NumberOfCodedMBs;
}
/*!
************************************************************************
* \brief
* Initializes the parameters for a new slice and
* allocates the memory for the coded slice in the Picture structure
* \par Side effects:
* Adds slice/partition header symbols to the symbol buffer
* increments Picture->no_slices, allocates memory for the
* slice, sets img->currSlice
************************************************************************
*/
static void init_slice (int start_mb_addr)
{
int i;
Picture *currPic = img->currentPicture;
DataPartition *dataPart;
Bitstream *currStream;
Slice *currSlice;
img->current_mb_nr = start_mb_addr;
// Allocate new Slice in the current Picture, and set img->currentSlice
assert (currPic != NULL);
currPic->no_slices++;
if (currPic->no_slices >= MAXSLICEPERPICTURE)
error ("Too many slices per picture, increase MAXSLICEPERPICTURE in global.h.", -1);
currPic->slices[currPic->no_slices-1] = malloc_slice();
currSlice = currPic->slices[currPic->no_slices-1];
img->currentSlice = currSlice;
currSlice->picture_id = img->tr % 256;
currSlice->qp = img->qp;
currSlice->start_mb_nr = start_mb_addr;
currSlice->slice_too_big = dummy_slice_too_big;
for (i = 0; i < currSlice->max_part_nr; i++)
{
dataPart = &(currSlice->partArr[i]);
currStream = dataPart->bitstream;
currStream->bits_to_go = 8;
currStream->byte_pos = 0;
currStream->byte_buf = 0;
}
img->num_ref_idx_l0_active = active_pps->num_ref_idx_l0_active_minus1 + 1;
img->num_ref_idx_l1_active = active_pps->num_ref_idx_l1_active_minus1 + 1;
// primary and redundant slices: number of references overriding.
if(input->redundant_pic_flag)
{
if(!redundant_coding)
{
img->num_ref_idx_l0_active = imin(img->number,input->NumRefPrimary);
}
else
{
// 1 reference picture for redundant slices
img->num_ref_idx_l0_active = 1;
}
}
// code now also considers fields. Issue whether we should account this within the appropriate input params directly
if ((img->type == P_SLICE || img->type == SP_SLICE) && input->P_List0_refs)
{
img->num_ref_idx_l0_active = imin(img->num_ref_idx_l0_active, input->P_List0_refs * ((img->structure !=0) + 1));
}
if (img->type == B_SLICE )
{
if (input->B_List0_refs)
{
img->num_ref_idx_l0_active = imin(img->num_ref_idx_l0_active, input->B_List0_refs * ((img->structure !=0) + 1));
}
if (input->B_List1_refs)
{
img->num_ref_idx_l1_active = imin(img->num_ref_idx_l1_active, input->B_List1_refs * ((img->structure !=0) + 1));
}
}
// generate reference picture lists
init_lists(img->type, (PictureStructure) img->structure);
// assign list 0 size from list size
img->num_ref_idx_l0_active = listXsize[0];
img->num_ref_idx_l1_active = listXsize[1];
//Perform memory management based on poc distances
//if (img->nal_reference_idc && input->HierarchicalCoding && input->PocMemoryManagement && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
if (img->nal_reference_idc && input->PocMemoryManagement && dpb.ref_frames_in_buffer==active_sps->num_ref_frames)
{
poc_based_ref_management(img->frame_num);
}
if (input->EnableOpenGOP)
{
for (i = 0; i<listXsize[0]; i++)
{
if (listX[0][i]->poc < img->last_valid_reference && img->ThisPOC > img->last_valid_reference)
{
listXsize[0] = img->num_ref_idx_l0_active = imax(1,i);
break;
}
}
for (i = 0; i<listXsize[1]; i++)
{
if (listX[1][i]->poc < img->last_valid_reference && img->ThisPOC > img->last_valid_reference)
{
listXsize[1] = img->num_ref_idx_l1_active = imax(1,i);
break;
}
}
}
init_ref_pic_list_reordering();
//Perform reordering based on poc distances for HierarchicalCoding
//if (img->type==P_SLICE && input->HierarchicalCoding && input->ReferenceReorder)
if (img->type==P_SLICE && input->ReferenceReorder)
{
int i, num_ref;
alloc_ref_pic_list_reordering_buffer(currSlice);
if ((img->type != I_SLICE) && (img->type !=SI_SLICE))
{
for (i=0; i<img->num_ref_idx_l0_active + 1; i++)
{
currSlice->reordering_of_pic_nums_idc_l0[i] = 3;
currSlice->abs_diff_pic_num_minus1_l0[i] = 0;
currSlice->long_term_pic_idx_l0[i] = 0;
}
if (img->type == B_SLICE)
{
for (i=0; i<img->num_ref_idx_l1_active + 1; i++)
{
currSlice->reordering_of_pic_nums_idc_l1[i] = 3;
currSlice->abs_diff_pic_num_minus1_l1[i] = 0;
currSlice->long_term_pic_idx_l1[i] = 0;
}
}
}
if ((img->type != I_SLICE) && (img->type !=SI_SLICE))
{
num_ref = img->num_ref_idx_l0_active;
poc_ref_pic_reorder(listX[LIST_0],
num_ref,
currSlice->reordering_of_pic_nums_idc_l0,
currSlice->abs_diff_pic_num_minus1_l0,
currSlice->long_term_pic_idx_l0, LIST_0);
//reference picture reordering
reorder_ref_pic_list(listX[LIST_0], &listXsize[LIST_0],
img->num_ref_idx_l0_active - 1,
currSlice->reordering_of_pic_nums_idc_l0,
currSlice->abs_diff_pic_num_minus1_l0,
currSlice->long_term_pic_idx_l0);
// This is not necessary since order is already poc based...
if (img->type == B_SLICE)
{
num_ref = img->num_ref_idx_l1_active;
poc_ref_pic_reorder(listX[LIST_1],
num_ref,
currSlice->reordering_of_pic_nums_idc_l1,
currSlice->abs_diff_pic_num_minus1_l1,
currSlice->long_term_pic_idx_l1, LIST_1);
//reference picture reordering
reorder_ref_pic_list(listX[LIST_1], &listXsize[LIST_1],
img->num_ref_idx_l1_active - 1,
currSlice->reordering_of_pic_nums_idc_l1,
currSlice->abs_diff_pic_num_minus1_l1,
currSlice->long_term_pic_idx_l1);
}
}
}
//if (img->MbaffFrameFlag)
if (img->structure==FRAME)
init_mbaff_lists();
if (img->type != I_SLICE && (active_pps->weighted_pred_flag == 1 || (active_pps->weighted_bipred_idc > 0 && (img->type == B_SLICE))))
{
if (img->type==P_SLICE || img->type==SP_SLICE)
{
if (input->GenerateMultiplePPS && input->RDPictureDecision)
{
if (enc_picture==enc_frame_picture2)
estimate_weighting_factor_P_slice (0);
else
estimate_weighting_factor_P_slice (1);
}
else
estimate_weighting_factor_P_slice (0);
}
else
estimate_weighting_factor_B_slice ();
}
set_ref_pic_num();
if (img->type == B_SLICE)
compute_colocated(Co_located, listX);
if (img->type != I_SLICE && input->SearchMode == EPZS)
EPZSSliceInit(EPZSCo_located, listX);
if (input->symbol_mode == UVLC)
{
writeMB_typeInfo = writeSE_UVLC;
writeIntraPredMode = writeIntraPredMode_CAVLC;
writeB8_typeInfo = writeSE_UVLC;
for (i=0; i<6; i++)
{
switch (listXsize[i])
{
case 0:
writeRefFrame[i] = NULL;
break;
case 1:
writeRefFrame[i] = writeSE_Dummy;
break;
case 2:
writeRefFrame[i] = writeSE_invFlag;
break;
default:
writeRefFrame[i] = writeSE_UVLC;
break;
}
}
writeMVD = writeSE_SVLC;
writeCBP = writeCBP_VLC;
writeDquant = writeSE_SVLC;
writeCIPredMode = writeSE_UVLC;
writeFieldModeInfo = writeSE_Flag;
writeMB_transform_size = writeSE_Flag;
}
else
{
writeMB_typeInfo = writeMB_typeInfo_CABAC;
writeIntraPredMode = writeIntraPredMode_CABAC;
writeB8_typeInfo = writeB8_typeInfo_CABAC;
for (i=0; i<6; i++)
{
switch (listXsize[i])
{
case 0:
writeRefFrame[i] = NULL;
case 1:
writeRefFrame[i] = writeSE_Dummy;
break;
default:
writeRefFrame[i] = writeRefFrame_CABAC;
}
}
writeMVD = writeMVD_CABAC;
writeCBP = writeCBP_CABAC;
writeDquant = writeDquant_CABAC;
writeCIPredMode = writeCIPredMode_CABAC;
writeFieldModeInfo = writeFieldModeInfo_CABAC;
writeMB_transform_size = writeMB_transform_size_CABAC;
}
}
/*!
************************************************************************
* \brief
* Allocates a slice structure along with its dependent data structures
* \return
* Pointer to a Slice
************************************************************************
*/
static Slice *malloc_slice()
{
int i;
DataPartition *dataPart;
Slice *slice;
// const int buffer_size = (img->size * 4); // AH 190202: There can be data expansion with
// low QP values. So, we make sure that buffer
// does not overflow. 4 is probably safe multiplier.
int buffer_size;
switch (input->slice_mode)
{
case 2:
buffer_size = 2 * input->slice_argument;
break;
case 1:
buffer_size = 500 + input->slice_argument * (128 + 256 * img->bitdepth_luma + 512 * img->bitdepth_chroma);;
break;
default:
buffer_size = 500 + img->FrameSizeInMbs * (128 + 256 * img->bitdepth_luma + 512 * img->bitdepth_chroma);
break;
}
// KS: this is approx. max. allowed code picture size
if ((slice = (Slice *) calloc(1, sizeof(Slice))) == NULL) no_mem_exit ("malloc_slice: slice structure");
if (input->symbol_mode == CABAC)
{
// create all context models
slice->mot_ctx = create_contexts_MotionInfo();
slice->tex_ctx = create_contexts_TextureInfo();
}
slice->max_part_nr = input->partition_mode==0?1:3;
//for IDR img there should be only one partition
if(img->currentPicture->idr_flag)
slice->max_part_nr = 1;
assignSE2partition[0] = assignSE2partition_NoDP;
//ZL
//for IDR img all the syntax element should be mapped to one partition
if(!img->currentPicture->idr_flag&&input->partition_mode==1)
assignSE2partition[1] = assignSE2partition_DP;
else
assignSE2partition[1] = assignSE2partition_NoDP;
slice->num_mb = 0; // no coded MBs so far
if ((slice->partArr = (DataPartition *) calloc(slice->max_part_nr, sizeof(DataPartition))) == NULL) no_mem_exit ("malloc_slice: partArr");
for (i=0; i<slice->max_part_nr; i++) // loop over all data partitions
{
dataPart = &(slice->partArr[i]);
if ((dataPart->bitstream = (Bitstream *) calloc(1, sizeof(Bitstream))) == NULL) no_mem_exit ("malloc_slice: Bitstream");
if ((dataPart->bitstream->streamBuffer = (byte *) calloc(buffer_size, sizeof(byte))) == NULL) no_mem_exit ("malloc_slice: StreamBuffer");
// Initialize storage of bitstream parameters
}
return slice;
}
/*!
************************************************************************
* \brief
* Memory frees of all Slice structures and of its dependent
* data structures
* \par Input:
* Image Parameters struct struct img_par *img
************************************************************************
*/
void free_slice_list(Picture *currPic)
{
int i;
for (i=0; i<currPic->no_slices; i++)
{
free_slice (currPic->slices[i]);
currPic->slices[i]=NULL;
}
}
/*!
************************************************************************
* \brief
* Memory frees of the Slice structure and of its dependent
* data structures
* \param slice:
* Slice to be freed
************************************************************************
*/
static void free_slice(Slice *slice)
{
int i;
DataPartition *dataPart;
if (slice != NULL)
{
for (i=0; i<slice->max_part_nr; i++) // loop over all data partitions
{
dataPart = &(slice->partArr[i]);
if (dataPart != NULL)
{
if (dataPart->bitstream->streamBuffer != NULL)
free(dataPart->bitstream->streamBuffer);
if (dataPart->bitstream != NULL)
free(dataPart->bitstream);
}
}
if (slice->partArr != NULL)
free(slice->partArr);
if (input->symbol_mode == CABAC)
{
delete_contexts_MotionInfo(slice->mot_ctx);
delete_contexts_TextureInfo(slice->tex_ctx);
}
free(slice);
}
}
void set_ref_pic_num()
{
int i,j;
StorablePicture *this_ref;
//! need to add field ref_pic_num that handles field pair.
for (i=0;i<listXsize[LIST_0];i++)
{
this_ref = listX[LIST_0][i];
enc_picture->ref_pic_num [LIST_0][i] = this_ref->poc * 2 + ((this_ref->structure==BOTTOM_FIELD)?1:0) ;
enc_picture->frm_ref_pic_num [LIST_0][i] = this_ref->frame_poc * 2;
enc_picture->top_ref_pic_num [LIST_0][i] = this_ref->top_poc * 2;
enc_picture->bottom_ref_pic_num [LIST_0][i] = this_ref->bottom_poc * 2 + 1;
}
for (i=0;i<listXsize[LIST_1];i++)
{
this_ref = listX[LIST_1][i];
enc_picture->ref_pic_num [LIST_1][i] = this_ref->poc *2 + ((this_ref->structure==BOTTOM_FIELD)?1:0);
enc_picture->frm_ref_pic_num [LIST_1][i] = this_ref->frame_poc * 2;
enc_picture->top_ref_pic_num [LIST_1][i] = this_ref->top_poc * 2;
enc_picture->bottom_ref_pic_num [LIST_1][i] = this_ref->bottom_poc * 2 + 1;
}
if (!active_sps->frame_mbs_only_flag && img->structure==FRAME)
{
for (j=2;j<6;j++)
for (i=0;i<listXsize[j];i++)
{
this_ref = listX[j][i];
enc_picture->ref_pic_num[j][i] = this_ref->poc * 2 + ((this_ref->structure==BOTTOM_FIELD)?1:0);
enc_picture->frm_ref_pic_num[j][i] = this_ref->frame_poc * 2 ;
enc_picture->top_ref_pic_num[j][i] = this_ref->top_poc * 2 ;
enc_picture->bottom_ref_pic_num[j][i] = this_ref->bottom_poc * 2 + 1;
}
}
}
/*!
************************************************************************
* \brief
* decide reference picture reordering, Frame only
************************************************************************
*/
void poc_ref_pic_reorder(StorablePicture **list, unsigned num_ref_idx_lX_active, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx, int list_no)
{
unsigned i,j,k;
int currPicNum, picNumLXPred;
int default_order[32];
int re_order[32];
int tmp_reorder[32];
int list_sign[32];
int reorder_stop, no_reorder;
int poc_diff[32];
int tmp_value, diff;
int abs_poc_dist;
int maxPicNum, MaxFrameNum = 1 << (log2_max_frame_num_minus4 + 4);
if (img->structure==FRAME)
{
maxPicNum = MaxFrameNum;
currPicNum = img->frame_num;
}
else
{
maxPicNum = 2 * MaxFrameNum;
currPicNum = 2 * img->frame_num + 1;
}
picNumLXPred = currPicNum;
// First assign default list order.
for (i=0; i<num_ref_idx_lX_active; i++)
{
default_order[i] = list[i]->pic_num;
}
// Now access all references in buffer and assign them
// to a pottential reordering list. For each one of these
// references compute the poc distance compared to current
// frame.
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
re_order[i] = dpb.fs_ref[i]->frame->pic_num;
if (dpb.fs_ref[i]->is_used==3 && (dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
{
abs_poc_dist = iabs(dpb.fs_ref[i]->frame->poc - enc_picture->poc) ;
poc_diff[i] = abs_poc_dist;
if (list_no == LIST_0)
{
list_sign[i] = (enc_picture->poc < dpb.fs_ref[i]->frame->poc) ? +1 : -1;
}
else
{
list_sign[i] = (enc_picture->poc > dpb.fs_ref[i]->frame->poc) ? +1 : -1;
}
}
}
// now sort these references based on poc (temporal) distance
for (i=0; i< dpb.ref_frames_in_buffer-1; i++)
{
for (j=i+1; j< dpb.ref_frames_in_buffer; j++)
{
if (poc_diff[i]>poc_diff[j] || (poc_diff[i] == poc_diff[j] && list_sign[j] > list_sign[i]))
{
tmp_value = poc_diff[i];
poc_diff[i] = poc_diff[j];
poc_diff[j] = tmp_value;
tmp_value = re_order[i];
re_order[i] = re_order[j];
re_order[j] = tmp_value ;
tmp_value = list_sign[i];
list_sign[i] = list_sign[j];
list_sign[j] = tmp_value ;
}
}
}
// Check versus default list to see if any
// change has happened
no_reorder = 1;
for (i=0; i<num_ref_idx_lX_active; i++)
{
if (default_order[i] != re_order[i])
{
no_reorder = 0;
}
}
// If different, then signal reordering
if (no_reorder==0)
{
for (i=0; i<num_ref_idx_lX_active; i++)
{
diff = re_order[i]-picNumLXPred;
if (diff <= 0)
{
reordering_of_pic_nums_idc[i] = 0;
abs_diff_pic_num_minus1[i] = iabs(diff)-1;
if (abs_diff_pic_num_minus1[i] < 0)
abs_diff_pic_num_minus1[i] = maxPicNum -1;
}
else
{
reordering_of_pic_nums_idc[i] = 1;
abs_diff_pic_num_minus1[i] = iabs(diff)-1;
}
picNumLXPred = re_order[i];
tmp_reorder[i] = re_order[i];
k = i;
for (j=i; j<num_ref_idx_lX_active; j++)
{
if (default_order[j] != re_order[i])
{
++k;
tmp_reorder[k] = default_order[j];
}
}
reorder_stop = 1;
for(j=i+1; j<num_ref_idx_lX_active; j++)
{
if (tmp_reorder[j] != re_order[j])
{
reorder_stop = 0;
break;
}
}
if (reorder_stop==1)
{
++i;
break;
}
for(j=0; j<num_ref_idx_lX_active; j++)
{
default_order[j] = tmp_reorder[j];
}
}
reordering_of_pic_nums_idc[i] = 3;
for(j=0; j<num_ref_idx_lX_active; j++)
{
default_order[j] = tmp_reorder[j];
}
if (list_no==0)
{
img->currentSlice->ref_pic_list_reordering_flag_l0=1;
}
else
{
img->currentSlice->ref_pic_list_reordering_flag_l1=1;
}
}
}
extern const int QP2QUANT[40];
void SetLagrangianMultipliers()
{
int qp, j, k;
double qp_temp;
double lambda_scale = 1.0 - dClip3(0.0,0.5,0.05 * (double) input->jumpd);;
if (input->rdopt) // RDOPT on computation of Lagrangian multipliers
{
for (j = 0; j < 5; j++)
{
for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
{
qp_temp = (double)qp + img->bitdepth_luma_qp_scale - SHIFT_QP;
if (input->UseExplicitLambdaParams == 1) // consideration of explicit lambda weights.
{
img->lambda_md[j][qp] = input->LambdaWeight[j] * pow (2, qp_temp/3.0);
// Scale lambda due to hadamard qpel only consideration
img->lambda_md[j][qp] = ( (input->MEErrorMetric[H_PEL] == ERROR_SATD && input->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[j][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
}
if (j == B_SLICE)
{
img->lambda_md[5][qp] = input->LambdaWeight[5] * pow (2, qp_temp/3.0);
img->lambda_md[5][qp] = ((input->MEErrorMetric[H_PEL] == ERROR_SATD && input->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[5][qp];
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[5][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
}
}
}
else if (input->UseExplicitLambdaParams == 2) // consideration of fixed lambda values.
{
img->lambda_md[j][qp] = input->FixedLambda[j];
// Scale lambda due to hadamard qpel only consideration
img->lambda_md[j][qp] = ( (input->MEErrorMetric[H_PEL] == ERROR_SATD && input->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[j][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
}
if (j == B_SLICE)
{
img->lambda_md[5][qp] = input->FixedLambda[5];
img->lambda_md[5][qp] = ((input->MEErrorMetric[H_PEL] == ERROR_SATD && input->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[5][qp];
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[5][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
}
}
}
else
{
if (input->successive_Bframe>0)
img->lambda_md[j][qp] = 0.68 * pow (2, qp_temp/3.0)
* (j == B_SLICE ? dClip3(2.00,4.00,(qp_temp / 6.0)) : (j == SP_SLICE) ? dClip3(1.4,3.0,(qp_temp / 12.0)) : 1.0);
else
img->lambda_md[j][qp] = 0.85 * pow (2, qp_temp/3.0)
* ( (j == B_SLICE) ? 4.0 : (j == SP_SLICE) ? dClip3(1.4,3.0,(qp_temp / 12.0)) : 1.0);
// Scale lambda due to hadamard qpel only consideration
img->lambda_md[j][qp] = ((input->MEErrorMetric[H_PEL] == ERROR_SATD && input->MEErrorMetric[Q_PEL] == ERROR_SATD) ? 1.00 : 0.95) * img->lambda_md[j][qp];
img->lambda_md[j][qp] = (j == B_SLICE && input->BRefPictures == 2 && img->b_frame_to_code == 0 ? 0.50 : 1.00) * img->lambda_md[j][qp];
if (j == B_SLICE)
{
img->lambda_md[5][qp] = img->lambda_md[j][qp];
if (input->HierarchicalCoding == 2)
img->lambda_md[5][qp] *= (1.0 - dmin(0.4,0.2 * (double) gop_structure[img->b_frame_to_code-1].hierarchy_layer)) ;
else
img->lambda_md[5][qp] *= 0.80;
img->lambda_md[5][qp] *= lambda_scale;
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[5][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[5][qp] : sqrt(img->lambda_md[5][qp]);
img->lambda_mf[5][qp][k] = LAMBDA_FACTOR (img->lambda_me[5][qp][k]);
}
}
else
img->lambda_md[j][qp] *= lambda_scale;
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[j][qp][k] = input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_md[j][qp] : sqrt(img->lambda_md[j][qp]);
img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
}
if (input->CtxAdptLagrangeMult == 1)
{
int lambda_qp = (qp >= 32 && !input->RCEnable) ? imax(0, qp - 4) : imax(0, qp - 6);
img->lambda_mf_factor[j][qp] = log (img->lambda_me[j][lambda_qp][Q_PEL] + 1.0) / log (2.0);
}
}
}
}
}
else // RDOPT off computation of Lagrangian multipliers
{
for (j = 0; j < 6; j++)
{
for (qp = -img->bitdepth_luma_qp_scale; qp < 52; qp++)
{
img->lambda_md[j][qp] = QP2QUANT[imax(0,qp - SHIFT_QP)];
for (k = F_PEL; k <= Q_PEL; k++)
{
img->lambda_me[j][qp][k] = img->lambda_md[j][qp];
img->lambda_me[j][qp][k] *= input->MEErrorMetric[k] == ERROR_SSE ? img->lambda_me[j][qp][k] : 1;
img->lambda_mf[j][qp][k] = LAMBDA_FACTOR (img->lambda_me[j][qp][k]);
}
if (input->CtxAdptLagrangeMult == 1)
{
int lambda_qp = (qp >= 32 && !input->RCEnable) ? imax(0, qp-4) : imax(0, qp-6);
img->lambda_mf_factor[j][qp] = log (img->lambda_me[j][lambda_qp][Q_PEL] + 1.0) / log (2.0);
}
}
}
}
}