STDMETHODIMP CDecWMV9::InitDecoder(AVCodecID codec, const CMediaType *pmt) { HRESULT hr = S_OK; DbgLog((LOG_TRACE, 10, L"CDecWMV9::InitDecoder(): Initializing WMV9 DMO decoder")); DestroyDecoder(false); BITMAPINFOHEADER *pBMI = nullptr; REFERENCE_TIME rtAvg = 0; DWORD dwARX = 0, dwARY = 0; videoFormatTypeHandler(*pmt, &pBMI, &rtAvg, &dwARX, &dwARY); size_t extralen = 0; BYTE *extra = nullptr; getExtraData(*pmt, nullptr, &extralen); if (extralen > 0) { extra = (BYTE *)av_mallocz(extralen + FF_INPUT_BUFFER_PADDING_SIZE); getExtraData(*pmt, extra, &extralen); } if (codec == AV_CODEC_ID_VC1 && extralen) { size_t i = 0; for (i = 0; i < (extralen - 4); i++) { uint32_t code = AV_RB32(extra+i); if ((code & ~0xFF) == 0x00000100) break; } if (i == 0) { memmove(extra+1, extra, extralen); *extra = 0; extralen++; } else if (i > 1) { DbgLog((LOG_TRACE, 10, L"-> VC-1 Header at position %u (should be 0 or 1)", i)); } } /* Create input type */ GUID subtype = VerifySubtype(codec, pmt->subtype); m_nCodecId = codec; mtIn.SetType(&MEDIATYPE_Video); mtIn.SetSubtype(&subtype); mtIn.SetFormatType(&FORMAT_VideoInfo); mtIn.SetTemporalCompression(TRUE); mtIn.SetSampleSize(0); mtIn.SetVariableSize(); VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)mtIn.AllocFormatBuffer((ULONG)(sizeof(VIDEOINFOHEADER) + extralen)); memset(vih, 0, sizeof(VIDEOINFOHEADER)); vih->bmiHeader.biWidth = pBMI->biWidth; vih->bmiHeader.biHeight = pBMI->biHeight; vih->bmiHeader.biPlanes = 1; vih->bmiHeader.biBitCount = 24; vih->bmiHeader.biSizeImage = pBMI->biWidth * pBMI->biHeight * 3 / 2; vih->bmiHeader.biSize = (DWORD)(sizeof(BITMAPINFOHEADER) + extralen); vih->bmiHeader.biCompression = subtype.Data1; vih->AvgTimePerFrame = rtAvg; SetRect(&vih->rcSource, 0, 0, pBMI->biWidth, pBMI->biHeight); vih->rcTarget = vih->rcSource; if (extralen > 0) { memcpy((BYTE *)vih + sizeof(VIDEOINFOHEADER), extra, extralen); av_freep(&extra); extra = (BYTE *)vih + sizeof(VIDEOINFOHEADER); } hr = m_pDMO->SetInputType(0, &mtIn, 0); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Failed to set input type on DMO")); return hr; } /* Create output type */ int idx = 0; while(SUCCEEDED(hr = m_pDMO->GetOutputType(0, idx++, &mtOut))) { if (mtOut.subtype == MEDIASUBTYPE_NV12) { hr = m_pDMO->SetOutputType(0, &mtOut, 0); m_OutPixFmt = LAVPixFmt_NV12; break; } else if (mtOut.subtype == MEDIASUBTYPE_YV12) { hr = m_pDMO->SetOutputType(0, &mtOut, 0); m_OutPixFmt = LAVPixFmt_YUV420; break; } } if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Failed to set output type on DMO")); return hr; } videoFormatTypeHandler(mtOut, &pBMI); m_pRawBufferSize = pBMI->biSizeImage + FF_INPUT_BUFFER_PADDING_SIZE; m_bInterlaced = FALSE; memset(&m_StreamAR, 0, sizeof(m_StreamAR)); if (extralen > 0) { m_vc1Header = new CVC1HeaderParser(extra, extralen, codec); if (m_vc1Header->hdr.valid) { m_bInterlaced = m_vc1Header->hdr.interlaced; m_StreamAR = m_vc1Header->hdr.ar; } } m_bManualReorder = (codec == AV_CODEC_ID_VC1) && !(m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_ONLY_DTS); return S_OK; }
STDMETHODIMP CDecWMV9MFT::InitDecoder(AVCodecID codec, const CMediaType *pmt) { HRESULT hr = S_OK; DbgLog((LOG_TRACE, 10, L"CDecWMV9MFT::InitDecoder(): Initializing WMV9 MFT decoder")); DestroyDecoder(false); BITMAPINFOHEADER *pBMI = nullptr; REFERENCE_TIME rtAvg = 0; DWORD dwARX = 0, dwARY = 0; videoFormatTypeHandler(*pmt, &pBMI, &rtAvg, &dwARX, &dwARY); size_t extralen = 0; BYTE *extra = nullptr; getExtraData(*pmt, nullptr, &extralen); if (extralen > 0) { extra = (BYTE *)av_mallocz(extralen + FF_INPUT_BUFFER_PADDING_SIZE); getExtraData(*pmt, extra, &extralen); } if (codec == AV_CODEC_ID_VC1 && extralen) { size_t i = 0; for (i = 0; i < (extralen - 4); i++) { uint32_t code = AV_RB32(extra + i); if ((code & ~0xFF) == 0x00000100) break; } if (i == 0) { memmove(extra + 1, extra, extralen); *extra = 0; extralen++; } else if (i > 1) { DbgLog((LOG_TRACE, 10, L"-> VC-1 Header at position %u (should be 0 or 1)", i)); } } if (extralen > 0) { m_vc1Header = new CVC1HeaderParser(extra, extralen, codec); } /* Create input type */ m_nCodecId = codec; IMFMediaType *pMTIn = nullptr; MF.CreateMediaType(&pMTIn); pMTIn->SetUINT32(MF_MT_COMPRESSED, TRUE); pMTIn->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, FALSE); pMTIn->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, FALSE); pMTIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); pMTIn->SetGUID(MF_MT_SUBTYPE, VerifySubtype(codec, pmt->subtype)); MFSetAttributeSize(pMTIn, MF_MT_FRAME_SIZE, pBMI->biWidth, pBMI->biHeight); UINT32 rateNum = 0, rateDen = 0; MF.AverageTimePerFrameToFrameRate(rtAvg, &rateNum, &rateDen); MFSetAttributeRatio(pMTIn, MF_MT_FRAME_RATE, rateNum, rateDen); pMTIn->SetBlob(MF_MT_USER_DATA, extra, (UINT32)extralen); av_freep(&extra); hr = m_pMFT->SetInputType(0, pMTIn, 0); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Failed to set input type on MFT")); return hr; } /* Create output type */ hr = SelectOutputType(); SafeRelease(&pMTIn); if (FAILED(hr)) { DbgLog((LOG_TRACE, 10, L"-> Failed to set output type on MFT")); return hr; } IMFMediaType *pMTOut = nullptr; m_pMFT->GetOutputCurrentType(0, &pMTOut); m_bInterlaced = MFGetAttributeUINT32(pMTOut, MF_MT_INTERLACE_MODE, MFVideoInterlace_Unknown) > MFVideoInterlace_Progressive; SafeRelease(&pMTOut); m_bManualReorder = (codec == AV_CODEC_ID_VC1) && !(m_pCallback->GetDecodeFlags() & LAV_VIDEO_DEC_FLAG_ONLY_DTS); return S_OK; }