Merge branch 'master' of github.com:cgutman/moonlight-qt

This commit is contained in:
R. Aidan Campbell 2018-07-20 15:47:57 -07:00
commit 48c2a8c5b0
4 changed files with 67 additions and 39 deletions

View file

@ -101,6 +101,11 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,
int Session::drSetup(int videoFormat, int width, int height, int frameRate, void *, int)
{
s_ActiveSession->m_ActiveVideoFormat = videoFormat;
s_ActiveSession->m_ActiveVideoWidth = width;
s_ActiveSession->m_ActiveVideoHeight = height;
s_ActiveSession->m_ActiveVideoFrameRate = frameRate;
if (!chooseDecoder(s_ActiveSession->m_Preferences.videoDecoderSelection,
s_ActiveSession->m_Window,
videoFormat, width, height, frameRate,
@ -117,7 +122,16 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du)
// from underneath the session when we initiate destruction.
// We need to destroy the decoder on the main thread to satisfy
// some API constraints (like DXVA2).
SDL_AtomicLock(&s_ActiveSession->m_DecoderLock);
if (s_ActiveSession->m_NeedsIdr) {
// If we reset our decoder, we'll need to request an IDR frame
s_ActiveSession->m_NeedsIdr = false;
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock);
return DR_NEED_IDR;
}
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
if (decoder != nullptr) {
int ret = decoder->submitDecodeUnit(du);
@ -160,7 +174,8 @@ Session::Session(NvComputer* computer, NvApp& app)
m_App(app),
m_Window(nullptr),
m_VideoDecoder(nullptr),
m_DecoderLock(0)
m_DecoderLock(0),
m_NeedsIdr(false)
{
LiInitializeVideoCallbacks(&m_VideoCallbacks);
m_VideoCallbacks.setup = drSetup;
@ -510,6 +525,32 @@ void Session::exec()
m_VideoDecoder->renderFrame(&event.user);
break;
}
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
SDL_AtomicLock(&m_DecoderLock);
// Destroy the old decoder
delete m_VideoDecoder;
// Chose a new decoder (hopefully the same one, but possibly
// not if a GPU was removed or something).
if (!chooseDecoder(m_Preferences.videoDecoderSelection,
m_Window, m_ActiveVideoFormat, m_ActiveVideoWidth,
m_ActiveVideoHeight, m_ActiveVideoFrameRate,
s_ActiveSession->m_VideoDecoder)) {
SDL_AtomicUnlock(&m_DecoderLock);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to recreate decoder after reset");
goto DispatchDeferredCleanup;
}
// Request an IDR frame to complete the reset
m_NeedsIdr = true;
SDL_AtomicUnlock(&m_DecoderLock);
break;
case SDL_KEYUP:
case SDL_KEYDOWN:
inputHandler.handleKeyEvent(&event.key);

View file

@ -94,6 +94,12 @@ private:
SDL_Window* m_Window;
IVideoDecoder* m_VideoDecoder;
SDL_SpinLock m_DecoderLock;
bool m_NeedsIdr;
int m_ActiveVideoFormat;
int m_ActiveVideoWidth;
int m_ActiveVideoHeight;
int m_ActiveVideoFrameRate;
static SDL_AudioDeviceID s_AudioDevice;
static OpusMSDecoder* s_OpusDecoder;

View file

@ -409,28 +409,6 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
IDirect3DSurface9* surface = reinterpret_cast<IDirect3DSurface9*>(frame->data[3]);
HRESULT hr;
hr = m_Device->TestCooperativeLevel();
switch (hr) {
case D3D_OK:
break;
case D3DERR_DEVICELOST:
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"D3D device lost!");
av_frame_free(&frame);
return;
case D3DERR_DEVICENOTRESET:
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"D3D device not reset!");
av_frame_free(&frame);
return;
default:
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Unknown D3D error: %x",
hr);
av_frame_free(&frame);
return;
}
DXVA2_VideoSample sample = {};
sample.Start = m_FrameIndex;
sample.End = m_FrameIndex + 1;
@ -473,25 +451,33 @@ void DXVA2Renderer::renderFrame(AVFrame* frame)
bltParams.Alpha = DXVA2_Fixed32OpaqueAlpha();
hr = m_Device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 0.0f, 0);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Clear() failed: %x",
hr);
if (SDL_RenderClear(m_SdlRenderer) != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
"SDL_RenderClear() failed: %s",
SDL_GetError());
av_frame_free(&frame);
// We're going to cheat a little bit here. It seems SDL's
// renderer may flake out in scenarios like moving the window
// between monitors, so generate a synthetic reset event for
// the main loop to consume.
SDL_Event event;
event.type = SDL_RENDER_TARGETS_RESET;
SDL_PushEvent(&event);
return;
}
hr = m_Processor->VideoProcessBlt(m_RenderTarget, &bltParams, &sample, 1, nullptr);
av_frame_free(&frame);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"VideoProcessBlt() failed: %x",
hr);
av_frame_free(&frame);
return;
}
m_Device->Present(nullptr, nullptr, nullptr, nullptr);
av_frame_free(&frame);
// We must try to present to trigger SDL's logic to recover the render target,
// even if VideoProcessBlt() fails.
SDL_RenderPresent(m_SdlRenderer);
}

View file

@ -128,14 +128,9 @@ FFmpegVideoDecoder::~FFmpegVideoDecoder()
}
}
avcodec_close(m_VideoDecoderCtx);
av_free(m_VideoDecoderCtx);
m_VideoDecoderCtx = nullptr;
m_HwDecodeCfg = nullptr;
avcodec_free_context(&m_VideoDecoderCtx);
delete m_Renderer;
m_Renderer = nullptr;
}
bool FFmpegVideoDecoder::initialize(