diff options
author | clsid2 <clsid2@users.sourceforge.net> | 2010-05-07 16:31:53 +0400 |
---|---|---|
committer | clsid2 <clsid2@users.sourceforge.net> | 2010-05-07 16:31:53 +0400 |
commit | 543aae0bc0a5009e9a3ef01d31344b5f61c3f604 (patch) | |
tree | e49784e02c6ba52177f3949675bb10317da73ac2 | |
parent | e183f8b57e1626f2dfbb564a5f5a0c09be9eeb3e (diff) |
Improved DXVA compatibility check
git-svn-id: https://mpc-hc.svn.sourceforge.net/svnroot/mpc-hc/trunk@1857 10f7b99b-c216-0410-bff0-8a66a9350fd8
5 files changed, 103 insertions, 95 deletions
diff --git a/src/filters/transform/MPCVideoDec/FfmpegContext.c b/src/filters/transform/MPCVideoDec/FfmpegContext.c index 812d6a923..a21b0cd85 100644 --- a/src/filters/transform/MPCVideoDec/FfmpegContext.c +++ b/src/filters/transform/MPCVideoDec/FfmpegContext.c @@ -124,6 +124,36 @@ void FFH264DecodeBuffer (struct AVCodecContext* pAVCtx, BYTE* pBuffer, UINT nSiz }
}
+// returns 1 if version is equal to or higher than A.B.C.D, returns 0 otherwise
+int DriverVersionCheck(LARGE_INTEGER VideoDriverVersion, int A, int B, int C, int D)
+{
+ if (HIWORD(VideoDriverVersion.HighPart) > A)
+ {
+ return 1;
+ }
+ else if (HIWORD(VideoDriverVersion.HighPart) == A)
+ {
+ if (LOWORD(VideoDriverVersion.HighPart) > B)
+ {
+ return 1;
+ }
+ else if (LOWORD(VideoDriverVersion.HighPart) == B)
+ {
+ if (HIWORD(VideoDriverVersion.LowPart) > C)
+ {
+ return 1;
+ }
+ else if (HIWORD(VideoDriverVersion.LowPart) == C)
+ {
+ if (LOWORD(VideoDriverVersion.LowPart) >= D)
+ {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
int FFH264CheckCompatibility(int nWidth, int nHeight, struct AVCodecContext* pAVCtx, BYTE* pBuffer, UINT nSize, int nPCIVendor, LARGE_INTEGER VideoDriverVersion)
{
@@ -131,130 +161,95 @@ int FFH264CheckCompatibility(int nWidth, int nHeight, struct AVCodecContext* pAV SPS* cur_sps;
PPS* cur_pps;
- int supportLevel51 = 0;
+ int video_is_level51 = 0;
+ int no_level51_support = 1;
+ int too_much_ref_frames = 0;
if (pBuffer != NULL)
+ {
av_h264_decode_frame (pAVCtx, NULL, NULL, pBuffer, nSize);
+ }
cur_sps = pContext->sps_buffers[0];
cur_pps = pContext->pps_buffers[0];
-
+
if (cur_sps != NULL)
{
+ video_is_level51 = cur_sps->level_idc >= 51 ? 1 : 0;
if (nPCIVendor == PCIV_nVidia)
{
// nVidia cards support level 5.1 since drivers v6.14.11.7800 for XP and drivers v7.15.11.7800 for Vista
- // vA.B.C.D
- int A, B, C, D;
if (IsVista())
{
- A = 7; B = 15; C = 11; D = 7800;
+ no_level51_support = !DriverVersionCheck(VideoDriverVersion, 7, 15, 11, 7800);
}
else
{
- A = 6; B = 14; C = 11; D = 7800;
- }
-
- if (HIWORD(VideoDriverVersion.HighPart) > A)
- {
- supportLevel51 = 1;
- }
- else if (HIWORD(VideoDriverVersion.HighPart) == A)
- {
- if (LOWORD(VideoDriverVersion.HighPart) > B)
- {
- supportLevel51 = 1;
- }
- else if (LOWORD(VideoDriverVersion.HighPart) == B)
- {
- if (HIWORD(VideoDriverVersion.LowPart) > C)
- {
- supportLevel51 = 1;
- }
- else if (HIWORD(VideoDriverVersion.LowPart) == C)
- {
- if (LOWORD(VideoDriverVersion.LowPart) >= D)
- {
- supportLevel51 = 1;
- }
- }
- }
+ no_level51_support = !DriverVersionCheck(VideoDriverVersion, 6, 14, 11, 7800);
}
}
else if (nPCIVendor == PCIV_S3_Graphics)
- supportLevel51 = 1;
-
+ {
+ no_level51_support = 0;
+ }
else if (nPCIVendor == PCIV_ATI)
{
+#if 0
// ATI cards support level 5.1 since drivers v8.14.1.6105 (Catalyst 10.4)
- // vA.B.C.D
- int A, B, C, D;
-
- A = 8; B = 14; C = 1; D = 6105;
-
- if (HIWORD(VideoDriverVersion.HighPart) > A)
- {
- supportLevel51 = 1;
- }
- else if (HIWORD(VideoDriverVersion.HighPart) == A)
- {
- if (LOWORD(VideoDriverVersion.HighPart) > B)
- {
- supportLevel51 = 1;
- }
- else if (LOWORD(VideoDriverVersion.HighPart) == B)
- {
- if (HIWORD(VideoDriverVersion.LowPart) > C)
- {
- supportLevel51 = 1;
- }
- else if (HIWORD(VideoDriverVersion.LowPart) == C)
- {
- if (LOWORD(VideoDriverVersion.LowPart) >= D)
- {
- supportLevel51 = 1;
- }
- }
- }
- }
+ no_level51_support = !DriverVersionCheck(VideoDriverVersion, 8, 14, 1, 6105);
+#else
+ // An UVD version check is needed to determine whether L5.1 is really supported by the graphics card
+ // UVD+ or UVD2 seems to be required?
+ // So for now disable level 5.1 for ATI by default. This can be overridden through the compatibility check options.
+ no_level51_support = 1;
+#endif
}
- // Check max num reference frame according to the level
#define MAX_DPB_41 12288 // DPB value for level 4.1
- if (supportLevel51 == 1)
+ // Check maximum allowed number reference frames
+ if(nPCIVendor == PCIV_nVidia && !no_level51_support)
{
- // 11 refs as absolute max, but for Nvidia(Vista, HD) - 16
- if(PCIV_nVidia)
+ // L5.1 is supported
+ if(IsVista())
{
- if(IsVista())
+ // max is 16 for HD and 11 otherwise
+ if(nWidth >= 1280)
{
- if(nWidth>1279)
+ if (cur_sps->ref_frame_count > 16)
{
- if (cur_sps->ref_frame_count > 16)
- return 2; // Too much ref frames
+ too_much_ref_frames = 1;
}
- else
+ }
+ else
+ {
+ if (cur_sps->ref_frame_count > 11)
{
- if (cur_sps->ref_frame_count > 11)
- return 2; // Too much ref frames
+ too_much_ref_frames = 1;
}
- } else {
- if (cur_sps->ref_frame_count > 14)
- return 2; // Too much ref frames
+ }
+ }
+ else
+ {
+ // max is 14
+ if (cur_sps->ref_frame_count > 14)
+ {
+ too_much_ref_frames = 1;
}
}
}
else
{
- // level 4.1 with 11 refs as absolute max
+ // maximum of 11 or less, depending on DPB check
if (cur_sps->ref_frame_count > min(11, (1024*MAX_DPB_41/(nWidth*nHeight*1.5))))
- return 2; // Too much ref frames
+ {
+ too_much_ref_frames = 1;
+ }
}
}
-
- return 0;
+
+ return (video_is_level51 * no_level51_support * DXVA_UNSUPPORTED_LEVEL) + (too_much_ref_frames * DXVA_TOO_MUCH_REF_FRAMES);
}
diff --git a/src/filters/transform/MPCVideoDec/FfmpegContext.h b/src/filters/transform/MPCVideoDec/FfmpegContext.h index 101ef4336..42c206f62 100644 --- a/src/filters/transform/MPCVideoDec/FfmpegContext.h +++ b/src/filters/transform/MPCVideoDec/FfmpegContext.h @@ -35,6 +35,11 @@ enum PCI_Vendors PCIV_S3_Graphics = 0x5333
};
+// Bitmasks for DXVA compatibility check
+#define DXVA_UNSUPPORTED_LEVEL 1
+#define DXVA_TOO_MUCH_REF_FRAMES 2
+#define DXVA_INCOMPATIBLE_SAR 4
+
// === H264 functions
void FFH264DecodeBuffer (struct AVCodecContext* pAVCtx, BYTE* pBuffer, UINT nSize, int* pFramePOC, int* pOutPOC, REFERENCE_TIME* pOutrtStart);
HRESULT FFH264BuildPicParams (DXVA_PicParams_H264* pDXVAPicParams, DXVA_Qmatrix_H264* pDXVAScalingMatrix, int* nFieldType, int* nSliceType, struct AVCodecContext* pAVCtx, int nPCIVendor);
diff --git a/src/filters/transform/MPCVideoDec/MPCVideoDecFilter.cpp b/src/filters/transform/MPCVideoDec/MPCVideoDecFilter.cpp index db188d44e..93e402bbf 100644 --- a/src/filters/transform/MPCVideoDec/MPCVideoDecFilter.cpp +++ b/src/filters/transform/MPCVideoDec/MPCVideoDecFilter.cpp @@ -1116,21 +1116,28 @@ HRESULT CMPCVideoDecFilter::SetMediaType(PIN_DIRECTION direction,const CMediaTyp }
else
{
- int nCompat;
- nCompat = FFH264CheckCompatibility (PictWidthRounded(), PictHeightRounded(), m_pAVCtx, (BYTE*)m_pAVCtx->extradata, m_pAVCtx->extradata_size, m_nPCIVendor, m_VideoDriverVersion);
+ // non-zero value indicates that an incompatibility was detected
+ int nCompat = FFH264CheckCompatibility (PictWidthRounded(), PictHeightRounded(), m_pAVCtx, (BYTE*)m_pAVCtx->extradata, m_pAVCtx->extradata_size, m_nPCIVendor, m_VideoDriverVersion);
- if(nCompat>0)
+ if(nCompat > 0)
{
switch(m_nDXVACheckCompatibility)
{
case 0 :
+ // full check
m_bDXVACompatible = false;
break;
case 1 :
- if(nCompat == 2) m_bDXVACompatible = false;
+ // skip level check
+ if(nCompat != DXVA_UNSUPPORTED_LEVEL) m_bDXVACompatible = false;
break;
case 2 :
- if(nCompat == 1) m_bDXVACompatible = false;
+ // skip reference frame check
+ if(nCompat != DXVA_TOO_MUCH_REF_FRAMES) m_bDXVACompatible = false;
+ break;
+ case 3 :
+ // skip all checks
+ //if(nCompat != (DXVA_UNSUPPORTED_LEVEL | DXVA_TOO_MUCH_REF_FRAMES)) m_bDXVACompatible = false; // example of how a combination of two ignored checks can be done
break;
}
}
diff --git a/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.cpp b/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.cpp index 35cbddebd..ac01bf18e 100644 --- a/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.cpp +++ b/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.cpp @@ -88,7 +88,7 @@ bool CMPCVideoDecSettingsWnd::OnActivate() GUID* DxvaGui = NULL;
#if INCLUDE_MPC_VIDEO_DECODER
- m_grpFFMpeg.Create (ResStr (IDS_VDF_FFSETTINGS), WS_VISIBLE|WS_CHILD | BS_GROUPBOX, CRect (10, nPosY, 330, nPosY+150), this, IDC_STATIC);
+ m_grpFFMpeg.Create (ResStr (IDS_VDF_FFSETTINGS), WS_VISIBLE|WS_CHILD | BS_GROUPBOX, CRect (10, nPosY, 350, nPosY+150), this, IDC_STATIC);
#if INTERNAL_DECODER_H264
@@ -148,16 +148,17 @@ bool CMPCVideoDecSettingsWnd::OnActivate() nPosY = 170;
#endif /* INCLUDE_MPC_VIDEO_DECODER */
- m_grpDXVA.Create (ResStr (IDS_VDF_DXVA_SETTING), WS_VISIBLE|WS_CHILD | BS_GROUPBOX, CRect (10, nPosY, 330, nPosY+135), this, IDC_STATIC);
+ m_grpDXVA.Create (ResStr (IDS_VDF_DXVA_SETTING), WS_VISIBLE|WS_CHILD | BS_GROUPBOX, CRect (10, nPosY, 350, nPosY+135), this, IDC_STATIC);
// DXVA Compatibility check
nPosY += VERTICAL_SPACING;
m_txtDXVACompatibilityCheck.Create (ResStr (IDS_VDF_DXVACOMPATIBILITY), WS_VISIBLE|WS_CHILD, CRect (LEFT_SPACING, nPosY, 190, nPosY+15), this, IDC_STATIC);
m_cbDXVACompatibilityCheck.Create (WS_VISIBLE|WS_CHILD|CBS_DROPDOWNLIST|WS_VSCROLL, CRect (200, nPosY-4, 315, nPosY+90), this, IDC_PP_DXVA_CHECK);
m_cbDXVACompatibilityCheck.AddString(ResStr (IDS_VDF_DXVA_FULLCHECK));
- m_cbDXVACompatibilityCheck.AddString(ResStr (IDS_VDF_DXVA_REFONLY));
- m_cbDXVACompatibilityCheck.AddString(ResStr (IDS_VDF_DXVA_SARONLY));
- m_cbDXVACompatibilityCheck.AddString(ResStr (IDS_VDF_DXVA_NOCHECK));
+ // ToDo: add strings to resource (and cleanup old ones)
+ m_cbDXVACompatibilityCheck.AddString(_T("Skip level check"));
+ m_cbDXVACompatibilityCheck.AddString(_T("Skip ref frame check"));
+ m_cbDXVACompatibilityCheck.AddString(_T("Skip all checks"));
nPosY += VERTICAL_SPACING;
m_cbDXVA_SD.Create (ResStr (IDS_VDF_DXVA_SD), WS_VISIBLE|WS_CHILD|BS_AUTOCHECKBOX|BS_LEFTTEXT, CRect (LEFT_SPACING, nPosY, 315, nPosY+15), this, IDC_PP_DXVA_SD);
@@ -218,7 +219,7 @@ bool CMPCVideoDecSettingsWnd::OnApply() {
OnDeactivate();
- if(m_pMDF && m_cbErrorRecognition.m_hWnd)
+ if(m_pMDF && m_cbDXVACompatibilityCheck.m_hWnd)
{
#if INCLUDE_MPC_VIDEO_DECODER
#if INTERNAL_DECODER_H264
diff --git a/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.h b/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.h index 5cac8534b..cdff3ed2b 100644 --- a/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.h +++ b/src/filters/transform/MPCVideoDec/MPCVideoDecSettingsWnd.h @@ -75,7 +75,7 @@ public: bool OnApply();
static LPCTSTR GetWindowTitle() {return _T("Settings");}
- static CSize GetWindowSize() {return CSize(320, 325);}
+ static CSize GetWindowSize() {return CSize(350, 325);}
DECLARE_MESSAGE_MAP()
};
@@ -104,7 +104,7 @@ public: bool OnApply();
static LPCTSTR GetWindowTitle() {return _T("Codecs");}
- static CSize GetWindowSize() {return CSize(320, 300);}
+ static CSize GetWindowSize() {return CSize(350, 300);}
DECLARE_MESSAGE_MAP()
};
|