예제 #1
0
int FmoSliceGroupCompletelyCoded( int SliceGroupID)
{
  if (FmoGetFirstMacroblockInSlice (SliceGroupID) < 0)  // slice group completelty coded or not present
    return TRUE;
  else
    return FALSE;
}
예제 #2
0
/*!
 ************************************************************************
 * \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;
        }