mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 21:57:57 +03:00
327 lines
8.7 KiB
C++
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;
|
|
}
|
|
}
|