void TvideoCodecLibavcodecDxva::getDXVAOutputFormats(TcspInfos &ocsps) { int nVideoOutputCount = 0; for (nVideoOutputCount = 0; nVideoOutputCount < MAX_SUPPORTED_MODE; nVideoOutputCount++) if (dxvaParamsp->Decoder[nVideoOutputCount] == &GUID_NULL) { break; } ocsps.clear(); TcspInfo csp = { FF_CSP_NV12, _l("avxd"), 1, 12, //Bpp 1, //numplanes {0, 0, 0, 0}, //shiftX {0, 1, 1, 0}, //shiftY {0, 128, 128, 0}, //black 'avxd', 'avxd', &GUID_NULL }; // Dynamic DXVA media types for DXVA1 for (int nPos = 0; nPos < nVideoOutputCount; nPos++) { TcspInfo *pCsp = new TcspInfo(csp); pCsp->subtype = dxvaParamsp->Decoder[nPos]; ocsps.push_back(pCsp); } // Static list for DXVA2 nVideoOutputCount = SIZEOF_ARRAY(dxva2List); for (int nPos = 0; nPos < nVideoOutputCount; nPos++) { ocsps.push_back((TcspInfo *)&dxva2List[nPos]); } }
HRESULT TffdshowDecVideoDXVA::setOutputMediaType(const CMediaType &mt) { DPRINTF(_l("TffdshowDecVideoDXVA::setOutputMediaType")); TvideoCodecDec *pDecoder=NULL; getMovieSource((const TvideoCodecDec**)&pDecoder); TcspInfos ocsps; // DXVA mode : special output format TvideoCodecLibavcodecDxva *pDecoderDxva = (TvideoCodecLibavcodecDxva*)pDecoder; pDecoderDxva->getDXVAOutputFormats(ocsps); for (int i=0; cspFccs[i].name; i++) { const TcspInfo *cspInfo; // Look for the right DXVA colorspace bool ok=false; for (TcspInfos::const_iterator oc=ocsps.begin(); oc!=ocsps.end(); oc++) { if (mt.subtype==*(*oc)->subtype) { cspInfo=(const TcspInfo *)(*oc); ok=true; break; } } if (!ok) { continue; } m_frame.dstColorspace=FF_CSP_NV12; int biWidth,outDy; BITMAPINFOHEADER *bih; if (mt.formattype==FORMAT_VideoInfo && mt.pbFormat) { // && mt.pbFormat = work around other filter's bug. VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)mt.pbFormat; m_frame.dstStride=calcBIstride(biWidth=vih->bmiHeader.biWidth,cspInfo->Bpp*8); outDy=vih->bmiHeader.biHeight; bih=&vih->bmiHeader; } else if (mt.formattype==FORMAT_VideoInfo2 && mt.pbFormat) { VIDEOINFOHEADER2 *vih2=(VIDEOINFOHEADER2*)mt.pbFormat; m_frame.dstStride=calcBIstride(biWidth=vih2->bmiHeader.biWidth,cspInfo->Bpp*8); outDy=vih2->bmiHeader.biHeight; bih=&vih2->bmiHeader; } else { return VFW_E_TYPE_NOT_ACCEPTED; //S_FALSE; } m_frame.dstSize=DIBSIZE(*bih); char_t s[256]; DPRINTF(_l("TffdshowDecVideoDXVA::setOutputMediaType: colorspace:%s, biWidth:%i, dstStride:%i, Bpp:%i, dstSize:%i"),csp_getName(m_frame.dstColorspace,s,256),biWidth,m_frame.dstStride,cspInfo->Bpp,m_frame.dstSize); if (csp_isRGB(m_frame.dstColorspace) && outDy>0) { m_frame.dstColorspace|=FF_CSP_FLAGS_VFLIP; } //else if (biheight<0) // m_frame.colorspace|=FF_CSP_FLAGS_VFLIP; return S_OK; } m_frame.dstColorspace=FF_CSP_NULL; DPRINTF(_l("TffdshowDecVideoDXVA::setOutputMediaType Type not supported by FFDShow DXVA")); return VFW_E_TYPE_NOT_ACCEPTED; //S_FALSE; }
uint64_t getBMPcolorspace(const BITMAPINFOHEADER *hdr, const TcspInfos &forcedCsps) { uint64_t csp; switch (hdr->biCompression) { case BI_RGB: switch (hdr->biBitCount) { case 15: csp = FF_CSP_RGB15 | FF_CSP_FLAGS_VFLIP; break; case 16: csp = FF_CSP_RGB16 | FF_CSP_FLAGS_VFLIP; break; case 24: csp = FF_CSP_RGB24 | FF_CSP_FLAGS_VFLIP; break; case 32: csp = FF_CSP_RGB32 | FF_CSP_FLAGS_VFLIP; break; default: return FF_CSP_NULL; } break; case FOURCC_I420: case FOURCC_IYUV: csp = FF_CSP_420P | FF_CSP_FLAGS_YUV_ADJ | FF_CSP_FLAGS_YUV_ORDER; break; case FOURCC_YV12: csp = FF_CSP_420P | FF_CSP_FLAGS_YUV_ADJ; break; case FOURCC_YUYV: case FOURCC_YUY2: case FOURCC_V422: csp = FF_CSP_YUY2; break; case FOURCC_YVYU: csp = FF_CSP_YVYU; break; case FOURCC_UYVY: csp = FF_CSP_UYVY; break; case FOURCC_VYUY: csp = FF_CSP_VYUY; break; case FOURCC_Y800: csp = FF_CSP_Y800; break; case FOURCC_444P: case FOURCC_YV24: csp = FF_CSP_444P; break; case FOURCC_422P: csp = FF_CSP_422P; break; case FOURCC_YV16: csp = FF_CSP_422P | FF_CSP_FLAGS_YUV_ADJ; break; case FOURCC_411P: case FOURCC_Y41B: csp = FF_CSP_411P; break; case FOURCC_410P: csp = FF_CSP_410P; break; case FOURCC_420R: csp = FF_CSP_420P10; break; case FOURCC_422R: csp = FF_CSP_422P10; break; case FOURCC_444R: csp = FF_CSP_444P10; break; case FOURCC_P016: csp = FF_CSP_P016; break; case FOURCC_P010: csp = FF_CSP_P010; break; case FOURCC_P210: csp = FF_CSP_P210; break; case FOURCC_P216: csp = FF_CSP_P216; break; case FOURCC_AYUV: csp = FF_CSP_AYUV; break; case FOURCC_Y416: csp = FF_CSP_Y416; break; default: return FF_CSP_NULL; } bool ok; if (!forcedCsps.empty()) { ok = std::find(forcedCsps.begin(), forcedCsps.end(), csp_getInfo(csp)) != forcedCsps.end(); } else { ok = true; } return ok ? csp : FF_CSP_NULL; }
// get list of supported output colorspaces HRESULT TffdshowDecVideoDXVA::GetMediaType(int iPosition, CMediaType *mtOut) { DPRINTF(_l("TffdshowDecVideoDXVA::GetMediaType")); CAutoLock lock(&inpin->m_csCodecs_and_imgFilters); if (m_pInput->IsConnected()==FALSE) { return E_UNEXPECTED; } if (!presetSettings) { initPreset(); } bool isVIH2; if (m_pOutput->IsConnected()) { const CLSID &ref=GetCLSID(m_pOutput->GetConnected()); if (ref==CLSID_VideoMixingRenderer || ref==CLSID_VideoMixingRenderer9) { isVIH2=true; } } isVIH2 = (iPosition&1)==0; iPosition/=2; if (iPosition<0) { return E_INVALIDARG; } TvideoCodecDec *pDecoder=NULL; getMovieSource((const TvideoCodecDec**)&pDecoder); if (!pDecoder->useDXVA()) { return VFW_S_NO_MORE_ITEMS; } TcspInfos ocsps; size_t osize; // DXVA mode : special output format TvideoCodecLibavcodecDxva *pDecoderDxva = (TvideoCodecLibavcodecDxva*)pDecoder; pDecoderDxva->getDXVAOutputFormats(ocsps); osize=ocsps.size(); if ((size_t)iPosition>=osize) { return VFW_S_NO_MORE_ITEMS; } TffPictBase pictOut; if (inReconnect) { pictOut=reconnectRect; } else { pictOut=inpin->pictIn; } // Support mediatype with unknown dimension. This is necessary to support MEDIASUBTYPE_H264. // http://msdn.microsoft.com/en-us/library/dd757808(VS.85).aspx // The downstream filter has to support reconnecting after this. if (pictOut.rectFull.dx == 0) { pictOut.rectFull.dx = 320; } if (pictOut.rectFull.dy == 0) { pictOut.rectFull.dy = 160; } oldRect=pictOut.rectFull; const TcspInfo *c=ocsps[iPosition]; BITMAPINFOHEADER bih; memset(&bih,0,sizeof(bih)); bih.biSize =sizeof(BITMAPINFOHEADER); bih.biWidth =pDecoderDxva->pictWidthRounded(); if(c->id == FF_CSP_420P) { // YV12 and odd number lines. pictOut.rectFull.dy=odd2even(pictOut.rectFull.dy); } bih.biHeight=pDecoderDxva->pictHeightRounded(); bih.biPlanes=WORD(c->numPlanes); bih.biCompression=c->fcc; bih.biBitCount=WORD(c->bpp); bih.biSizeImage=DIBSIZE(bih);// bih.biWidth*bih.biHeight*bih.biBitCount>>3; mtOut->majortype=MEDIATYPE_Video; mtOut->subtype=*c->subtype; mtOut->formattype=isVIH2?FORMAT_VideoInfo2:FORMAT_VideoInfo; mtOut->SetTemporalCompression(FALSE); mtOut->SetSampleSize(bih.biSizeImage); if (!isVIH2) { VIDEOINFOHEADER *vih=(VIDEOINFOHEADER*)mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER)); if (!vih) { return E_OUTOFMEMORY; } ZeroMemory(vih,sizeof(VIDEOINFOHEADER)); vih->rcSource.left=0; vih->rcSource.right=pictOut.rectFull.dx; vih->rcSource.top=0; vih->rcSource.bottom=pictOut.rectFull.dy; vih->rcTarget=vih->rcSource; vih->AvgTimePerFrame=inpin->avgTimePerFrame; vih->bmiHeader=bih; } else { VIDEOINFOHEADER2 *vih2=(VIDEOINFOHEADER2*)mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER2)); if (!vih2) { return E_OUTOFMEMORY; } ZeroMemory(vih2,sizeof(VIDEOINFOHEADER2)); if((presetSettings->resize && presetSettings->resize->is && presetSettings->resize->SARinternally && presetSettings->resize->mode==0)) { pictOut.rectFull.sar.num= 1;//pictOut.rectFull.dx; // VMR9 behaves better when this is set to 1(SAR). But in reconnectOutput, it is different(DAR) in my system. pictOut.rectFull.sar.den= 1;//pictOut.rectFull.dy; } setVIH2aspect(vih2,pictOut.rectFull,presetSettings->output->hwOverlayAspect); //DPRINTF(_l("AR getMediaType: %i:%i"),vih2->dwPictAspectRatioX,vih2->dwPictAspectRatioY); vih2->rcSource.left=0; vih2->rcSource.right=pictOut.rectFull.dx; vih2->rcSource.top=0; vih2->rcSource.bottom=pictOut.rectFull.dy; vih2->rcTarget=vih2->rcSource; vih2->AvgTimePerFrame=inpin->avgTimePerFrame; vih2->bmiHeader=bih; //vih2->dwControlFlags=AMCONTROL_USED | AMCONTROL_COLORINFO_PRESENT | (DXVA_NominalRange_Wide << DXVA_NominalRangeShift) | (DXVA_VideoTransferMatrix_BT601 << DXVA_VideoTransferMatrixShift); hwDeinterlace=1; // HW deinterlace for DXVA if (hwDeinterlace) { vih2->dwInterlaceFlags=AMINTERLACE_IsInterlaced|AMINTERLACE_DisplayModeBobOrWeave; } } return S_OK; }