Play-/tools/MediaCenter/Source/VideoStream_ReadMacroblock.cpp
2018-04-30 21:01:23 +01:00

327 lines
8.7 KiB
C++

#include <assert.h>
#include "MpegVideoState.h"
#include "VideoStream_ReadMacroblock.h"
#include "MPEG2/MacroblockAddressIncrementTable.h"
#include "MPEG2/CodedBlockPatternTable.h"
#include "../../../Source/Log.h"
#include "LogSettings.h"
using namespace VideoStream;
ReadMacroblock::ReadMacroblock()
{
}
ReadMacroblock::~ReadMacroblock()
{
}
void ReadMacroblock::RegisterOnMacroblockDecodedHandler(const OnMacroblockDecodedHandler& handler)
{
m_OnMacroblockDecodedHandler = handler;
}
void ReadMacroblock::Reset()
{
m_programState = STATE_INIT;
}
void ReadMacroblock::Execute(void* context, Framework::CBitStream& stream)
{
MPEG_VIDEO_STATE* state(reinterpret_cast<MPEG_VIDEO_STATE*>(context));
PICTURE_HEADER& pictureHeader(state->pictureHeader);
BLOCK_DECODER_STATE& decoderState(state->blockDecoderState);
PICTURE_CODING_EXTENSION& pictureCodingExtension(state->pictureCodingExtension);
SEQUENCE_HEADER& sequenceHeader(state->sequenceHeader);
while(1)
{
switch(m_programState)
{
case STATE_INIT:
goto Label_Init;
case STATE_ESCAPE:
goto Label_Escape;
case STATE_SKIPESCAPE:
goto Label_SkipEscape;
case STATE_READMBINCREMENT:
goto Label_ReadMbIncrement;
case STATE_READMBMODES:
goto Label_ReadMbModes;
case STATE_READDCTTYPE:
goto Label_ReadDctType;
case STATE_CHECKMBMODES:
goto Label_CheckMbModes;
case STATE_CHECKMBMODES_QSC:
goto Label_CheckMbModes_Qsc;
case STATE_CHECKMBMODES_FWM_INIT:
goto Label_CheckMbModes_Fwm_Init;
case STATE_CHECKMBMODES_FWM:
goto Label_CheckMbModes_Fwm;
case STATE_CHECKMBMODES_BKM_INIT:
goto Label_CheckMbModes_Bkm_Init;
case STATE_CHECKMBMODES_BKM:
goto Label_CheckMbModes_Bkm;
case STATE_CHECKMBMODES_CBP:
goto Label_CheckMbModes_Cbp;
case STATE_READBLOCKINIT:
goto Label_ReadBlockInit;
case STATE_READBLOCK:
goto Label_ReadBlock;
default:
assert(0);
}
Label_Init:
decoderState.mbIncrement = 0;
m_programState = STATE_ESCAPE;
continue;
Label_Escape:
{
uint32 escapeSequence = stream.PeekBits_MSBF(11);
if(escapeSequence != 0x08)
{
m_programState = STATE_READMBINCREMENT;
}
else
{
m_programState = STATE_SKIPESCAPE;
}
}
continue;
Label_SkipEscape:
stream.Advance(11);
#ifdef _DECODE_LOGGING
CLog::GetInstance().Print(DECODE_LOG_NAME, "Symbol(%d, 'mb increment') = %d\r\n",
g_currentVdec++, 35);
#endif
decoderState.mbIncrement += 33;
m_programState = STATE_ESCAPE;
continue;
Label_ReadMbIncrement:
uint32 increment = MPEG2::CMacroblockAddressIncrementTable::GetInstance()->GetSymbol(&stream);
#ifdef _DECODE_LOGGING
CLog::GetInstance().Print(DECODE_LOG_NAME, "Symbol(%d, 'mb increment') = %d\r\n",
g_currentVdec++, increment);
#endif
decoderState.mbIncrement += increment;
if(decoderState.mbIncrement != 1)
{
decoderState.currentMbAddress += (decoderState.mbIncrement - 1);
decoderState.mbIncrement = 1;
{
int16 resetValue = 0;
switch(pictureCodingExtension.intraDcPrecision)
{
case 0:
resetValue = 128;
break;
case 1:
resetValue = 256;
break;
case 2:
resetValue = 512;
break;
default:
resetValue = 0;
assert(0);
break;
}
decoderState.dcPredictor[0] = resetValue;
decoderState.dcPredictor[1] = resetValue;
decoderState.dcPredictor[2] = resetValue;
}
if((pictureHeader.pictureCodingType == PICTURE_TYPE_P))
{
decoderState.forwardMotionVector[0] = 0;
decoderState.forwardMotionVector[1] = 0;
}
}
m_macroblockModesReader.Reset();
m_programState = STATE_READMBMODES;
continue;
Label_ReadMbModes:
m_macroblockModesReader.Execute(context, stream);
#ifdef _DECODE_LOGGING
CLog::GetInstance().Print(DECODE_LOG_NAME, "Symbol(%d, 'mb type') = %d\r\n",
g_currentVdec++, decoderState.macroblockType);
#endif
if(
(!pictureCodingExtension.framePredFrameDct) &&
(decoderState.macroblockType & (MACROBLOCK_MODE_BLOCK_PATTERN | MACROBLOCK_MODE_INTRA)))
{
m_programState = STATE_READDCTTYPE;
}
else
{
m_programState = STATE_CHECKMBMODES;
}
continue;
Label_ReadDctType:
decoderState.dctType = static_cast<uint8>(stream.GetBits_MSBF(1));
m_programState = STATE_CHECKMBMODES;
continue;
Label_CheckMbModes:
m_programState = STATE_CHECKMBMODES_QSC;
continue;
Label_CheckMbModes_Qsc:
if(decoderState.macroblockType & MACROBLOCK_MODE_QUANT)
{
decoderState.quantizerScaleCode = static_cast<uint8>(stream.GetBits_MSBF(5));
}
m_programState = STATE_CHECKMBMODES_FWM_INIT;
continue;
Label_CheckMbModes_Fwm_Init:
if(sequenceHeader.isMpeg2)
{
m_motionVectorsReader.Reset();
m_motionVectorsReader.SetRSizes(pictureCodingExtension.fcode00 - 1, pictureCodingExtension.fcode01 - 1);
}
else
{
m_singleMotionVectorReader.Reset();
m_singleMotionVectorReader.SetRSizes(pictureHeader.forwardFCode - 1, pictureHeader.forwardFCode - 1);
}
m_programState = STATE_CHECKMBMODES_FWM;
continue;
Label_CheckMbModes_Fwm:
if(decoderState.macroblockType & MACROBLOCK_MODE_MOTION_FORWARD) //or intra & concealment motion vectors
{
if(sequenceHeader.isMpeg2)
{
m_motionVectorsReader.SetMotionVector(decoderState.forwardMotionVector);
m_motionVectorsReader.Execute(context, stream);
}
else
{
m_singleMotionVectorReader.Execute(context, stream);
decoderState.forwardMotionVector[0] =
ReadMotionVector::ComputeMotionVector(decoderState.forwardMotionVector[0], decoderState.motionCode[0], decoderState.motionResidual[0], pictureHeader.forwardFCode - 1);
decoderState.forwardMotionVector[1] =
ReadMotionVector::ComputeMotionVector(decoderState.forwardMotionVector[1], decoderState.motionCode[1], decoderState.motionResidual[1], pictureHeader.forwardFCode - 1);
}
}
m_programState = STATE_CHECKMBMODES_BKM_INIT;
continue;
Label_CheckMbModes_Bkm_Init:
if(sequenceHeader.isMpeg2)
{
m_motionVectorsReader.Reset();
m_motionVectorsReader.SetRSizes(pictureCodingExtension.fcode10 - 1, pictureCodingExtension.fcode11 - 1);
}
else
{
m_singleMotionVectorReader.Reset();
m_singleMotionVectorReader.SetRSizes(pictureHeader.backwardFCode - 1, pictureHeader.backwardFCode - 1);
}
m_programState = STATE_CHECKMBMODES_BKM;
continue;
Label_CheckMbModes_Bkm:
if(decoderState.macroblockType & MACROBLOCK_MODE_MOTION_BACKWARD)
{
if(sequenceHeader.isMpeg2)
{
m_motionVectorsReader.SetMotionVector(decoderState.backwardMotionVector);
m_motionVectorsReader.Execute(context, stream);
}
else
{
m_singleMotionVectorReader.Execute(context, stream);
}
}
m_programState = STATE_CHECKMBMODES_CBP;
continue;
Label_CheckMbModes_Cbp:
if(decoderState.macroblockType & MACROBLOCK_MODE_BLOCK_PATTERN)
{
//Need to verify that
decoderState.codedBlockPattern = static_cast<uint8>(MPEG2::CCodedBlockPatternTable::GetInstance()->GetSymbol(&stream));
}
else
{
if(
(pictureHeader.pictureCodingType == PICTURE_TYPE_I) ||
(decoderState.macroblockType & MACROBLOCK_MODE_INTRA))
{
decoderState.codedBlockPattern = 0x3F;
}
else
{
decoderState.codedBlockPattern = 0;
}
}
m_programState = STATE_READBLOCKINIT;
continue;
Label_ReadBlockInit:
m_blockReader.Reset();
#ifdef _DECODE_LOGGING
if(decoderState.codedBlockPattern != 0)
{
static int currentMbIndex = 0;
CLog::GetInstance().Print(DECODE_LOG_NAME, "Macroblock(%d, CBP: 0x%0.2X)\r\n",
currentMbIndex++, decoderState.codedBlockPattern);
}
#endif
m_programState = STATE_READBLOCK;
continue;
Label_ReadBlock:
m_blockReader.Execute(context, stream);
if(!(decoderState.macroblockType & MACROBLOCK_MODE_INTRA))
{
int16 resetValue = 0;
switch(pictureCodingExtension.intraDcPrecision)
{
case 0:
resetValue = 128;
break;
case 1:
resetValue = 256;
break;
case 2:
resetValue = 512;
break;
default:
resetValue = 0;
assert(0);
break;
}
decoderState.dcPredictor[0] = resetValue;
decoderState.dcPredictor[1] = resetValue;
decoderState.dcPredictor[2] = resetValue;
}
if((pictureHeader.pictureCodingType == PICTURE_TYPE_P) && !(decoderState.macroblockType & (MACROBLOCK_MODE_INTRA | MACROBLOCK_MODE_MOTION_FORWARD)))
{
decoderState.forwardMotionVector[0] = 0;
decoderState.forwardMotionVector[1] = 0;
}
if((decoderState.macroblockType & MACROBLOCK_MODE_INTRA) && (pictureCodingExtension.concealmentMotionVectors == 0))
{
decoderState.forwardMotionVector[0] = 0;
decoderState.forwardMotionVector[1] = 0;
decoderState.backwardMotionVector[0] = 0;
decoderState.backwardMotionVector[1] = 0;
}
if(m_OnMacroblockDecodedHandler)
{
m_OnMacroblockDecodedHandler(state);
}
decoderState.currentMbAddress += decoderState.mbIncrement;
return;
}
}