/*! ************************************************************************ * \brief * decodes one slice ************************************************************************ */ void decode_one_slice(struct img_par *img,struct inp_par *inp) { Boolean end_of_slice = FALSE; int read_flag; img->cod_counter=-1; //reset_ec_flags(); while (end_of_slice == FALSE) // loop over macroblocks { #if TRACE fprintf(p_trace,"\n*********** POC: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->ThisPOC, img->current_mb_nr, img->current_slice_nr, img->type); #endif // Initializes the current macroblock start_macroblock(img,inp, img->current_mb_nr); // Get the syntax elements from the NAL read_flag = read_one_macroblock(img,inp); decode_one_macroblock(img,inp); if(img->MbaffFrameFlag && dec_picture->mb_field[img->current_mb_nr]) { img->num_ref_idx_l0_active >>= 1; img->num_ref_idx_l1_active >>= 1; } //ercWriteMBMODEandMV(img,inp); end_of_slice=exit_macroblock(img,inp,(!img->MbaffFrameFlag||img->current_mb_nr%2)); }
void c_avs_enc:: bot_field(Picture *pic) { myboolean end_of_picture = myfalse; int_32_t CurrentMbNumber=0; int_32_t MBRowSize = img->width / MB_BLOCK_SIZE; int_32_t slice_nr =0; int_32_t slice_qp = img->qp; int_32_t len; img->top_bot = 1; //Yulj 2004.07.20 while (end_of_picture == myfalse) // loop over macroblocks { set_MB_parameters (CurrentMbNumber); if (input->slice_row_nr && (img->current_mb_nr ==0 ||(img->current_mb_nr>0 && img->mb_data[img->current_mb_nr].slice_nr != img->mb_data[img->current_mb_nr-1].slice_nr))) { // slice header start jlzheng 7.11 start_slice (); img->current_slice_qp = img->qp; img->current_slice_start_mb = img->current_mb_nr; len = SliceHeader(slice_nr, slice_qp); stat->bit_slice += len; slice_nr++; // slice header end } img->current_mb_nr_fld = img->current_mb_nr+img->total_number_mb; start_macroblock (); (this->*encode_one_macroblock) (); write_one_macroblock (1); terminate_macroblock (&end_of_picture); proceed2nextMacroblock (); CurrentMbNumber++; } terminate_picture (); if(!input->loop_filter_disable) DeblockFrame (img, imgY, imgUV); pic->bits_per_picture = 8 * (currBitStream->byte_pos); }
void c_avs_enc:: picture_data( ) { myboolean end_of_picture = myfalse; int_32_t CurrentMbNumber=0; int_32_t MBRowSize = img->img_width_in_mb; int_32_t slice_nr = 0; int_32_t slice_qp = img->qp; int_32_t len, i; //init the intra pred mode for(i=0; i<img->width/B8_SIZE+100; i++) { memset(img->ipredmode[i], -1, (img->height/B8_SIZE+100)*sizeof(int_32_t)); } for(i=0; i<img->total_number_mb; i++) { img->mb_data[i].slice_nr = -1; } if (input->rdopt) { switch(img->type) { case INTRA_IMG: encode_one_macroblock = &c_avs_enc::encode_one_intra_macroblock_rdo; break; case INTER_IMG: encode_one_macroblock = &c_avs_enc::encode_one_inter_macroblock_rdo; break; case B_IMG: encode_one_macroblock = &c_avs_enc::encode_one_b_frame_macroblock_rdo; break; } } else { // xzhao //img->type=INTRA_IMG; switch(img->type) { case INTRA_IMG: encode_one_macroblock = &c_avs_enc::encode_one_intra_macroblock_not_rdo; break; case INTER_IMG: encode_one_macroblock = &c_avs_enc::encode_one_inter_macroblock_not_rdo; break; case B_IMG: encode_one_macroblock = &c_avs_enc::encode_one_b_frame_macroblock_not_rdo; break; } } while (end_of_picture == myfalse) // loop over macroblocks { set_MB_parameters(CurrentMbNumber); if (input->slice_row_nr && (img->current_mb_nr ==0 ||(img->current_mb_nr>0 && img->mb_data[img->current_mb_nr].slice_nr != img->mb_data[img->current_mb_nr-1].slice_nr))) { #ifdef _ME_FOR_RATE_CONTROL_ if (glb_me_for_rate_control_flag) { start_slice (); } #else start_slice (); #endif img->current_slice_qp = img->qp; img->current_slice_start_mb = img->current_mb_nr; len = SliceHeader(slice_nr, slice_qp); img->current_slice_nr = slice_nr; stat->bit_slice += len; slice_nr++; } start_macroblock(); (this->*encode_one_macroblock)(); write_one_macroblock(1); terminate_macroblock (&end_of_picture); proceed2nextMacroblock (); CurrentMbNumber++; } terminate_picture (); DeblockFrame (img, imgY, imgUV); }
/*! ************************************************************************ * \brief * Encodes one slice * \para * returns the number of coded MBs in the SLice ************************************************************************ */ int encode_one_slice (int SliceGroupId, Picture *pic) { Boolean end_of_slice = FALSE; Boolean recode_macroblock; int len, i, j; int NumberOfCodedMBs = 0; int CurrentMbInScanOrder; int MBRowSize = img->width / MB_BLOCK_SIZE; double FrameRDCost, FieldRDCost; img->cod_counter = 0; CurrentMbInScanOrder = FmoGetFirstMacroblockInSlice (SliceGroupId); // printf ("\n\nEncode_one_slice: PictureID %d SliceGroupId %d SliceID %d FirstMB %d \n", img->tr, SliceGroupId, img->current_slice_nr, CurrentMbInScanOrder); set_MB_parameters (CurrentMbInScanOrder); init_slice (CurrentMbInScanOrder); Bytes_After_Header = img->currentSlice->partArr[0].bitstream->byte_pos; if (input->symbol_mode==CABAC) { SetCtxModelNumber (); } /* // 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; img_ref = img->nb_references; } */ len = start_slice (); // 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; img->nb_references = fb->short_used + fb->long_used; } */ // Update statistics stat->bit_slice += len; stat->bit_use_header[img->type] += len; // printf ("\n\n"); while (end_of_slice == FALSE) // loop over macroblocks { if (!img->MbaffFrameFlag) { recode_macroblock = FALSE; set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); 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 { CurrentMbInScanOrder = FmoGetNextMBNr (CurrentMbInScanOrder); if (CurrentMbInScanOrder == -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 (CurrentMbInScanOrder); } else { //! The statement below breaks obviously FMO. I believe the correct statement would be //! img->current_mb_nr = CurrentMbInScanOrder; //! It's now tested with an assert() (take it out if I'm wrong) and should be changed //! as soon as someone works on FMO img->current_mb_nr--;/*KS*/ assert (img->current_mb_nr == CurrentMbInScanOrder); } } 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"? // 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 set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); SetStateVariablesForFrameMode(); rdopt = &rddata_top_frame_mb; // store data in top frame MB TopFrameIsSkipped = 0; WriteFrameFieldMBInHeader = 1; encode_one_macroblock (); // code the MB as frame field_mb[img->mb_y][img->mb_x] = 0; // set the MB as field (for use in FindSkipMotionVector) FrameRDCost = rdopt->min_rdcost; //*** Top MB coded as frame MB ***// // go to the bottom MB in the MB pair CurrentMbInScanOrder = img->current_mb_nr + MBRowSize; img->field_mode = 0; // MB coded as frame //GB set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); rdopt = &rddata_bot_frame_mb; // store data in top frame MB WriteFrameFieldMBInHeader = TopFrameIsSkipped ? 1 : 0; field_mb[img->mb_y][img->mb_x] = 0; encode_one_macroblock (); // code the MB as frame field_mb[img->mb_y][img->mb_x] = 0; // set the MB as field (for use in FindSkipMotionVector) FrameRDCost += rdopt->min_rdcost; //*** Bottom MB coded as frame MB ***// // start coding the MB pair as a field MB pair CurrentMbInScanOrder -= MBRowSize; //! FMO problem and generally dirty, just to go back like this img->field_mode = 1; // MB coded as frame img->top_field = 1; // Set top field to 1 set_MB_parameters (CurrentMbInScanOrder); img->buf_cycle <<= 1; input->num_reference_frames <<= 1; img->num_ref_idx_l0_active <<= 1; img->num_ref_idx_l0_active += 1; start_macroblock (); img->height = input->img_height >> 1; rdopt = &rddata_top_field_mb; // store data in top frame MB SetStateVariablesForFieldMode(); TopFieldIsSkipped = 0; // set the top field MB skipped flag to 0 WriteFrameFieldMBInHeader = 1; encode_one_macroblock (); // code the MB as frame field_mb[img->mb_y][img->mb_x] = 1; // set the MB as field (for use in FindSkipMotionVector) FieldRDCost = rdopt->min_rdcost; //*** Top MB coded as field MB ***// CurrentMbInScanOrder += MBRowSize; img->top_field = 0; // Set top field to 0 set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); rdopt = &rddata_bot_field_mb; // store data in top frame MB SetStateVariablesForFieldMode(); WriteFrameFieldMBInHeader = TopFieldIsSkipped ? 1 : 0; encode_one_macroblock (); // code the MB as frame field_mb[img->mb_y][img->mb_x] = 1; // set the MB as field (for use in FindSkipMotionVector) FieldRDCost += rdopt->min_rdcost; //*** Bottom MB coded as field MB ***// // decide between frame/field MB pair if (FrameRDCost < FieldRDCost) { img->field_mode = 0; img->buf_cycle >>= 1; input->num_reference_frames >>= 1; MBPairIsField = 0; SetStateVariablesForFrameMode(); img->num_ref_idx_l0_active -= 1; img->num_ref_idx_l0_active >>= 1; } else { img->field_mode = 1; MBPairIsField = 1; SetStateVariablesForFieldMode(); img->height = input->img_height / 2; // set image height as frame height } if (MBPairIsField) img->top_field = 1; else img->top_field = 0; // go back to the Top MB in the MB pair CurrentMbInScanOrder -= MBRowSize; set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); for (i=0;i<4;i++) for (j=0;j<4;j++) { img->field_anchor[img->block_y+j][img->block_x+i] = 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 WriteFrameFieldMBInHeader = 1; write_one_macroblock (1); // write the Top MB data to the bitstream NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice terminate_macroblock (&end_of_slice, &recode_macroblock); // done coding the Top MB proceed2nextMacroblock (CurrentMbInScanOrder); // Go to next macroblock // go to the Bottom MB in the MB pair CurrentMbInScanOrder += MBRowSize; img->top_field = 0; set_MB_parameters (CurrentMbInScanOrder); start_macroblock (); for (i=0;i<4;i++) for (j=0;j<4;j++) { img->field_anchor[img->block_y+j][img->block_x+i] = 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 if (img->field_mode) WriteFrameFieldMBInHeader = TopFieldIsSkipped ? 1 : 0; else WriteFrameFieldMBInHeader = TopFrameIsSkipped ? 1 : 0; write_one_macroblock (0); // write the Bottom MB data to the bitstream NumberOfCodedMBs++; // only here we are sure that the coded MB is actually included in the slice terminate_macroblock (&end_of_slice, &recode_macroblock); // done coding the Top MB proceed2nextMacroblock (CurrentMbInScanOrder); // Go to next macroblock CurrentMbInScanOrder -= MBRowSize; if (MBPairIsField) // if MB Pair was coded as field the buffer size variables back to frame mode { img->buf_cycle >>= 1; input->num_reference_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 img->height = input->img_height; // reset the img->height CurrentMbInScanOrder++; //! Breaks FMO if (CurrentMbInScanOrder == img->total_number_mb - MBRowSize) end_of_slice = TRUE; // just in case it does n't get set in terminate_macroblock if (CurrentMbInScanOrder % MBRowSize == 0) //! Breaks FMO CurrentMbInScanOrder += MBRowSize; }