mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-23 00:47:31 +09:00
Add VP9 Hardware Decoding with DXVA (Non-MFT), Vista+
Thanks to Maggie (imjustsomeoneiguess) on discord for helping with a lot of this VP9 media code. This is the first browser so far to support VP9 Non MFT
This commit is contained in:
parent
e0fe6706d1
commit
1414824320
18 changed files with 1747 additions and 34 deletions
590
dom/media/platforms/wmf/DXVAVP9Manager.cpp
Normal file
590
dom/media/platforms/wmf/DXVAVP9Manager.cpp
Normal file
|
|
@ -0,0 +1,590 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DXVAVP9Manager.h"
|
||||
#include "WMFUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
|
||||
// VP9 DXVA2 GUID: {463707F8-A1D0-4585-876D-83AA6D60B89E}
|
||||
// its the VP9_VLD_Profile0.
|
||||
static const GUID sVP9DecoderGUID = {
|
||||
0x463707f8, 0xa1d0, 0x4585,
|
||||
{ 0x87, 0x6d, 0x83, 0xaa, 0x6d, 0x60, 0xb8, 0x9e }
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
DXVAVP9Manager::DXVAVP9Manager()
|
||||
: mNumSurfaces(kDefaultSurfaces)
|
||||
, mCurrentSurface(kDefaultSurfaces - 1)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mFrameCount(0)
|
||||
, mLock("DXVAVP9Manager")
|
||||
{
|
||||
memset(mRefFrameSurface, 0xFF, sizeof(mRefFrameSurface));
|
||||
memset(mRefFrameWidth, 0, sizeof(mRefFrameWidth));
|
||||
memset(mRefFrameHeight, 0, sizeof(mRefFrameHeight));
|
||||
}
|
||||
|
||||
DXVAVP9Manager::~DXVAVP9Manager()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
/* static */ const GUID&
|
||||
DXVAVP9Manager::GetVP9DecoderGUID()
|
||||
{
|
||||
return sVP9DecoderGUID;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DXVAVP9Manager::SupportsVP9(IDirect3DDeviceManager9* aDeviceManager)
|
||||
{
|
||||
if (!aDeviceManager) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE handle = nullptr;
|
||||
HRESULT hr = aDeviceManager->OpenDeviceHandle(&handle);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDirectXVideoDecoderService> decoderService;
|
||||
hr = aDeviceManager->GetVideoService(
|
||||
handle, IID_PPV_ARGS(decoderService.StartAssignment()));
|
||||
aDeviceManager->CloseDeviceHandle(handle);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT count = 0;
|
||||
GUID* guids = nullptr;
|
||||
hr = decoderService->GetDecoderDeviceGuids(&count, &guids);
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (UINT i = 0; i < count; i++) {
|
||||
if (guids[i] == sVP9DecoderGUID) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CoTaskMemFree(guids);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool
|
||||
DXVAVP9Manager::Init(IUnknown* aDeviceManager, uint32_t aWidth,
|
||||
uint32_t aHeight, nsACString& aFailureReason)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
if (!aDeviceManager) { aFailureReason.AssignLiteral("Missing D3D9 device manager"); return false; }
|
||||
|
||||
HRESULT hr = aDeviceManager->QueryInterface(
|
||||
__uuidof(IDirect3DDeviceManager9),
|
||||
reinterpret_cast<void**>(mDeviceManager.StartAssignment()));
|
||||
if (FAILED(hr)) {
|
||||
aFailureReason.AssignLiteral(
|
||||
"DXVAVP9: QueryInterface to IDirect3DDeviceManager9 failed — "
|
||||
"D3D11 path is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE handle = nullptr;
|
||||
hr = mDeviceManager->OpenDeviceHandle(&handle);
|
||||
if (FAILED(hr)) {
|
||||
aFailureReason = nsPrintfCString(
|
||||
"DXVAVP9: OpenDeviceHandle failed %X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = mDeviceManager->GetVideoService(
|
||||
handle, IID_PPV_ARGS(mDecoderService.StartAssignment()));
|
||||
mDeviceManager->CloseDeviceHandle(handle);
|
||||
if (FAILED(hr)) {
|
||||
aFailureReason = nsPrintfCString(
|
||||
"DXVAVP9: GetVideoService failed %X", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SupportsVP9(mDeviceManager)) {
|
||||
aFailureReason.AssignLiteral(
|
||||
"DXVAVP9: VP9 DXVA2 GUID not exposed by driver — "
|
||||
"GPU/driver does not support hardware VP9 decode");
|
||||
return false;
|
||||
}
|
||||
|
||||
mWidth = aWidth ? aWidth : 1280;
|
||||
mHeight = aHeight ? aHeight : 720;
|
||||
|
||||
hr = InitDecoder(mWidth, mHeight);
|
||||
if (FAILED(hr)) {
|
||||
aFailureReason = nsPrintfCString(
|
||||
"DXVAVP9: InitDecoder(%ux%u) failed %X", mWidth, mHeight, hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DXVAVP9Manager::Flush()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mParser.Reset();
|
||||
memset(mRefFrameSurface, 0xff, sizeof(mRefFrameSurface));
|
||||
memset(mRefFrameWidth, 0, sizeof(mRefFrameWidth));
|
||||
memset(mRefFrameHeight, 0, sizeof(mRefFrameHeight));
|
||||
}
|
||||
|
||||
void
|
||||
DXVAVP9Manager::Shutdown()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
FreeSurfaces();
|
||||
mParser.Reset();
|
||||
mDecoderService = nullptr;
|
||||
mDeviceManager = nullptr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DXVAVP9Manager::AllocateSurfaces(uint32_t aWidth, uint32_t aHeight,
|
||||
uint32_t aCount)
|
||||
{
|
||||
FreeSurfaces();
|
||||
|
||||
if (aCount < kMinSurfaces || aCount > kMaxSurfaces) { return E_INVALIDARG; }
|
||||
|
||||
const uint32_t alignedWidth = (aWidth + 15) & ~15u;
|
||||
const uint32_t alignedHeight = (aHeight + 15) & ~15u;
|
||||
|
||||
IDirect3DSurface9* surfaces[kMaxSurfaces] = {};
|
||||
HRESULT hr = mDecoderService->CreateSurface(
|
||||
alignedWidth,
|
||||
alignedHeight,
|
||||
aCount - 1,
|
||||
(D3DFORMAT)MAKEFOURCC('N','V','1','2'),
|
||||
D3DPOOL_DEFAULT,
|
||||
0,
|
||||
DXVA2_VideoDecoderRenderTarget,
|
||||
surfaces,
|
||||
nullptr);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < aCount; i++) {
|
||||
mSurfaces[i] = dont_AddRef(surfaces[i]);
|
||||
}
|
||||
mNumSurfaces = aCount;
|
||||
mCurrentSurface = aCount - 1;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
DXVAVP9Manager::FreeSurfaces()
|
||||
{
|
||||
mDecoder = nullptr;
|
||||
for (uint32_t i = 0; i < kMaxSurfaces; i++) {
|
||||
mSurfaces[i] = nullptr;
|
||||
}
|
||||
memset(mRefFrameSurface, 0xFF, sizeof(mRefFrameSurface));
|
||||
memset(mRefFrameWidth, 0, sizeof(mRefFrameWidth));
|
||||
memset(mRefFrameHeight, 0, sizeof(mRefFrameHeight));
|
||||
mNumSurfaces = kDefaultSurfaces;
|
||||
mCurrentSurface = kDefaultSurfaces - 1;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DXVAVP9Manager::InitDecoder(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
if (!aWidth || !aHeight || aWidth > 8192 || aHeight > 8192) { return E_INVALIDARG; }
|
||||
UINT formatCount = 0;
|
||||
D3DFORMAT* formats = nullptr;
|
||||
HRESULT hr = mDecoderService->GetDecoderRenderTargets(sVP9DecoderGUID, &formatCount, &formats);
|
||||
if (FAILED(hr)) { return hr; }
|
||||
bool nv12 = false;
|
||||
for (UINT i = 0; i < formatCount; ++i) {
|
||||
nv12 |= formats[i] == (D3DFORMAT)MAKEFOURCC('N','V','1','2');
|
||||
}
|
||||
CoTaskMemFree(formats);
|
||||
if (!nv12) { return E_FAIL; }
|
||||
|
||||
DXVA2_VideoDesc desc = {};
|
||||
desc.SampleWidth = aWidth;
|
||||
desc.SampleHeight = aHeight;
|
||||
desc.Format = (D3DFORMAT)MAKEFOURCC('N','V','1','2');
|
||||
desc.InputSampleFreq.Numerator = 30;
|
||||
desc.InputSampleFreq.Denominator = 1;
|
||||
desc.OutputFrameFreq = desc.InputSampleFreq;
|
||||
|
||||
UINT configCount = 0;
|
||||
DXVA2_ConfigPictureDecode* configs = nullptr;
|
||||
hr = mDecoderService->GetDecoderConfigurations(
|
||||
sVP9DecoderGUID, &desc, nullptr, &configCount, &configs);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (configCount == 0) {
|
||||
CoTaskMemFree(configs);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static const GUID noEncrypt = {0x1b81bed0, 0xa0c7, 0x11d3,
|
||||
{0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5}};
|
||||
DXVA2_ConfigPictureDecode chosenConfig = {};
|
||||
bool found = false;
|
||||
UINT rejectedForBuffCount = 0;
|
||||
UINT rejectedForRaw = 0;
|
||||
UINT rejectedForEncrypt = 0;
|
||||
for (UINT i = 0; i < configCount; ++i) {
|
||||
if (configs[i].ConfigBitstreamRaw != 1 &&
|
||||
configs[i].ConfigBitstreamRaw != 2) {
|
||||
rejectedForRaw = configs[i].ConfigBitstreamRaw;
|
||||
continue;
|
||||
}
|
||||
if (configs[i].guidConfigBitstreamEncryption != noEncrypt &&
|
||||
configs[i].guidConfigBitstreamEncryption != GUID_NULL) {
|
||||
rejectedForEncrypt++;
|
||||
continue;
|
||||
}
|
||||
if (configs[i].ConfigMinRenderTargetBuffCount > kMaxSurfaces) {
|
||||
rejectedForBuffCount = configs[i].ConfigMinRenderTargetBuffCount;
|
||||
continue;
|
||||
}
|
||||
chosenConfig = configs[i]; found = true; break;
|
||||
}
|
||||
CoTaskMemFree(configs);
|
||||
if (!found) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
uint32_t surfaceCount = kDefaultSurfaces;
|
||||
if (chosenConfig.ConfigMinRenderTargetBuffCount > surfaceCount) {
|
||||
surfaceCount = chosenConfig.ConfigMinRenderTargetBuffCount;
|
||||
}
|
||||
if (surfaceCount > kMaxSurfaces) { surfaceCount = kMaxSurfaces; }
|
||||
|
||||
hr = AllocateSurfaces(aWidth, aHeight, surfaceCount);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
IDirect3DSurface9* surfacePtrs[kMaxSurfaces];
|
||||
for (uint32_t i = 0; i < mNumSurfaces; i++) {
|
||||
surfacePtrs[i] = mSurfaces[i];
|
||||
}
|
||||
|
||||
hr = mDecoderService->CreateVideoDecoder(
|
||||
sVP9DecoderGUID,
|
||||
&desc,
|
||||
&chosenConfig,
|
||||
surfacePtrs,
|
||||
mNumSurfaces,
|
||||
mDecoder.StartAssignment());
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DXVAVP9Manager::ConfigureForSize(uint32_t aWidth, uint32_t aHeight)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
if (aWidth == mWidth && aHeight == mHeight) {
|
||||
return S_OK;
|
||||
}
|
||||
mWidth = aWidth;
|
||||
mHeight = aHeight;
|
||||
return InitDecoder(aWidth, aHeight);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
DXVAVP9Manager::PickNextSurface() const
|
||||
{
|
||||
for (uint32_t tries = 0; tries < mNumSurfaces; tries++) {
|
||||
uint32_t idx = (mCurrentSurface + 1 + tries) % mNumSurfaces;
|
||||
bool inUse = false;
|
||||
for (int slot = 0; slot < 8; slot++) {
|
||||
if (mRefFrameSurface[slot] == idx) {
|
||||
inUse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inUse) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
return (mCurrentSurface + 1) % mNumSurfaces;
|
||||
}
|
||||
|
||||
void
|
||||
DXVAVP9Manager::FillPicParams(const VP9FrameHeader& h,
|
||||
UXP_DXVA_PicParams_VP9& p)
|
||||
{
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
p.CurrPic.Index7Bits = (UCHAR)mCurrentSurface;
|
||||
p.CurrPic.AssociatedFlag = 0;
|
||||
p.profile = 0;
|
||||
|
||||
p.frame_type = h.frameType;
|
||||
p.show_frame = h.showFrame;
|
||||
p.error_resilient_mode = h.errorResilientMode;
|
||||
p.subsampling_x = h.subsamplingX;
|
||||
p.subsampling_y = h.subsamplingY;
|
||||
p.refresh_frame_context = h.refreshFrameContext;
|
||||
p.frame_parallel_decoding_mode = h.frameParallelDecodingMode;
|
||||
p.intra_only = (h.frameType != 0 && h.isIntra) ? 1 : 0;
|
||||
p.frame_context_idx = h.frameContextIdx;
|
||||
p.reset_frame_context = h.resetFrameContext;
|
||||
p.allow_high_precision_mv = (h.frameType != 0) ? h.allowHighPrecisionMv : 0;
|
||||
|
||||
p.BitDepthMinus8Luma = 0;
|
||||
p.BitDepthMinus8Chroma = 0;
|
||||
|
||||
p.interp_filter = h.interpFilter;
|
||||
|
||||
p.width = h.frameWidth;
|
||||
p.height = h.frameHeight;
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
p.ref_frame_map[i].bPicEntry = mRefFrameSurface[i];
|
||||
p.ref_frame_coded_width[i] = mRefFrameWidth[i];
|
||||
p.ref_frame_coded_height[i] = mRefFrameHeight[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
p.frame_refs[i].bPicEntry = 0xFF;
|
||||
}
|
||||
if (!h.isIntra) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uint8_t slot = h.refFrameIdx[i] & 7;
|
||||
uint8_t surfIdx = mRefFrameSurface[slot];
|
||||
p.frame_refs[i].bPicEntry = surfIdx;
|
||||
p.ref_frame_sign_bias[i + 1] = h.refFrameSignBias[i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
p.filter_level = (CHAR)h.filterLevel;
|
||||
p.sharpness_level = (CHAR)h.sharpnessLevel;
|
||||
p.mode_ref_delta_enabled = h.modeRefLfEnabled;
|
||||
p.mode_ref_delta_update = h.modeRefDeltaUpdate;
|
||||
p.use_prev_in_find_mv_refs = h.usePrevFrameMvs;
|
||||
for (int i = 0; i < 4; i++) { p.ref_deltas[i] = h.refDeltas[i]; }
|
||||
for (int i = 0; i < 2; i++) { p.mode_deltas[i] = h.modeDeltas[i]; }
|
||||
|
||||
p.base_qindex = (SHORT)h.baseQIndex;
|
||||
p.y_dc_delta_q = h.deltaQYDc;
|
||||
p.uv_dc_delta_q = h.deltaQUvDc;
|
||||
p.uv_ac_delta_q = h.deltaQUvAc;
|
||||
|
||||
p.stVP9Segments.enabled = h.segmentationEnabled;
|
||||
p.stVP9Segments.update_map = h.segmentationUpdateMap;
|
||||
p.stVP9Segments.temporal_update = h.segmentationTemporalUpdate;
|
||||
p.stVP9Segments.abs_delta = h.segmentationAbsOrDelta;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
p.stVP9Segments.tree_probs[i] = h.segmentationTreeProbs[i];
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
p.stVP9Segments.pred_probs[i] = h.segmentationPredProbs[i];
|
||||
}
|
||||
for (int i = 0; i < 8; i++) {
|
||||
UCHAR mask = 0;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (h.segFeatureEnabled[i][j]) {
|
||||
mask |= (1 << j);
|
||||
}
|
||||
p.stVP9Segments.feature_data[i][j] = (SHORT)h.segFeatureData[i][j];
|
||||
}
|
||||
p.stVP9Segments.feature_mask[i] = mask;
|
||||
}
|
||||
|
||||
p.log2_tile_cols = (UCHAR)h.log2TileCols;
|
||||
p.log2_tile_rows = (UCHAR)h.log2TileRows;
|
||||
|
||||
p.first_partition_size = (USHORT)h.compressedHeaderSize;
|
||||
p.uncompressed_header_size_byte_aligned = (USHORT)h.uncompressedHeaderSizeBytes;
|
||||
|
||||
p.StatusReportFeedbackNumber = ++mFrameCount;
|
||||
if (p.StatusReportFeedbackNumber == 0) {
|
||||
p.StatusReportFeedbackNumber = ++mFrameCount;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
DXVAVP9Manager::DecodeFrame(const uint8_t* aData, uint32_t aSize,
|
||||
IDirect3DSurface9** aOutSurface,
|
||||
bool* aOutShouldDisplay,
|
||||
VP9FrameHeader* aOutHeader)
|
||||
{
|
||||
NS_ENSURE_TRUE(mDecoder, E_NOT_VALID_STATE);
|
||||
NS_ENSURE_TRUE(aData && aSize > 0, E_INVALIDARG);
|
||||
NS_ENSURE_TRUE(aOutSurface, E_POINTER);
|
||||
NS_ENSURE_TRUE(aOutShouldDisplay, E_POINTER);
|
||||
|
||||
MutexAutoLock lock(mLock);
|
||||
|
||||
NS_ENSURE_TRUE(aOutHeader, E_POINTER);
|
||||
*aOutSurface = nullptr;
|
||||
*aOutShouldDisplay = false;
|
||||
|
||||
VP9FrameHeader header;
|
||||
if (!mParser.Parse(aData, aSize, header)) {
|
||||
if (header.profile != 0) {
|
||||
return MF_E_INVALIDMEDIATYPE;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*aOutHeader = header;
|
||||
|
||||
if (header.showExistingFrame) {
|
||||
uint8_t slot = header.frameToShowMapIdx;
|
||||
uint8_t surfIdx = mRefFrameSurface[slot];
|
||||
if (surfIdx == 0xFF || !mSurfaces[surfIdx]) {
|
||||
return E_FAIL;
|
||||
}
|
||||
*aOutSurface = mSurfaces[surfIdx];
|
||||
(*aOutSurface)->AddRef();
|
||||
*aOutShouldDisplay = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (header.frameWidth != mWidth || header.frameHeight != mHeight) {
|
||||
if (header.frameType != 0) { return MF_E_INVALIDMEDIATYPE; }
|
||||
HRESULT hr = InitDecoder(header.frameWidth, header.frameHeight);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
mWidth = header.frameWidth;
|
||||
mHeight = header.frameHeight;
|
||||
}
|
||||
|
||||
mCurrentSurface = PickNextSurface();
|
||||
IDirect3DSurface9* currentSurf = mSurfaces[mCurrentSurface];
|
||||
|
||||
static const uint32_t kBeginFrameRetries = 50;
|
||||
HRESULT hr = E_PENDING;
|
||||
for (uint32_t attempt = 0; attempt < kBeginFrameRetries; ++attempt) {
|
||||
hr = mDecoder->BeginFrame(currentSurf, nullptr);
|
||||
if (hr != E_PENDING) {
|
||||
break;
|
||||
}
|
||||
::Sleep(2);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
auto failWith = [this](HRESULT aHR) -> HRESULT {
|
||||
mDecoder->EndFrame(nullptr);
|
||||
return aHR;
|
||||
};
|
||||
|
||||
if (aSize > UINT32_MAX - 127) { return failWith(E_INVALIDARG); }
|
||||
UINT bitstreamCopied = (aSize + 127) & ~127u;
|
||||
{
|
||||
void* buf = nullptr; UINT size = 0;
|
||||
hr = mDecoder->GetBuffer(DXVA2_BitStreamDateBufferType, &buf, &size);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
if (!buf || size < bitstreamCopied) {
|
||||
mDecoder->ReleaseBuffer(DXVA2_BitStreamDateBufferType);
|
||||
return failWith(E_FAIL);
|
||||
}
|
||||
memcpy(buf, aData, aSize);
|
||||
memset(static_cast<uint8_t*>(buf) + aSize, 0, bitstreamCopied - aSize);
|
||||
hr = mDecoder->ReleaseBuffer(DXVA2_BitStreamDateBufferType);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
}
|
||||
|
||||
UXP_DXVA_PicParams_VP9 picParams;
|
||||
FillPicParams(header, picParams);
|
||||
|
||||
UXP_DXVA_Slice_VPx_Short sliceInfo = {};
|
||||
sliceInfo.BSNALunitDataLocation = 0;
|
||||
sliceInfo.SliceBytesInBuffer = aSize;
|
||||
sliceInfo.wBadSliceChopping = 0;
|
||||
|
||||
{
|
||||
void* buf = nullptr;
|
||||
UINT size = 0;
|
||||
hr = mDecoder->GetBuffer(DXVA2_PictureParametersBufferType, &buf, &size);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
if (size < sizeof(picParams)) {
|
||||
mDecoder->ReleaseBuffer(DXVA2_PictureParametersBufferType);
|
||||
return failWith(E_FAIL);
|
||||
}
|
||||
memcpy(buf, &picParams, sizeof(picParams));
|
||||
hr = mDecoder->ReleaseBuffer(DXVA2_PictureParametersBufferType);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
}
|
||||
|
||||
{
|
||||
void* buf = nullptr;
|
||||
UINT size = 0;
|
||||
hr = mDecoder->GetBuffer(DXVA2_SliceControlBufferType, &buf, &size);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
if (size < sizeof(sliceInfo)) {
|
||||
mDecoder->ReleaseBuffer(DXVA2_SliceControlBufferType);
|
||||
return failWith(E_FAIL);
|
||||
}
|
||||
memcpy(buf, &sliceInfo, sizeof(sliceInfo));
|
||||
hr = mDecoder->ReleaseBuffer(DXVA2_SliceControlBufferType);
|
||||
if (FAILED(hr)) { return failWith(hr); }
|
||||
}
|
||||
|
||||
DXVA2_DecodeBufferDesc bufDescs[3] = {};
|
||||
bufDescs[0].CompressedBufferType = DXVA2_PictureParametersBufferType;
|
||||
bufDescs[0].DataSize = (UINT)sizeof(picParams);
|
||||
bufDescs[0].DataOffset = 0;
|
||||
|
||||
bufDescs[1].CompressedBufferType = DXVA2_SliceControlBufferType;
|
||||
bufDescs[1].DataSize = (UINT)sizeof(sliceInfo);
|
||||
bufDescs[1].DataOffset = 0;
|
||||
|
||||
bufDescs[2].CompressedBufferType = DXVA2_BitStreamDateBufferType;
|
||||
bufDescs[2].DataSize = bitstreamCopied;
|
||||
bufDescs[2].DataOffset = 0;
|
||||
|
||||
DXVA2_DecodeExecuteParams execParams = {};
|
||||
execParams.NumCompBuffers = 3;
|
||||
execParams.pCompressedBuffers = bufDescs;
|
||||
|
||||
hr = mDecoder->Execute(&execParams);
|
||||
if (FAILED(hr)) {
|
||||
return failWith(hr);
|
||||
}
|
||||
|
||||
hr = mDecoder->EndFrame(nullptr);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (header.refreshFrameFlags & (1 << i)) {
|
||||
mRefFrameSurface[i] = (uint8_t)mCurrentSurface;
|
||||
mRefFrameWidth[i] = header.frameWidth;
|
||||
mRefFrameHeight[i] = header.frameHeight;
|
||||
}
|
||||
}
|
||||
|
||||
mParser.Commit(header);
|
||||
|
||||
*aOutSurface = currentSurf;
|
||||
(*aOutSurface)->AddRef();
|
||||
*aOutShouldDisplay = (header.showFrame != 0);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
Loading…
Add table
Add a link
Reference in a new issue