Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasimir666 <casimir666@users.sourceforge.net>2008-05-14 00:06:04 +0400
committerCasimir666 <casimir666@users.sourceforge.net>2008-05-14 00:06:04 +0400
commit3dfb1b96c1710ba00941fd374cce2cda582cf1b7 (patch)
tree36d5f1ecaee37aab9a5e403a6dd4fb7d5c39184e /src/filters/transform/mpcvideodec/DXVADecoderH264.cpp
parent2e3bb8f6f7fb4e64a8ec4eade6a8575f6186af4f (diff)
Fixed : revamped NALU parsing (to manage RTP and Annex B streams) for dxva decoder
Changed : Mpeg parser full support for VC1 streams in M2TS git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@514 10f7b99b-c216-0410-bff0-8a66a9350fd8
Diffstat (limited to 'src/filters/transform/mpcvideodec/DXVADecoderH264.cpp')
-rw-r--r--src/filters/transform/mpcvideodec/DXVADecoderH264.cpp194
1 files changed, 90 insertions, 104 deletions
diff --git a/src/filters/transform/mpcvideodec/DXVADecoderH264.cpp b/src/filters/transform/mpcvideodec/DXVADecoderH264.cpp
index e752a3d05..18508608e 100644
--- a/src/filters/transform/mpcvideodec/DXVADecoderH264.cpp
+++ b/src/filters/transform/mpcvideodec/DXVADecoderH264.cpp
@@ -107,55 +107,33 @@ void CDXVADecoderH264::Init()
void CDXVADecoderH264::CopyBitstream(BYTE* pDXVABuffer, BYTE* pBuffer, UINT& nSize)
{
- NALU Nalu;
- BYTE* pDataSlice = pBuffer;
- UINT nSliceSize = nSize;
+ CNalu Nalu;
int nDummy;
+ Nalu.SetBuffer (pBuffer, nSize, m_nNALLength);
nSize = 0;
- do
+ while (Nalu.ReadNext())
{
- if (FAILED (ReadNalu (&Nalu, pDataSlice, nSliceSize, m_nNALLength)) || (Nalu.len > nSliceSize))
+ switch (Nalu.GetType())
{
- ASSERT(FALSE);
- break;
- }
+ case NALU_TYPE_SLICE:
+ case NALU_TYPE_IDR:
+ // For AVC1, put startcode 0x000001
+ pDXVABuffer[0]=pDXVABuffer[1]=0;pDXVABuffer[2]=1;
+
+ // Copy NALU
+ memcpy (pDXVABuffer+3, Nalu.GetDataBuffer(), Nalu.GetDataLength());
+
+ // Add trailing bit
+// pDXVABuffer[Nalu.GetDataLength()+3] = 0x00; // ???????
+
+ pDXVABuffer += Nalu.GetDataLength() + 3;
+ nSize += Nalu.GetDataLength() + 3;
- switch (Nalu.nal_unit_type)
- {
- case NALU_TYPE_PPS :
- case NALU_TYPE_SPS :
- case NALU_TYPE_SEI :
- // Do not copy thoses units, accelerator don't like it
- break;
- default :
- if (m_nNALLength > 0)
- {
- // For AVC1, put startcode 0x000001
- pDXVABuffer[0]=pDXVABuffer[1]=0;pDXVABuffer[2]=1;
-
- // Copy NALU
- memcpy (pDXVABuffer+3, (BYTE*)pDataSlice+m_nNALLength, Nalu.len-m_nNALLength);
-
- // Add trailing bit
- pDXVABuffer[Nalu.len+3-m_nNALLength] = 0x00;
-
- pDXVABuffer += Nalu.len + 4 - m_nNALLength;
- nSize += Nalu.len + 4 - m_nNALLength;
- }
- else
- {
- memcpy (pDXVABuffer, (BYTE*)pDataSlice, Nalu.len);
- pDXVABuffer += Nalu.len;
- nSize += Nalu.len;
- }
- break;
+ break;
}
-
- pDataSlice += Nalu.len;
- nSliceSize -= Nalu.len;
- } while (nSliceSize > 0);
+ }
// Complete with zero padding (buffer size should be a multiple of 128)
nDummy = 128 - (nSize %128);
@@ -173,48 +151,42 @@ void CDXVADecoderH264::Flush()
__super::Flush();
}
-
HRESULT CDXVADecoderH264::DecodeFrame (BYTE* pDataIn, UINT nSize, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
{
HRESULT hr = S_FALSE;
- BYTE* pDataSlice = pDataIn;
- UINT nSliceSize = nSize;
- NALU Nalu;
+ CNalu Nalu;
+ bool bSliceFound = false;
+ BYTE* pDataSlice = NULL;
+ UINT nSliceSize = 0;
int nSurfaceIndex;
CComPtr<IMediaSample> pSampleToDeliver;
- bool bSliceFound = false;
- while (!bSliceFound && (nSliceSize>0))
+ Nalu.SetBuffer (pDataIn, nSize, m_nNALLength);
+
+ while (!bSliceFound && Nalu.ReadNext())
{
- CHECK_HR(ReadNalu (&Nalu, pDataSlice, nSliceSize, m_nNALLength));
- switch (Nalu.nal_unit_type)
+ switch (Nalu.GetType())
{
case NALU_TYPE_SLICE:
case NALU_TYPE_IDR:
+ pDataSlice = Nalu.GetDataBuffer();
+ nSliceSize = Nalu.GetDataLength();
bSliceFound = true;
break;
case NALU_TYPE_PPS :
case NALU_TYPE_SPS :
- FFH264DecodeBuffer (m_pFilter->GetAVCtx(), pDataSlice, nSliceSize);
+ FFH264DecodeBuffer (m_pFilter->GetAVCtx(), Nalu.GetNALBuffer(), Nalu.GetLength());
break;
}
-
- if (!bSliceFound)
- {
- if (Nalu.len > nSliceSize)
- return E_INVALIDARG;
- pDataSlice += Nalu.len;
- nSliceSize -= Nalu.len;
- }
}
if (!bSliceFound) return S_FALSE;
m_nMaxWaiting = min (max (m_DXVAPicParams.num_ref_frames, 3), 8);
// Parse slice header and set DX destination surface
- CHECK_HR (FFH264ReadSlideHeader (&m_DXVAPicParams, &m_DXVAScalingMatrix, m_pFilter->GetAVCtx(), pDataSlice+ m_nNALLength, nSliceSize - m_nNALLength));
+ CHECK_HR (FFH264ReadSlideHeader (&m_DXVAPicParams, &m_DXVAScalingMatrix, m_pFilter->GetAVCtx(), pDataSlice, nSliceSize));
// Wait I frame after a flush
if (m_bFlushed && !m_DXVAPicParams.IntraPicFlag)
return S_FALSE;
@@ -243,13 +215,13 @@ HRESULT CDXVADecoderH264::DecodeFrame (BYTE* pDataIn, UINT nSize, REFERENCE_TIME
CHECK_HR (EndFrame(nSurfaceIndex));
- if (AddToStore (nSurfaceIndex, pSampleToDeliver, (Nalu.nal_reference_idc != 0), rtStart, rtStop, m_DXVAPicParams.field_pic_flag))
+ if (AddToStore (nSurfaceIndex, pSampleToDeliver, Nalu.IsRefFrame(), rtStart, rtStop, m_DXVAPicParams.field_pic_flag))
{
// Reset when new picture group detected
if (m_DXVAPicParams.frame_num == 0) ClearRefFramesList();
hr = DisplayNextFrame();
}
- UpdateRefFramesList (m_DXVAPicParams.frame_num, (Nalu.nal_reference_idc != 0));
+ UpdateRefFramesList (m_DXVAPicParams.frame_num, Nalu.IsRefFrame());
m_bFlushed = false;
return hr;
@@ -324,58 +296,72 @@ void CDXVADecoderH264::UpdateRefFramesList (int nFrameNum, bool bRefFrame)
}
-HRESULT CDXVADecoderH264::ReadNalu (NALU* pNalu, BYTE* pBuffer, UINT nBufferLength, UINT NbBytesForSize)
+void CNalu::SetBuffer(BYTE* pBuffer, int nSize, int nNALSize)
{
- if (m_nNALLength > 0)
- {
- // NALU for AVC stream (Size -> Nalu)
- pNalu->data = pBuffer;
+ m_pBuffer = pBuffer;
+ m_nSize = nSize;
+ m_nNALSize = nNALSize;
+ m_nCurPos = 0;
+ m_nNextRTP = 0;
+
+ m_nNALStartPos = 0;
+ m_nNALDataPos = 0;
+ m_nDataLen = 0;
+}
- pNalu->data_len = 0;
- for (UINT i=0; i<NbBytesForSize; i++)
+bool CNalu::MoveToNextStartcode()
+{
+ for (int i=m_nCurPos; i<min (m_nNextRTP, m_nSize-4); i++)
+ {
+ if ((*((DWORD*)(m_pBuffer+i)) & 0x00FFFFFF) == 0x00010000)
{
- pNalu->data_len = (pNalu->data_len << 8) + *pNalu->data;
- pNalu->data++;
+ // Find next AnnexB Nal
+ m_nCurPos = i;
+ return true;
}
}
- else
+
+ if ((m_nNALSize != 0) && (m_nNextRTP < m_nSize))
{
- if (nBufferLength < 4) return E_INVALIDARG;
- // NALU for H264 streams (Startcode -> Nalu)
- if ((pBuffer[0] == 0x00) || (pBuffer[1] == 0x00) || (pBuffer[2] == 0x01))
- {
- pNalu->data = pBuffer + 3;
- pNalu->data_len = 3;
- }
- else if ((pBuffer[0] == 0x00) || (pBuffer[1] == 0x00) || (pBuffer[2] == 0x00) || (pBuffer[3] == 0x01))
- {
- pNalu->data = pBuffer + 4;
- pNalu->data_len = 4;
- }
- else
- {
- ASSERT (FALSE);
- return E_INVALIDARG;
- }
-
- for (int i=pNalu->data_len; i<nBufferLength; i++)
+ m_nCurPos = m_nNextRTP;
+ return true;
+ }
+
+ m_nCurPos = m_nSize;
+ return false;
+}
+
+bool CNalu::ReadNext()
+{
+ int nTemp;
+
+ if (m_nCurPos >= m_nSize) return false;
+
+ if ((m_nNALSize != 0) && (m_nCurPos == m_nNextRTP))
+ {
+ // RTP Nalu type
+ m_nNALStartPos = m_nCurPos;
+ m_nNALDataPos = m_nCurPos + m_nNALSize;
+ nTemp = 0;
+ for (UINT i=0; i<m_nNALSize; i++)
{
- if (i>=nBufferLength-3) // Test end of buffer!
- {
- pNalu->data_len += 3;
- break;
- }
- if ((pBuffer[i] == 0x00) && (pBuffer[i+1] == 0x00) && (pBuffer[i+2] == 0x01)) break;
- pNalu->data_len++;
+ nTemp = (nTemp << 8) + m_pBuffer[m_nCurPos++];
}
+ m_nNextRTP += nTemp + m_nNALSize;
+ MoveToNextStartcode();
+ }
+ else
+ {
+ // AnnexB Nalu
+ m_nNALStartPos = m_nCurPos;
+ m_nCurPos += 3;
+ m_nNALDataPos = m_nCurPos;
+ MoveToNextStartcode();
}
- pNalu->len = pNalu->data_len + NbBytesForSize;
- pNalu->forbidden_bit = (*pNalu->data>>7) & 1;
- pNalu->nal_reference_idc = (*pNalu->data>>5) & 3;
- pNalu->nal_unit_type = (*pNalu->data) & 0x1f;
- pNalu->data++;
- pNalu->data_len--;
+ forbidden_bit = (m_pBuffer[m_nNALDataPos]>>7) & 1;
+ nal_reference_idc = (m_pBuffer[m_nNALDataPos]>>5) & 3;
+ nal_unit_type = (NALU_TYPE) (m_pBuffer[m_nNALDataPos] & 0x1f);
- return S_OK;
+ return true;
}