⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macroblock.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    se.value2  = 0;

#if TRACE
    if (se.value1 < 0 )
      snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 8x8 mode  = predicted (context: %d)",se.context);
    else
      snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 8x8 mode  = %3d (context: %d)",se.value1,se.context);
#endif

    // set symbol type and function pointers
    se.type = SE_INTRAPREDMODE;

    // encode and update rate
    writeIntraPredMode (&se, dataPart);

    bitCount[BITS_COEFF_Y_MB]+=se.len;
    rate += se.len;
  }

  return rate;
}

int writeIntraModes(Macroblock *currMB)
{
  switch (currMB->mb_type)
  {
  case I4MB:
    return writeIntra4x4Modes(currMB);
    break;
  case I8MB:
    return writeIntra8x8Modes(currMB);
    break;
  default:
    return 0;
    break;
  }
}

/*!
 ************************************************************************
 * \brief
 *    Converts 8x8 block type to coding value
 ************************************************************************
 */
int B8Mode2Value (short b8mode, short b8pdir)
{
  static const int b8start[8] = {0,0,0,0, 1, 4, 5, 10};
  static const int b8inc  [8] = {0,0,0,0, 1, 2, 2, 1};

  return (img->type!=B_SLICE) ? (b8mode - 4) : b8start[b8mode] + b8inc[b8mode] * b8pdir;
}


static int writeIPCMLuma (ImageParameters *img, imgpel **imgY, Bitstream *currStream, SyntaxElement *se, int *bitCount)
{
  int i, j;
  int bit_size = MB_BLOCK_SIZE * MB_BLOCK_SIZE * img->bitdepth_luma;
  bitCount[BITS_COEFF_Y_MB] += bit_size;
  se->len   = img->bitdepth_luma;
  se->type  = SE_MBTYPE;   

  for (j = img->pix_y; j < img->pix_y + MB_BLOCK_SIZE; j++)
  {      
    for (i = img->pix_x; i < img->pix_x + MB_BLOCK_SIZE; i++)
    {
      se->bitpattern = imgY[j][i];
      se->value1 = se->bitpattern;      
#if TRACE
      snprintf(se->tracestring, TRACESTRING_SIZE, "pcm_sample_luma (%d %d) = %d", j, i, se->bitpattern);
#endif
      writeSE_Fix(se, currStream);
    }
  }
  return bit_size;
}

static int writeIPCMChroma (ImageParameters *img, imgpel **imgUV, Bitstream *currStream, SyntaxElement *se, int *bitCount)
{
  int i, j;
  int bit_size = img->mb_cr_size_y * img->mb_cr_size_x * img->bitdepth_luma;
  bitCount[BITS_COEFF_UV_MB] += bit_size;
  se->len   = img->bitdepth_chroma;
  se->type  = SE_MBTYPE;

  for (j = img->pix_c_y; j < img->pix_c_y + img->mb_cr_size_y; j++)
  {
    for (i = img->pix_c_x; i < img->pix_c_x + img->mb_cr_size_x; i++)
    {
      se->bitpattern = imgUV[j][i];
      se->value1 = se->bitpattern;
#if TRACE
      //snprintf(se.tracestring, TRACESTRING_SIZE, "pcm_sample_chroma (%s) (%d %d) = %d", uv?"v":"u", j,i,se->bitpattern);
      snprintf(se->tracestring, TRACESTRING_SIZE, "pcm_sample_chroma (%d %d) = %d", j, i, se->bitpattern);
#endif
      writeSE_Fix(se, currStream);
    }
  }
  return bit_size;
}

static int writeIPCMByteAlign(Bitstream *currStream, SyntaxElement *se, int *bitCount)
{
  if (currStream->bits_to_go < 8)
  {
    // This will only happen in the CAVLC case, CABAC is already padded
    se->type  = SE_MBTYPE;
    se->len   = currStream->bits_to_go;      
    bitCount[BITS_COEFF_Y_MB]+= se->len;
    se->bitpattern = 0;
#if TRACE
    snprintf(se->tracestring, TRACESTRING_SIZE, "pcm_alignment_zero_bits = %d", se->len);
#endif
    writeSE_Fix(se, currStream);
    return se->len;
  }
  else 
    return 0;
}

/*!
************************************************************************
* \brief
*    Codes macroblock header
* \param currMB
*    current macroblock
* \param rdopt
*    true for calls during RD-optimization
* \param coeff_rate
*    bitrate of Luma and Chroma coeff
************************************************************************
*/
int writeMBLayer (Macroblock *currMB, int rdopt, int *coeff_rate)
{
  int             i,j;
  int             mb_nr      = img->current_mb_nr;
  int             prev_mb_nr = FmoGetPreviousMBNr(img->current_mb_nr);
  Macroblock*     prevMB     = mb_nr ? (&img->mb_data[prev_mb_nr]) : NULL;
  SyntaxElement   se;
  int*            bitCount   = currMB->bitcounter;
  Slice*          currSlice  = img->currentSlice;
  DataPartition*  dataPart;
  const int*      partMap    = assignSE2partition[params->partition_mode];
  int             no_bits    = 0;
  int             skip       = currMB->mb_type ? 0:((img->type == B_SLICE) ? !currMB->cbp:1);
  int             mb_type;
  int             prevMbSkipped = 0;
  int             mb_field_tmp;
  Macroblock      *topMB = NULL;

  int             WriteFrameFieldMBInHeader = 0;

  if (img->MbaffFrameFlag)
  {
    if (0==(mb_nr & 0x01))
    {
      WriteFrameFieldMBInHeader = 1; // top field

      prevMbSkipped = 0;
    }
    else
    {
      if (prevMB->mb_type ? 0:((img->type == B_SLICE) ? !prevMB->cbp:1))
      {
        WriteFrameFieldMBInHeader = 1; // bottom, if top was skipped
      }

      topMB= &img->mb_data[prev_mb_nr];
      prevMbSkipped = topMB->skip_flag;
    }
  }
  currMB->IntraChromaPredModeFlag = IS_INTRA(currMB);

  // choose the appropriate data partition
  dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);

  if(img->type == I_SLICE)
  {
    //========= write mb_aff (I_SLICE) =========
    if(WriteFrameFieldMBInHeader)
    {
      se.value1 = currMB->mb_field;
      se.value2 = 0;
      se.type   = SE_MBTYPE;

      TRACE_SE (se.tracestring, "mb_field_decoding_flag");
      writeFieldModeInfo(&se, dataPart);

      bitCount[BITS_MB_MODE] += se.len;
      no_bits                += se.len;
    }

    //========= write mb_type (I_SLICE) =========
    se.value1  = MBType2Value (currMB);
    se.value2  = 0;
    se.type    = SE_MBTYPE;

#if TRACE
    snprintf(se.tracestring, TRACESTRING_SIZE,   "mb_type (I_SLICE) (%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
#endif
    writeMB_typeInfo (&se, dataPart);

    bitCount[BITS_MB_MODE] += se.len;
    no_bits                += se.len;
  }
  // not I_SLICE, CABAC
  else if (currSlice->symbol_mode == CABAC)
  {
    if (img->MbaffFrameFlag && ((img->current_mb_nr & 0x01) == 0||prevMbSkipped))
    {
      mb_field_tmp = currMB->mb_field;
      currMB->mb_field = field_flag_inference(currMB);
      CheckAvailabilityOfNeighborsCABAC(currMB);
      currMB->mb_field = mb_field_tmp;
    }

    //========= write mb_skip_flag (CABAC) =========
    mb_type    = MBType2Value (currMB);
    se.value1  = mb_type;
    se.value2  = currMB->cbp;
    se.type    = SE_MBTYPE;

    TRACE_SE (se.tracestring, "mb_skip_flag");
    writeMB_skip_flagInfo_CABAC(currMB, &se, dataPart);

    bitCount[BITS_MB_MODE] += se.len;
    no_bits                += se.len;

    CheckAvailabilityOfNeighborsCABAC(currMB);

    //========= write mb_aff (CABAC) =========
    if(img->MbaffFrameFlag && !skip) // check for copy mode
    {
      if(WriteFrameFieldMBInHeader)
      {
        se.value1 = currMB->mb_field;
        se.value2 = 0;
        se.type   =  SE_MBTYPE;

        TRACE_SE(se.tracestring, "mb_field_decoding_flag");
        writeFieldModeInfo(&se, dataPart);

        bitCount[BITS_MB_MODE] += se.len;
        no_bits                += se.len;
      }
    }

    //========= write mb_type (CABAC) =========
    if (currMB->mb_type != 0 || ((img->type == B_SLICE) && (currMB->cbp != 0 || cmp_cbp[1] !=0 || cmp_cbp[2]!=0 )))
    {
      se.value1  = mb_type;
      se.value2  = 0;
      se.type    = SE_MBTYPE;

#if TRACE
      if (img->type == B_SLICE)
        snprintf(se.tracestring, TRACESTRING_SIZE, "mb_type (B_SLICE) (%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
      else
        snprintf(se.tracestring, TRACESTRING_SIZE, "mb_type (P_SLICE) (%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
#endif
      writeMB_typeInfo( &se, dataPart);

      bitCount[BITS_MB_MODE] += se.len;
      no_bits                += se.len;
    }
  }
  // VLC not intra
  else if (currMB->mb_type != 0 || ((img->type == B_SLICE) && (currMB->cbp != 0 || cmp_cbp[1] != 0 || cmp_cbp[2]!=0 )))
  {
    //===== Run Length Coding: Non-Skipped macroblock =====
    se.value1  = img->cod_counter;
    se.value2  = 0;
    se.type    = SE_MBTYPE;

    TRACE_SE (se.tracestring, "mb_skip_run");
    writeSE_UVLC(&se, dataPart);

    bitCount[BITS_MB_MODE] += se.len;
    no_bits                += se.len;

    // Reset cod counter
    img->cod_counter = 0;

    // write mb_aff
    if(img->MbaffFrameFlag && !skip) // check for copy mode
    {
      if(WriteFrameFieldMBInHeader)
      {
        se.value1 = currMB->mb_field;
        se.type   =  SE_MBTYPE;

        TRACE_SE(se.tracestring, "mb_field_decoding_flag");
        writeSE_Flag (&se, dataPart);

        bitCount[BITS_MB_MODE] += se.len;
        no_bits                += se.len;
      }
    }
    // Put out mb mode
    se.value1  = MBType2Value (currMB);

    if (img->type != B_SLICE)
    {
      se.value1--;
    }
    se.type    = SE_MBTYPE;
    se.value2  = 0;

#if TRACE
    if (img->type == B_SLICE)
      snprintf(se.tracestring, TRACESTRING_SIZE, "mb_type (B_SLICE) (%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
    else
      snprintf(se.tracestring, TRACESTRING_SIZE, "mb_type (P_SLICE) (%2d,%2d) = %3d",img->mb_x, img->mb_y, currMB->mb_type);
#endif
    writeMB_typeInfo(&se, dataPart);

    bitCount[BITS_MB_MODE] += se.len;
    no_bits                += se.len;
  }
  else
  {
    //Run Length Coding: Skipped macroblock
    img->cod_counter++;

    currMB->skip_flag = 1;
    // CAVLC
    for (j=0; j < (4 + img->num_blk8x8_uv); j++)
      for (i=0; i < 4; i++)
        img->nz_coeff [img->current_mb_nr][i][j]=0;


    if(FmoGetNextMBNr(img->current_mb_nr) == -1 && img->cod_counter>0)
    {
      // Put out run
      se.value1  = img->cod_counter;
      se.value2  = 0;
      se.type    = SE_MBTYPE;

      TRACE_SE(se.tracestring, "mb_skip_run");
      writeSE_UVLC(&se, dataPart);

      bitCount[BITS_MB_MODE] += se.len;
      no_bits                += se.len;

      // Reset cod counter
      img->cod_counter = 0;
    }
  }

  //init NoMbPartLessThan8x8Flag
  currMB->NoMbPartLessThan8x8Flag = (IS_DIRECT(currMB) && !(active_sps->direct_8x8_inference_flag))? 0: 1;

  if (currMB->mb_type == IPCM)
  {
    dataPart = &(currSlice->partArr[partMap[SE_LUM_DC_INTRA]]);
    if (currSlice->symbol_mode == CABAC)
    {
      int len;
      EncodingEnvironmentPtr eep = &dataPart->ee_cabac;
      len = arienco_bits_written(eep);
      arienco_done_encoding(eep); // This pads to byte
      len = arienco_bits_written(eep) - len;
      no_bits += len;
      // Now restart the encoder
      arienco_start_encoding(eep, dataPart->bitstream->streamBuffer, &(dataPart->bitstream->byte_pos));
    }


    writeIPCMByteAlign(dataPart->bitstream, &se, bitCount);

    no_bits += writeIPCMLuma (img, enc_picture->imgY, dataPart->bitstream, &se, bitCount);

    if ((active_sps->chroma_format_idc != YUV400) && !IS_INDEPENDENT(params))
    {
      int uv;
      for (uv = 0; uv < 2; uv ++)
      {
        no_bits += writeIPCMChroma (img, enc_picture->imgUV[uv], dataPart->bitstream, &se, bitCount);
      }
    }
    return no_bits;
  }

  dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);

  //===== BITS FOR 8x8 SUB-PARTITION MODES =====
  if (IS_P8x8 (currMB))
  {
    for (i=0; i<4; i++)
    {
      se.value1  = B8Mode2Value (currMB->b8mode[i], currMB->b8pdir[i]);
      se.value2  = 0;
      se.type    = SE_MBTYPE;
#if TRACE
      snprintf(se.tracestring, TRACESTRING_SIZE, "8x8 mode/pdir(%2d) = %3d/%d", i, currMB->b8mode[i], currMB->b8pdir[i]);
#endif
      writeB8_typeInfo (&se, dataPart);
      bitCount[BITS_MB_MODE]+= se.len;
      no_bits               += se.len;

      //set NoMbPartLessThan8x8Flag for P8x8 mode
      currMB->NoMbPartLessThan8x8Flag &= (currMB->b8mode[i]==0 && act

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -