📄 iframe.cpp
字号:
/***********************************************************************/
/* iframe.cpp : Implementation of I-Frame video parser
* REALmagic Quasar Hardware Library
* Created by Kevin Vo
* Copyright Sigma Designs Inc
* Sigma Designs Proprietary and confidential
* Created on 7/24/01
/************************************************************************/
#include "pch.h"
#include "manager.h"
#include "splitter.h"
#include "videodef.h"
#include "iframe.h"
LONG g_lCounter = 0;
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI VideoThreadRoutine (PVOID pVal)
{
CIFrame *pCIFrame = 0;
pCIFrame = (CIFrame*)pVal;
pCIFrame->GetVideoInfo();
return 0;
}
/////////////////////////////////////////////////////////////////////////////
CIFrame::CIFrame()
{
m_bStopVideoDemux = FALSE;
m_bSequenceHeader = FALSE;
m_bSequenceEnd = FALSE;
m_bSequenceHeaderDisplay = TRUE;
m_bLookForPictureHeader = TRUE;
m_dw32Bits = 0;
m_iBitIndex = 0;
m_iFrameNumber = -1;
m_bFirstBuffer = TRUE;
MPEG2_Flag = 0;
m_bStartIFrame = m_bEndIFrame = FALSE;
// Sequence header
m_iHorizontalSize;
m_iVerticalSize;
m_iAspectRatio;
m_iFrameRateCode;
m_dwFrameRate;
m_dwBitRateVal;
// Sequence Extension
m_iProgressiveSequence;
m_iChromaFormat;
// Sequence Display Extension
m_iMatrixCoefficients;
// Picture Header
m_iTemporalRef;
m_iPictureCodeType;
m_iForwardFCode = 0x111;
m_iBackwardFCode = 0x111;
m_iFullPelForwardVector = 0;
m_iFullPelBackwardVector = 0;
// Picture Coding Extension
f_code[2][2];
m_iIntraDcPrecision;
m_iPictureStructure;
m_iTopFieldFirst;
m_iFramePredFrameDct;
m_iConcealmentMotionVectors;
m_iQScaleType;
m_iIntraVlcFormat;
m_iAlternateScan;
m_iRepeatFirstField;
m_iProgressiveFrame;
// Picture Display Extension
m_iFrameCenterHorizontalOffset[3];
m_iFrameCenterVerticalOffset[3];
// Picture Spatial Scalable Extension
m_iPictScal ;
m_iSpatialTemporalWeightCodeTableIndex;
m_iLowerLayerHorizontalOffset;
m_iLowerLayerVerticalOffset;
// SequenceScalableExtension
m_iScalableMode;
// Quant Matrix Extention
m_iIntraQuantiserMatrix[64];
m_iNonIntraQuantiserMatrix[64];
m_iChromaIntraQuantiserMatrix[64];
m_iChromaNonIntraQuantiserMatrix[64];
// Slice
m_iQuantiserScale;
m_pVideoSampleList = new CIMediaSampleList();
OSInitializeCriticalSection(&m_crVideoList);
m_bStartVideoThread = FALSE;
m_pVSample = 0;
m_pVBuffer = 0;
m_dwVLength = 0;
m_dwVIndex = 0;
m_hVideoThread = 0;
}
/////////////////////////////////////////////////////////////////////////////
CIFrame::~CIFrame()
{
if (m_hVideoThread) {
#ifdef _LINUXAPPS_
LinuxCloseThread (m_hVideoThread);
#else // _LINUXAPPS_
CloseHandle (m_hVideoThread);
#endif // _LINUXAPPS_
}
delete m_pVideoSampleList;
OSDeleteCriticalSection(&m_crVideoList);
}
/////////////////////////////////////////////////////////////////////////////
void CIFrame::StopDemux (void)
{
int timeout = 2000;
m_bStopVideoDemux = TRUE;
if (m_bStartVideoThread)
{
while (m_bStopVideoDemux && (--timeout > 0))
Sleep(1);
if (timeout == 0)
MmDebugLogfile ((MmDebugLevelLog, "CIFrame::StopDemux timeout"));
}
}
/////////////////////////////////////////////////////////////////////////////
void CIFrame::RestartDemux (void)
{
m_bStopVideoDemux = FALSE;
m_bStartVideoThread = FALSE;
}
/////////////////////////////////////////////////////////////////////////////
void CIFrame::Cleanup()
{
if (m_bStartVideoThread)
{
m_bStartVideoThread = FALSE;
#ifdef _LINUXAPPS_
LinuxCloseThread (m_hVideoThread);
#else // _LINUXAPPS_
CloseHandle (m_hVideoThread);
#endif // _LINUXAPPS_
m_hVideoThread = NULL;
if (m_pVSample)
m_pVSample->Release();
CIMediaSample *pMedia;
while (1)
{
pMedia = m_pVideoSampleList->GetMediaSample();
if (pMedia != NULL)
pMedia->Release();
else
break;
}
}
}
/////////////////////////////////////////////////////////////////////
void CIFrame::Receiver(CIMediaSample *pMedia)
{
if (m_bStopVideoDemux)
{
m_bStopVideoDemux = FALSE;
pMedia->Release();
return;
}
if (pMedia->GetMediaType() == MM_VIDEO)
{
OSEnterCriticalSection (&m_crVideoList);
m_pVideoSampleList->SetMediaSample (pMedia);
OSLeaveCriticalSection (&m_crVideoList);
if (!m_bStartVideoThread)
{
DWORD dwThreadId;
m_hVideoThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)::VideoThreadRoutine, this, 0, &dwThreadId);
m_bStartVideoThread = TRUE;
}
}
else
pMedia->Release();
}
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
DWORD CIFrame::GetVideoInfo()
{
int ret = 0;
// Buffer contains at least on sample.
OSEnterCriticalSection (&m_crVideoList);
m_pVSample = m_pVideoSampleList->GetMediaSample();
OSLeaveCriticalSection (&m_crVideoList);
m_pVBuffer = m_pVSample->GetPointer();
m_dwVLength = m_pVSample->GetActualDataLength();
m_dwVIndex = 0;
if (m_bFirstBuffer)
{
m_dw32Bits = GetNextByte ();
for (int i = 0; i < 3; i++)
m_dw32Bits = (m_dw32Bits << 8) + GetNextByte ();
m_iBitIndex = 32;
m_bFirstBuffer = FALSE;
}
while (!m_bStopVideoDemux)
{
try
{
ret = GetHeaders();
if (!ret)
{
m_pVSample->Release();
break;
}
else
{
if (m_iPictureCodeType == I_TYPE)
{
m_bStartIFrame = TRUE;
m_iStartIFrameIndex = m_dwVIndex;
}
// Get slice
for (;;)
{
GetStartCode();
if (m_bStopVideoDemux)
break;
if (ShowBits(32) < SLICE_START_CODE_MIN || ShowBits(32) > SLICE_START_CODE_MAX)
break;
FlushBits(32);
if (MPEG2_Flag && (m_iVerticalSize > 2800))
FlushBits(3);
if (m_iScalableMode == SC_DP)
FlushBits (7); // priority breakpoint
FlushBits (5); // quantiser scale code
if (ShowBits(1))
{
FlushBits(9); // Intra_Slice_Flag, intra_slice, reserved_bits
while (ShowBits(1)) // Extra information slice
{
FlushBits(9);
if (m_bStopVideoDemux)
break;
}
}
FlushBits(1); // extra_bit_slice (with the value 0)
// Get macroblock (quick and dirty!!)
for (;;)
{
if (!ShowBits(23)) // next_start_code or fault
break; // trigger: go to next slice
FlushBits(8);
if (m_bStopVideoDemux)
break;
}
}
if (m_iPictureCodeType == I_TYPE)
{
m_bEndIFrame = TRUE;
m_iEndIFrameIndex = m_dwVIndex-1;
}
}
Sleep(1);
}
catch (int err)
{
MmDebugLogfile ((MmDebugLevelTrace, "Exception thrown: %d", err));
}
} // end while
// Clean up the video buffer
Cleanup();
m_bStopVideoDemux = FALSE;
MmDebugLogfile((MmDebugLevelTrace, "IFrame thread exists"));
return ret;
}
////////////////////////////////////////////////////////////////////
int CIFrame::GetHeaders()
{
DWORD dwSyncCode = 0;
while (!m_bStopVideoDemux)
{
GetStartCode();
dwSyncCode = GetBits (32);
switch (dwSyncCode)
{
case SEQUENCE_HEADER_CODE:
SequenceHeader ();
m_bSequenceHeader = TRUE;
dwSyncCode = 0;
break;
case GROUP_START_CODE:
m_bLookForPictureHeader = FALSE;
GOPHeader ();
dwSyncCode = 0;
break;
case PICTURE_START_CODE:
if (!m_bLookForPictureHeader)
{
PictureHeader ();
return 1;
}
break;
case SEQUENCE_END_CODE:
m_bSequenceEnd = TRUE;
break;
}
}
return 0;
}
/////////////////////////////////////////////////////////////////////
BYTE CIFrame::GetNextByte()
{
if (m_bStopVideoDemux)
return 0;
if (m_dwVIndex >= m_dwVLength)
{
if (m_bEndIFrame)
{
m_bStartIFrame = m_bEndIFrame = FALSE;
m_pVSample->SetActualDataLength(m_iEndIFrameIndex);
SendToHardware (m_pVSample);
}
else if (m_bStartIFrame)
SendToHardware (m_pVSample);
m_pVSample->Release();
while (1)
{
OSEnterCriticalSection (&m_crVideoList);
m_pVSample = m_pVideoSampleList->GetMediaSample(); // Already AddRef
OSLeaveCriticalSection (&m_crVideoList);
if (m_pVSample)
break;
else if (m_bStopVideoDemux)
return 0;
else
{
Sleep(1);
MmDebugLogfile((MmDebugLevelTrace, "CIFrame needs more data"));
}
}
m_dwVLength = m_pVSample->GetActualDataLength();
m_pVBuffer = m_pVSample->GetPointer();
m_dwVIndex = 0;
}
return *(m_pVBuffer + m_dwVIndex++);
}
////////////////////////////////////////////////////////////////////
DWORD CIFrame::GetStartCode ()
{
FlushBits(m_iBitIndex & 7); // Align to next byte
while (ShowBits(24) != 0x000001)
{
FlushBits(8);
if (m_bStopVideoDemux)
return 0;
}
return 0;
}
////////////////////////////////////////////////////////////////////
DWORD CIFrame::GetBits(int bits)
{
register DWORD dwReturn;
int i;
if (m_bFirstBuffer)
{
m_dw32Bits = GetNextByte ();
for (i = 0; i < 3; i++)
m_dw32Bits = (m_dw32Bits << 8) + GetNextByte ();
m_iBitIndex = 32;
m_bFirstBuffer = FALSE;
}
dwReturn = m_dw32Bits;
dwReturn = dwReturn >> (32 - bits);
FlushBits (bits);
return dwReturn;
}
////////////////////////////////////////////////////////////////////
void CIFrame::FlushBits (int bits)
{
if (bits <= 31)
m_dw32Bits <<= bits;
m_iBitIndex -= bits;
// Try to maintain buffer with 32 bits if possible.
if (m_iBitIndex <= 24)
{
while (m_iBitIndex <= 24)
{
m_dw32Bits |= GetNextByte() << (24 - m_iBitIndex);
m_iBitIndex += 8;
}
}
}
////////////////////////////////////////////////////////////////////
DWORD CIFrame::ShowBits (int bits)
{
return m_dw32Bits >> (32 - bits);
}
////////////////////////////////////////////////////////////////////
void CIFrame::SequenceHeader ()
{
int i;
int iLoadIntraQuantiserMatrix;
int iLoadNonIntraQuantiserMatrix;
m_iHorizontalSize = GetBits (12);
m_iVerticalSize = GetBits (12);
m_iAspectRatio = GetBits (4);
m_iFrameRateCode = GetBits (4);
m_dwBitRateVal = GetBits (18);
FlushBits (1); // marker bit
FlushBits (10); // VbvBufferSizeVal
FlushBits (1); // ConstrainedParaFlag
iLoadIntraQuantiserMatrix = GetBits (1);
if (iLoadIntraQuantiserMatrix)
{
for (i = 0; i < 64; i++)
m_iIntraQuantiserMatrix[scan[ZIG_ZAG][i]] = GetBits(8);
}
else
{
for (i = 0; i < 64; i++)
m_iIntraQuantiserMatrix[i] = default_intra_quantizer_matrix[i];
}
iLoadNonIntraQuantiserMatrix = GetBits (1);
if (iLoadNonIntraQuantiserMatrix)
{
for (i = 0; i < 64; i++)
m_iNonIntraQuantiserMatrix[scan[ZIG_ZAG][i]] = GetBits (8);
}
else
{
for (i = 0; i < 64; i++)
m_iNonIntraQuantiserMatrix[i] = default_intra_quantizer_matrix[i];
}
// Copy luminance to chrominance matrices
for (i = 0; i<64; i++)
{
m_iChromaIntraQuantiserMatrix[i] = m_iIntraQuantiserMatrix[i];
m_iChromaNonIntraQuantiserMatrix[i] = m_iNonIntraQuantiserMatrix[i];
}
ExtensionUserData ();
}
////////////////////////////////////////////////////////////////////
void CIFrame::ExtensionUserData ()
{
DWORD dwSyncCode = 0;
int ext_ID;
GetStartCode();
while ((dwSyncCode = ShowBits(32))==EXTENSION_START_CODE || dwSyncCode==USER_DATA_START_CODE)
{
if (m_bStopVideoDemux)
break;
FlushBits(32);
if (dwSyncCode==EXTENSION_START_CODE)
{
ext_ID = GetBits(4);
switch (ext_ID)
{
case SEQUENCE_EXTENSION_ID:
SequenceExtension();
break;
case SEQUENCE_DISPLAY_EXTENSION_ID:
SequenceDisplayExtension();
break;
case QUANT_MATRIX_EXTENSION_ID:
QuantMatrixExtension();
break;
case SEQUENCE_SCALABLE_EXTENSION_ID:
SequenceScalableExtension();
break;
case PICTURE_DISPLAY_EXTENSION_ID:
PictureDisplayExtension();
break;
case PICTURE_CODING_EXTENSION_ID:
PictureCodingExtension();
break;
case PICTURE_SPATIAL_SCALABLE_EXTENSION_ID:
PictureSpatialScalableExtension();
break;
case PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID:
break;
case COPYRIGHT_EXTENSION_ID:
CopyrightExtension();
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -