WMFUtils.cpp (6788B)
1 /* 2 * Copyright 2013, Mozilla Foundation and contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "WMFUtils.h" 18 19 #define INITGUID 20 #include <guiddef.h> 21 #include <stdio.h> 22 #include <versionhelpers.h> 23 24 #include <algorithm> 25 26 #include "ClearKeyUtils.h" 27 28 #ifndef __MINGW32__ 29 # pragma comment(lib, "mfuuid.lib") 30 # pragma comment(lib, "wmcodecdspuuid") 31 #endif 32 33 void LOG(const char* format, ...) { 34 #ifdef WMF_DECODER_LOG 35 va_list args; 36 va_start(args, format); 37 vprintf(format, args); 38 #endif 39 } 40 41 DEFINE_GUID(CLSID_CMSH264DecMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45, 42 0x28, 0x31, 0xA8, 0x7D, 0x9D); 43 44 namespace wmf { 45 46 #define MFPLAT_FUNC(_func, _dllname) decltype(::_func)* _func; 47 #include "WMFSymbols.h" 48 #undef MFPLAT_FUNC 49 50 static bool LinkMfplat() { 51 static bool sInitDone = false; 52 static bool sInitOk = false; 53 if (!sInitDone) { 54 sInitDone = true; 55 HMODULE handle; 56 57 #define MFPLAT_FUNC(_func, _dllname) \ 58 handle = GetModuleHandleA(_dllname); \ 59 if (!(_func = (decltype(_func))(GetProcAddress(handle, #_func)))) { \ 60 return false; \ 61 } 62 63 #include "WMFSymbols.h" 64 #undef MFPLAT_FUNC 65 sInitOk = true; 66 } 67 return sInitOk; 68 } 69 70 bool EnsureLibs() { 71 static bool sInitDone = false; 72 static bool sInitOk = false; 73 if (!sInitDone) { 74 sInitOk = LinkMfplat() && !!GetModuleHandleA(WMFDecoderDllName()); 75 sInitDone = true; 76 } 77 return sInitOk; 78 } 79 80 int32_t MFOffsetToInt32(const MFOffset& aOffset) { 81 return int32_t(aOffset.value + (aOffset.fract / 65536.0f)); 82 } 83 84 // Gets the sub-region of the video frame that should be displayed. 85 // See: 86 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx 87 HRESULT 88 GetPictureRegion(IMFMediaType* aMediaType, IntRect& aOutPictureRegion) { 89 // Determine if "pan and scan" is enabled for this media. If it is, we 90 // only display a region of the video frame, not the entire frame. 91 BOOL panScan = 92 MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE); 93 94 // If pan and scan mode is enabled. Try to get the display region. 95 HRESULT hr = E_FAIL; 96 MFVideoArea videoArea; 97 memset(&videoArea, 0, sizeof(MFVideoArea)); 98 if (panScan) { 99 hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE, (UINT8*)&videoArea, 100 sizeof(MFVideoArea), NULL); 101 } 102 103 // If we're not in pan-and-scan mode, or the pan-and-scan region is not set, 104 // check for a minimimum display aperture. 105 if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) { 106 hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8*)&videoArea, 107 sizeof(MFVideoArea), NULL); 108 } 109 110 if (hr == MF_E_ATTRIBUTENOTFOUND) { 111 // Minimum display aperture is not set, for "backward compatibility with 112 // some components", check for a geometric aperture. 113 hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, (UINT8*)&videoArea, 114 sizeof(MFVideoArea), NULL); 115 } 116 117 if (SUCCEEDED(hr)) { 118 // The media specified a picture region, return it. 119 IntRect picture = IntRect(MFOffsetToInt32(videoArea.OffsetX), 120 MFOffsetToInt32(videoArea.OffsetY), 121 videoArea.Area.cx, videoArea.Area.cy); 122 ENSURE(picture.width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); 123 ENSURE(picture.height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); 124 aOutPictureRegion = picture; 125 return S_OK; 126 } 127 128 // No picture region defined, fall back to using the entire video area. 129 UINT32 width = 0, height = 0; 130 hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); 131 ENSURE(SUCCEEDED(hr), hr); 132 ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); 133 ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); 134 aOutPictureRegion = IntRect(0, 0, width, height); 135 return S_OK; 136 } 137 138 HRESULT 139 GetDefaultStride(IMFMediaType* aType, uint32_t* aOutStride) { 140 // Try to get the default stride from the media type. 141 UINT32 stride = 0; 142 HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride); 143 if (SUCCEEDED(hr)) { 144 ENSURE(stride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); 145 *aOutStride = stride; 146 return S_OK; 147 } 148 149 // Stride attribute not set, calculate it. 150 GUID subtype = GUID_NULL; 151 uint32_t width = 0; 152 uint32_t height = 0; 153 154 hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); 155 ENSURE(SUCCEEDED(hr), hr); 156 157 hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); 158 ENSURE(SUCCEEDED(hr), hr); 159 ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); 160 ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); 161 162 LONG lstride = 0; 163 hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lstride); 164 ENSURE(SUCCEEDED(hr), hr); 165 ENSURE(lstride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); 166 ENSURE(lstride >= 0, E_FAIL); 167 *aOutStride = lstride; 168 169 return hr; 170 } 171 172 void dump(const uint8_t* data, uint32_t len, const char* filename) { 173 FILE* f = 0; 174 fopen_s(&f, filename, "wb"); 175 fwrite(data, len, 1, f); 176 fclose(f); 177 } 178 179 HRESULT 180 CreateMFT(const CLSID& clsid, const char* aDllName, 181 CComPtr<IMFTransform>& aOutMFT) { 182 HMODULE module = ::GetModuleHandleA(aDllName); 183 if (!module) { 184 LOG("Failed to get %S\n", aDllName); 185 return E_FAIL; 186 } 187 188 typedef HRESULT(WINAPI * DllGetClassObjectFnPtr)( 189 const CLSID& clsid, const IID& iid, void** object); 190 191 DllGetClassObjectFnPtr GetClassObjPtr = 192 reinterpret_cast<DllGetClassObjectFnPtr>( 193 GetProcAddress(module, "DllGetClassObject")); 194 if (!GetClassObjPtr) { 195 LOG("Failed to get DllGetClassObject\n"); 196 return E_FAIL; 197 } 198 199 CComPtr<IClassFactory> classFactory; 200 HRESULT hr = GetClassObjPtr( 201 clsid, __uuidof(IClassFactory), 202 reinterpret_cast<void**>(static_cast<IClassFactory**>(&classFactory))); 203 if (FAILED(hr)) { 204 LOG("Failed to get H264 IClassFactory\n"); 205 return E_FAIL; 206 } 207 208 hr = classFactory->CreateInstance( 209 NULL, __uuidof(IMFTransform), 210 reinterpret_cast<void**>(static_cast<IMFTransform**>(&aOutMFT))); 211 if (FAILED(hr)) { 212 LOG("Failed to get create MFT\n"); 213 return E_FAIL; 214 } 215 216 return S_OK; 217 } 218 219 int32_t GetNumThreads(int32_t aCoreCount) { 220 return aCoreCount > 4 ? -1 : (std::max)(aCoreCount - 1, 1); 221 } 222 223 } // namespace wmf