void ReadSequenceHeader::QuantizerMatrixReader::Execute(void* state, Framework::CBitStream& stream)
{
	while(1)
	{
		if(m_currentIndex == 0x40) return;
		m_table[m_currentIndex] = static_cast<uint8>(stream.GetBits_MSBF(8));
		m_currentIndex++;
	}
}
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;
	}
}
void ReadMotionVectors::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);

	while(1)
	{
		switch(m_programState)
		{
		case STATE_INIT:							goto Label_Init;
		case STATE_SINGLE_READVECTOR:				goto Label_Single_ReadVector;
		case STATE_DOUBLE_FIRST_READFIELDSELECT:	goto Label_Double_First_ReadFieldSelect;
		case STATE_DOUBLE_FIRST_READVECTOR:			goto Label_Double_First_ReadVector;
		case STATE_DOUBLE_SECOND_READFIELDSELECT:	goto Label_Double_Second_ReadFieldSelect;
		case STATE_DOUBLE_SECOND_READVECTOR:		goto Label_Double_Second_ReadVector;
		case STATE_DONE:							goto Label_Done;
		default:									assert(0);
		}

Label_Init:
		if(decoderState.motionVectorCount == 1)
		{
			m_motionVectorReader.Reset();
			m_programState = STATE_SINGLE_READVECTOR;
		}
		else
		{
			m_programState = STATE_DOUBLE_FIRST_READFIELDSELECT;
		}
		continue;

Label_Single_ReadVector:
		m_motionVectorReader.Execute(context, stream);
		m_motionVector[0] = ReadMotionVector::ComputeMotionVector(m_motionVector[0], decoderState.motionCode[0], decoderState.motionResidual[0], m_hrSize);
		m_motionVector[1] = ReadMotionVector::ComputeMotionVector(m_motionVector[1], decoderState.motionCode[1], decoderState.motionResidual[1], m_vrSize);
		m_programState = STATE_DONE;
		continue;

Label_Double_First_ReadFieldSelect:
		{
			uint8 fieldSelect = static_cast<uint8>(stream.GetBits_MSBF(1));
			m_motionVectorReader.Reset();
			m_programState = STATE_DOUBLE_FIRST_READVECTOR;
		}
		continue;

Label_Double_First_ReadVector:
		m_motionVectorReader.Execute(context, stream);
		m_programState = STATE_DOUBLE_SECOND_READFIELDSELECT;
		continue;

Label_Double_Second_ReadFieldSelect:
		{
			uint8 fieldSelect = static_cast<uint8>(stream.GetBits_MSBF(1));
			m_motionVectorReader.Reset();
			m_programState = STATE_DOUBLE_SECOND_READVECTOR;
		}
		continue;

Label_Double_Second_ReadVector:
		m_motionVectorReader.Execute(context, stream);
		m_programState = STATE_DONE;
		continue;

Label_Done:
		return;
	}
}
void ReadSequenceHeader::Execute(void* context, Framework::CBitStream& stream)
{
	MPEG_VIDEO_STATE* state(reinterpret_cast<MPEG_VIDEO_STATE*>(context));
	SEQUENCE_HEADER& sequenceHeader(state->sequenceHeader);

	while(1)
	{
		switch(m_programState)
		{
		case STATE_INIT:					goto Label_Init;
		case STATE_READSTRUCT:				goto Label_ReadStruct;
		case STATE_CHECKREADINTRAMATRIX:	goto Label_CheckReadIntraMatrix;
		case STATE_READINTRAMATRIX:			goto Label_ReadIntraMatrix;
		case STATE_CHECKREADNONINTRAMATRIX:	goto Label_CheckReadNonIntraMatrix;
		case STATE_READNONINTRAMATRIX:		goto Label_ReadNonIntraMatrix;
		case STATE_DONE:					goto Label_Done;
		default:							assert(0);
		}

Label_Init:
		m_structureReader.Reset();
		m_programState = STATE_READSTRUCT;
		continue;

Label_ReadStruct:
		m_structureReader.Execute(state, stream);
		m_programState = STATE_CHECKREADINTRAMATRIX;
		sequenceHeader.macroblockWidth = (sequenceHeader.horizontalSize + 15) / 16;
		//Need to check interlaced mode, etc.
		sequenceHeader.macroblockHeight = (sequenceHeader.verticalSize + 15) / 16;
		sequenceHeader.macroblockMaxAddress = sequenceHeader.macroblockWidth * sequenceHeader.macroblockHeight;
		continue;

Label_CheckReadIntraMatrix:
		sequenceHeader.loadIntraQuantiserMatrix = static_cast<uint8>(stream.GetBits_MSBF(1));
		if(sequenceHeader.loadIntraQuantiserMatrix)
		{
			m_quantizerMatrixReader.Reset();
			m_quantizerMatrixReader.SetTable(sequenceHeader.intraQuantiserMatrix);
			m_programState = STATE_READINTRAMATRIX;
		}
		else
		{
			m_programState = STATE_CHECKREADNONINTRAMATRIX;
		}
		continue;

Label_ReadIntraMatrix:
		m_quantizerMatrixReader.Execute(state, stream);
		m_programState = STATE_CHECKREADNONINTRAMATRIX;
		continue;

Label_CheckReadNonIntraMatrix:
		sequenceHeader.loadNonIntraQuantiserMatrix = static_cast<uint8>(stream.GetBits_MSBF(1));
		if(sequenceHeader.loadNonIntraQuantiserMatrix)
		{
			m_quantizerMatrixReader.Reset();
			m_quantizerMatrixReader.SetTable(sequenceHeader.nonIntraQuantiserMatrix);
			m_programState = STATE_READNONINTRAMATRIX;
		}
		else
		{
			m_programState = STATE_DONE;
		}
		continue;

Label_ReadNonIntraMatrix:
		m_quantizerMatrixReader.Execute(state, stream);
		m_programState = STATE_DONE;
		continue;

Label_Done:
		return;
	}
}