зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1236112 - Block on d3d9 video frames to complete before returning them from the decoder. r=cpearce
This commit is contained in:
Родитель
b06db46573
Коммит
bfae8352c6
|
@ -48,6 +48,7 @@
|
|||
#include "TimeUnits.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -2420,7 +2421,7 @@ MediaDecoderStateMachine::CheckFrameValidity(VideoData* aData)
|
|||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
||||
// Update corrupt-frames statistics
|
||||
if (aData->mImage && !aData->mImage->IsValid()) {
|
||||
if (aData->mImage && !aData->mImage->IsValid() && !gfxPrefs::HardwareVideoDecodingForceEnabled()) {
|
||||
FrameStatistics& frameStats = *mFrameStats;
|
||||
frameStats.NotifyCorruptFrame();
|
||||
// If more than 10% of the last 30 frames have been corrupted, then try disabling
|
||||
|
|
|
@ -423,12 +423,40 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
|
|||
getter_AddRefs(surface));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
RefPtr<D3D9SurfaceImage> image = new D3D9SurfaceImage(mFirstFrame);
|
||||
RefPtr<D3D9SurfaceImage> image = new D3D9SurfaceImage();
|
||||
hr = image->AllocateAndCopy(mTextureClientAllocator, surface, aRegion);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
// Flush the draw command now, so that by the time we come to draw this
|
||||
// image, we're less likely to need to wait for the draw operation to
|
||||
// complete.
|
||||
RefPtr<IDirect3DQuery9> query;
|
||||
hr = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
hr = query->Issue(D3DISSUE_END);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
bool valid = false;
|
||||
int iterations = 0;
|
||||
while (iterations < (mFirstFrame ? 100 : 10)) {
|
||||
hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
|
||||
if (hr == S_FALSE) {
|
||||
Sleep(1);
|
||||
iterations++;
|
||||
continue;
|
||||
}
|
||||
if (hr == S_OK) {
|
||||
valid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mFirstFrame = false;
|
||||
|
||||
if (!valid) {
|
||||
image->Invalidate();
|
||||
}
|
||||
|
||||
image.forget(aOutImage);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,10 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
|
||||
D3D9SurfaceImage::D3D9SurfaceImage(bool aIsFirstFrame)
|
||||
D3D9SurfaceImage::D3D9SurfaceImage()
|
||||
: Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE)
|
||||
, mSize(0, 0)
|
||||
, mValid(false)
|
||||
, mIsFirstFrame(aIsFirstFrame)
|
||||
{}
|
||||
|
||||
D3D9SurfaceImage::~D3D9SurfaceImage()
|
||||
|
@ -73,52 +72,11 @@ D3D9SurfaceImage::AllocateAndCopy(D3D9RecycleAllocator* aAllocator,
|
|||
hr = device->StretchRect(surface, &src, textureSurface, nullptr, D3DTEXF_NONE);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
// Flush the draw command now, so that by the time we come to draw this
|
||||
// image, we're less likely to need to wait for the draw operation to
|
||||
// complete.
|
||||
RefPtr<IDirect3DQuery9> query;
|
||||
hr = device->CreateQuery(D3DQUERYTYPE_EVENT, getter_AddRefs(query));
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
hr = query->Issue(D3DISSUE_END);
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
|
||||
|
||||
mTextureClient = textureClient;
|
||||
mSize = aRegion.Size();
|
||||
mQuery = query;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
D3D9SurfaceImage::IsValid()
|
||||
{
|
||||
EnsureSynchronized();
|
||||
return mValid;
|
||||
}
|
||||
|
||||
void
|
||||
D3D9SurfaceImage::EnsureSynchronized()
|
||||
{
|
||||
RefPtr<IDirect3DQuery9> query = mQuery;
|
||||
if (!query) {
|
||||
// Not setup, or already synchronized.
|
||||
return;
|
||||
}
|
||||
int iterations = 0;
|
||||
while (iterations < (mIsFirstFrame ? 100 : 10)) {
|
||||
HRESULT hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
|
||||
if (hr == S_FALSE) {
|
||||
Sleep(1);
|
||||
iterations++;
|
||||
continue;
|
||||
}
|
||||
if (hr == S_OK) {
|
||||
mValid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
mQuery = nullptr;
|
||||
}
|
||||
|
||||
const D3DSURFACE_DESC&
|
||||
D3D9SurfaceImage::GetDesc() const
|
||||
{
|
||||
|
@ -136,7 +94,6 @@ D3D9SurfaceImage::GetTextureClient(CompositableClient* aClient)
|
|||
{
|
||||
MOZ_ASSERT(mTextureClient);
|
||||
MOZ_ASSERT(mTextureClient->GetAllocator() == aClient->GetForwarder());
|
||||
EnsureSynchronized();
|
||||
return mTextureClient;
|
||||
}
|
||||
|
||||
|
@ -153,9 +110,6 @@ D3D9SurfaceImage::GetAsSourceSurface()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Ensure that the texture is ready to be used.
|
||||
EnsureSynchronized();
|
||||
|
||||
DXGID3D9TextureData* texData = static_cast<DXGID3D9TextureData*>(mTextureClient->GetInternalData());
|
||||
// Readback the texture from GPU memory into system memory, so that
|
||||
// we can copy it into the Cairo image. This is expensive.
|
||||
|
|
|
@ -47,7 +47,7 @@ protected:
|
|||
// resource is ready to use.
|
||||
class D3D9SurfaceImage : public Image {
|
||||
public:
|
||||
explicit D3D9SurfaceImage(bool aIsFirstFrame);
|
||||
explicit D3D9SurfaceImage();
|
||||
virtual ~D3D9SurfaceImage();
|
||||
|
||||
HRESULT AllocateAndCopy(D3D9RecycleAllocator* aAllocator,
|
||||
|
@ -63,19 +63,15 @@ public:
|
|||
|
||||
virtual TextureClient* GetTextureClient(CompositableClient* aClient) override;
|
||||
|
||||
virtual bool IsValid() override;
|
||||
virtual bool IsValid() override { return mValid; }
|
||||
|
||||
void Invalidate() { mValid = false; }
|
||||
|
||||
private:
|
||||
|
||||
// Blocks the calling thread until the copy operation started in SetData()
|
||||
// is complete, whereupon the texture is safe to use.
|
||||
void EnsureSynchronized();
|
||||
|
||||
gfx::IntSize mSize;
|
||||
RefPtr<IDirect3DQuery9> mQuery;
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
bool mValid;
|
||||
bool mIsFirstFrame;
|
||||
};
|
||||
|
||||
} // namepace layers
|
||||
|
|
Загрузка…
Ссылка в новой задаче