diff options
author | Hendrik Leppkes <h.leppkes@gmail.com> | 2013-01-15 11:22:44 +0400 |
---|---|---|
committer | Hendrik Leppkes <h.leppkes@gmail.com> | 2013-01-15 11:31:21 +0400 |
commit | a9c8d77606449205f3e2b15143eeea4f12df73cf (patch) | |
tree | 30cd1792c39aaa255b9f62ab4c811cc51add7bdf /decoder | |
parent | 00b6435ee84b04f63f5060b5044e35be2a945a2b (diff) |
wmv9dmo: improve handling of streams not starting with a keyframe
When the wmv9 dmo internally drops a frame, it doesn't drop the timestamps
with it. So instead of letting the DMO drop frames, ensure the stream it
sees always starts with an I frame, and drop the frames ourselves.
Diffstat (limited to 'decoder')
-rw-r--r-- | decoder/LAVVideo/decoders/wmv9.cpp | 35 | ||||
-rw-r--r-- | decoder/LAVVideo/decoders/wmv9.h | 2 |
2 files changed, 27 insertions, 10 deletions
diff --git a/decoder/LAVVideo/decoders/wmv9.cpp b/decoder/LAVVideo/decoders/wmv9.cpp index 9e3922fc..c1b1b7d3 100644 --- a/decoder/LAVVideo/decoders/wmv9.cpp +++ b/decoder/LAVVideo/decoders/wmv9.cpp @@ -185,6 +185,8 @@ CDecWMV9::CDecWMV9(void) , m_bReorderBufferValid(FALSE) , m_rtReorderBuffer(AV_NOPTS_VALUE) , m_vc1Profile(0) + , m_bNeedKeyFrame(FALSE) + , m_nCodecId(AV_CODEC_ID_NONE) { memset(&m_StreamAR, 0, sizeof(m_StreamAR)); } @@ -333,6 +335,7 @@ STDMETHODIMP CDecWMV9::InitDecoder(AVCodecID codec, const CMediaType *pmt) /* Create input type */ GUID subtype = codec == AV_CODEC_ID_VC1 ? MEDIASUBTYPE_WVC1 : MEDIASUBTYPE_WMV3; + m_nCodecId = codec; mtIn.SetType(&MEDIATYPE_Video); mtIn.SetSubtype(&subtype); @@ -484,8 +487,6 @@ STDMETHODIMP CDecWMV9::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME rtS } if (!(dwStatus & DMO_INPUT_STATUSF_ACCEPT_DATA)) return S_FALSE; - - CMediaBuffer *pInBuffer = new CMediaBufferDecode(buffer, buflen); DWORD dwFlags = 0; if (bSyncPoint) @@ -495,18 +496,31 @@ STDMETHODIMP CDecWMV9::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME rtS if (rtStop != AV_NOPTS_VALUE) dwFlags |= DMO_INPUT_DATA_BUFFERF_TIMELENGTH; - if (m_bManualReorder) { + if (m_bManualReorder || m_bNeedKeyFrame) { AVPictureType pictype = parse_picture_type(buffer, buflen, m_vc1Profile, m_bInterlaced); - if (pictype == AV_PICTURE_TYPE_I || pictype == AV_PICTURE_TYPE_P) { - if (m_bReorderBufferValid) - m_timestampQueue.push(m_rtReorderBuffer); - m_rtReorderBuffer = rtStart; - m_bReorderBufferValid = TRUE; - } else { - m_timestampQueue.push(rtStart); + if (m_bManualReorder) { + if (pictype == AV_PICTURE_TYPE_I || pictype == AV_PICTURE_TYPE_P) { + if (m_bReorderBufferValid) + m_timestampQueue.push(m_rtReorderBuffer); + m_rtReorderBuffer = rtStart; + m_bReorderBufferValid = TRUE; + } else { + m_timestampQueue.push(rtStart); + } + } + + if (m_bNeedKeyFrame) { + if (pictype != AV_PICTURE_TYPE_I) { + if (m_bManualReorder) + m_timestampQueue.pop(); + return S_OK; + } else { + m_bNeedKeyFrame = FALSE; + } } } + CMediaBuffer *pInBuffer = new CMediaBufferDecode(buffer, buflen); hr = m_pDMO->ProcessInput(0, pInBuffer, dwFlags, rtStart, rtStop - rtStart); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> ProcessInput failed with hr: %0x%x", hr)); @@ -652,6 +666,7 @@ STDMETHODIMP CDecWMV9::Flush() std::queue<REFERENCE_TIME>().swap(m_timestampQueue); m_rtReorderBuffer = AV_NOPTS_VALUE; m_bReorderBufferValid = FALSE; + m_bNeedKeyFrame = (m_nCodecId == AV_CODEC_ID_VC1); return __super::Flush(); } diff --git a/decoder/LAVVideo/decoders/wmv9.h b/decoder/LAVVideo/decoders/wmv9.h index 13f34fda..67f92056 100644 --- a/decoder/LAVVideo/decoders/wmv9.h +++ b/decoder/LAVVideo/decoders/wmv9.h @@ -72,10 +72,12 @@ private: AVRational m_StreamAR; LAVPixelFormat m_OutPixFmt; + AVCodecID m_nCodecId; CCritSec m_BufferCritSec; std::vector<Buffer *> m_BufferQueue; + BOOL m_bNeedKeyFrame; BOOL m_bManualReorder; BOOL m_bReorderBufferValid; REFERENCE_TIME m_rtReorderBuffer; |