videoeditorengine/h263decoder/src/decmbdct_mpeg.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:  
* Prediction error block decoding functions (MPEG-4).
*
*/



/* 
 * Includes 
 */
#include "h263dConfig.h"
#include "decmbdct.h"
#include "decblock.h"
#include "block.h"
#include "viddemux.h"
/* MVE */
#include "MPEG4Transcoder.h"

/*
 * Global functions
 */

/* {{-output"dmdGetAndDecodeMPEGIMBBlocks.txt"}} */
/*
 * dmdGetAndDecodeMPEGIMBBlocks
 *    
 *
 * Parameters:
 *    param                   parameters needed in this function
 *
 * Function:
 *    This function gets the DCT coefficients of an INTRA macroblock
 *    from the bitstream, reconstructs the corresponding
 *    pixel-domain blocks and puts the blocks to the output frame.
 *
 * Returns:
 *    >= 0                       the function was successful
 *    < 0                        an error occured when accessing bit buffer
 *
 */

int dmdGetAndDecodeMPEGIMBBlocks(
   dmdMPEGIParam_t *param, CMPEG4Transcoder *hTranscoder)
/* {{-output"dmdGetAndDecodeMPEGIMBBlocks.txt"}} */
{
   bibBuffer_t *inBuffer;

   bibBuffer_t 
      *outBuffer;        /* Output bit buffer instance */

   bibBufferEdit_t 
      *bufEdit; 

   int colorEffect;
   TBool getDecodedFrame;

   int i, j,
      block[64], cWidth, bitErrorIndication = 0, ret = 0;
   u_char *yBlockInFrame;
   int IntraDC_size, 
        IntraDC_delta,
        DC_coeff;

   inBuffer = param->inBuffer;
   outBuffer = param->outBuffer;
   bufEdit = param->bufEdit;
   colorEffect = param->iColorEffect; 
   getDecodedFrame = param->iGetDecodedFrame;

   if ( param->yMBInFrame )
    {
        yBlockInFrame = param->yMBInFrame +
            ((param->reversible_vlc && param->vlc_dec_direction) ? ((/*8 **/ param->yWidth<<3) + 8) : 0);
    }
   else
    {
        yBlockInFrame = NULL;
    }
   cWidth = (param->yWidth >>1 /*/ 2*/);
   

    /* Loop through the 4 Luminance and the 2 Chrominance blocks */
   for (j=0; j<=5; j++) 
   {

      /* if reversible decoding, the block numbering is reverse */
      if (param->reversible_vlc && param->vlc_dec_direction) 
      {
         i = 5-j;
      }
      else 
      {
         i=j;
      }

      /* MVE */
      hTranscoder->BeginOneBlock(i);

      bitErrorIndication = 0;

      /* Get Intra DC if not switched */
      if(!param->switched) {
         if (param->data_partitioned)
            IntraDC_delta = param->DC[i];
         else {
            ret = vdxGetIntraDC(inBuffer, outBuffer, bufEdit, colorEffect, &(param->StartByteIndex), &(param->StartBitIndex), 
                            i, &IntraDC_size, &IntraDC_delta, &bitErrorIndication);

            if ( ret < 0 )
               return DMD_ERR;
            else if ( ret == VDX_OK_BUT_BIT_ERROR )
               goto corruptedMB;
         }
         block[0] = IntraDC_delta;
      }

      /* Get DCT coefficients */
      if (((i<4) && (vdxIsYCoded(param->cbpy, i + 1))) ||
         ((i==4) && (vdxIsUCoded(param->cbpc))) ||
         ((i==5) && (vdxIsVCoded(param->cbpc))))
      {
         /* if reversible VLC, also the direction of decoding is relevant */
         if (param->reversible_vlc) 
         {
            if (!param->vlc_dec_direction)
               ret = vdxGetRVLCDCTBlock(inBuffer, (!param->switched), 1, block,
                                 &bitErrorIndication);
            else
               ret = vdxGetRVLCDCTBlockBackwards(inBuffer, (!param->switched), 1, block,
                                        &bitErrorIndication);
         } 
         else 
         {
            ret = vdxGetMPEGIntraDCTBlock(inBuffer, (!param->switched), block,
                                  &bitErrorIndication);
         }
         
         if ( ret < 0 )
            return DMD_ERR;
         else if ( ret == VDX_OK_BUT_BIT_ERROR )
            goto corruptedMB;

      } 
      /* if block is not coded */
      else 
      {
         memset(block + (!param->switched), 0, (63 + (param->switched))* sizeof(int));
      }

      /* MVE */
      hTranscoder->AddOneBlockDataToMB(i, block);            

      /* DC/AC prediction: reconstruct the Intra coefficients */
      aicDCACrecon(param->aicData, param->quant,
         param->fTopOfVP, param->fLeftOfVP, param->fBBlockOut,
         i, block, param->currMBNum);

      /* optimized nonlinear inverse quantization for Intra DC */
      DC_coeff = (block[0] *= aicDCScaler(param->quant,(i<4)?1:2));

      hTranscoder->AddOneBlockDCACrecon(i, block);           

      /* Update the AIC module data, with the current MB */
      aicBlockUpdate (param->aicData, param->currMBNum, i, block, 
         param->quant, DC_coeff);
      

      if(getDecodedFrame || hTranscoder->NeedDecodedYUVFrame())
      {
         /* inverse quantization and IDCT */
         dblIdctAndDequant(block, param->quant, 1);
            
          if (i<4)
          {
               blcBlockToFrame(block, yBlockInFrame, param->yWidth);
               if (param->reversible_vlc && param->vlc_dec_direction) 
               {
                   yBlockInFrame -= 8;
                   if (i == 2)
                       yBlockInFrame -= ((/*8 **/ param->yWidth<<3) - 16);
               } 
               else 
               {
                   yBlockInFrame += 8;
                   if (i & 1)
                       yBlockInFrame += ((/*8 **/ param->yWidth<<3) - 16);
               }
          }
          else
          {
              blcBlockToFrame(block, ((i==4)? param->uBlockInFrame : param->vBlockInFrame) , cWidth);   
          }
          
      }
            
   }
   /* for blocks */
   
   if ( hTranscoder->TranscodingOneMB(NULL) != TX_OK )
   {
      return DMD_ERR;
   }
    
   return DMD_OK;
   
corruptedMB:

   return DMD_BIT_ERR;
}

/* {{-output"dmdGetAndDecodeMPEGPMBBlocks.txt"}} */

/* without the possibility to decode only Y component (#ifdef H263D_LUMINANCE_ONLY) */
/*
 * dmdGetAndDecodeMPEGPMBBlocks
 *    
 *
 * Parameters:
 *    param                      parameters needed in this function
 *
 * Function:
 *    This function gets the DCT coefficients of an INTER macroblock
 *    from the bitstream, reconstructs the corresponding
 *    pixel-domain blocks and adds the blocks to the prediction frame.
 *
 * Returns:
 *    >= 0                       the function was successful
 *    < 0                        an error occured when accessing bit buffer
 *
 */

int dmdGetAndDecodeMPEGPMBBlocks(
   dmdPParam_t *param, CMPEG4Transcoder *hTranscoder)
/* {{-output"dmdGetAndDecodeMPEGPMBBlocks.txt"}} */
{
   int i, j, 
      bitErrorIndication = 0, /* Carries bit error indication information returned
                                 by the video demultiplexer module */
      ret = 0;
      
   bibBuffer_t *inBuffer;

   TBool getDecodedFrame;

   inBuffer = param->inBuffer;
   getDecodedFrame = param->iGetDecodedFrame;

   int yWidth, block[64];
   u_char *yBlockInFrame;
   int chrQuant;

   int fEscapeCodeUsed = 0;

   /* Find out the value of QP for chrominance block. */
   chrQuant = param->quant;

   yWidth = param->uvWidth <<1 /** 2*/;
   if ( param->currYMBInFrame )
    {
        yBlockInFrame = param->currYMBInFrame + 
            ((param->reversible_vlc && param->vlc_dec_direction) ? ((/*8 **/ yWidth<<3) + 8) : 0);
    }
   else
    {
        yBlockInFrame = NULL;
    }

   /* Loop through the 4 Luminance and the 2 Chrominance blocks */
   for (j=0; j<=5; j++) {
         
         /* if reversible decoding, the block numbering is reverse */
         if (param->reversible_vlc && param->vlc_dec_direction) 
         {
            i = 5-j;
         }
         else 
         {
            i=j;
         }
         
     /* MVE */
         hTranscoder->BeginOneBlock(i);
         
         if (((i<4) && (vdxIsYCoded(param->cbpy, i + 1))) ||
             ((i==4) && (vdxIsUCoded(param->cbpc))) ||
             ((i==5) && (vdxIsVCoded(param->cbpc))))
         {
             
             /* Get DCT coefficients */
             if (param->reversible_vlc) 
             {
                if (!param->vlc_dec_direction)
                    ret = vdxGetRVLCDCTBlock(inBuffer, 0, 0, block,
                    &bitErrorIndication);
                else
                    ret = vdxGetRVLCDCTBlockBackwards(inBuffer, 0, 0, block,
                    &bitErrorIndication);
             } 
             else 
             {
                ret = vdxGetDCTBlock(inBuffer, 0, 1, block, 
                     &bitErrorIndication, 0, param->quant, &fEscapeCodeUsed);
             }
             if ( ret < 0 )
                return DMD_ERR;
             else if ( ret == VDX_OK_BUT_BIT_ERROR )
                return DMD_BIT_ERR;
             
            hTranscoder->AddOneBlockDataToMB(i, block);          
            if(getDecodedFrame || hTranscoder->NeedDecodedYUVFrame()) // we need the YUV frames.
            {
                 
                /* IDCT & dequant */
                dblIdctAndDequant(block, ((i<4)?param->quant:chrQuant), 0);

                if (i<4)
                {
                     
                    blcAddBlock(block, yBlockInFrame,
                        yWidth, 0, 0, 0);
                } 
                else 
                {
                    /* U or V component */

                    blcAddBlock(block, ((i==4)? param->currUBlkInFrame : param->currVBlkInFrame), param->uvWidth, 0, 0, 0);
                }
            }
             
        }
         
         /* MVE */
         else
         {
             /* this block is not coded */
             hTranscoder->AddOneBlockDataToMB(i, NULL);          
         }

         
         if ((i<4) && yBlockInFrame)
         {
             if (param->reversible_vlc && param->vlc_dec_direction) {
                 yBlockInFrame -= 8;
                 if (i == 2)
                     yBlockInFrame -= ((/*8 **/ yWidth<<3) - 16);
             } else {
                 yBlockInFrame += 8;
                 if (i & 1)
                     yBlockInFrame += ((/*8 **/ yWidth<<3) - 16);
             }
             
         }
         else   //u,v
         {
             /* nothing here */
         }
   }

     
     /* MVE */
   if ( hTranscoder->TranscodingOneMB(param) != TX_OK )
    {
    return DMD_ERR;
    }
   return DMD_OK;
}
// End of File