Refactor renderer initialization to reduce duplication and inconsistency

This commit is contained in:
Cameron Gutman 2019-04-18 20:02:14 -07:00
parent e51ad1a68a
commit 1dfca525cf
2 changed files with 65 additions and 55 deletions

View File

@ -394,6 +394,50 @@ IFFmpegRenderer* FFmpegVideoDecoder::createHwAccelRenderer(const AVCodecHWConfig
} }
} }
bool FFmpegVideoDecoder::tryInitializeRenderer(AVCodec* decoder,
PDECODER_PARAMETERS params,
const AVCodecHWConfig* hwConfig,
std::function<IFFmpegRenderer*()> createRendererFunc)
{
m_BackendRenderer = createRendererFunc();
m_HwDecodeCfg = hwConfig;
if (m_BackendRenderer != nullptr &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, m_TestOnly || m_BackendRenderer->needsTestFrame())) {
if (m_TestOnly) {
// This decoder is only for testing capabilities, so don't bother
// creating a usable renderer
return true;
}
if (m_BackendRenderer->needsTestFrame()) {
// The test worked, so now let's initialize it for real
reset();
if ((m_BackendRenderer = createRendererFunc()) != nullptr &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, false)) {
return true;
}
else {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
"Decoder failed to initialize after successful test");
reset();
}
}
else {
// No test required. Good to go now.
return true;
}
}
else {
// Failed to initialize or test frame failed, so keep looking
reset();
}
return false;
}
bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params) bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params)
{ {
AVCodec* decoder; AVCodec* decoder;
@ -427,76 +471,35 @@ bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params)
break; break;
} }
m_BackendRenderer = createHwAccelRenderer(config);
if (!m_BackendRenderer) {
continue;
}
// Initialize the hardware codec and submit a test frame if the renderer needs it // Initialize the hardware codec and submit a test frame if the renderer needs it
m_HwDecodeCfg = config; if (tryInitializeRenderer(decoder, params, config,
if (m_BackendRenderer->initialize(params) && [config]() -> IFFmpegRenderer* { return createHwAccelRenderer(config); })) {
completeInitialization(decoder, params, m_TestOnly || m_BackendRenderer->needsTestFrame())) {
if (m_TestOnly) {
// This decoder is only for testing capabilities, so don't bother
// creating a usable renderer
return true; return true;
} }
if (m_BackendRenderer->needsTestFrame()) {
// The test worked, so now let's initialize it for real
reset();
if ((m_BackendRenderer = createHwAccelRenderer(config)) != nullptr &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, false)) {
return true;
}
else {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION,
"Decoder failed to initialize after successful test");
reset();
}
}
else {
// No test required. Good to go now.
return true;
}
}
else {
// Failed to initialize or test frame failed, so keep looking
reset();
}
} }
#ifdef HAVE_MMAL #ifdef HAVE_MMAL
// MMAL is a non-hwaccel hardware decoder for the Raspberry Pi
if ((params->videoFormat & VIDEO_FORMAT_MASK_H264) && if ((params->videoFormat & VIDEO_FORMAT_MASK_H264) &&
(params->vds != StreamingPreferences::VDS_FORCE_SOFTWARE)) { (params->vds != StreamingPreferences::VDS_FORCE_SOFTWARE)) {
AVCodec* mmalDecoder = avcodec_find_decoder_by_name("h264_mmal"); AVCodec* mmalDecoder = avcodec_find_decoder_by_name("h264_mmal");
if (mmalDecoder) { if (mmalDecoder != nullptr &&
m_BackendRenderer = new MmalRenderer(); tryInitializeRenderer(decoder, params, nullptr,
if (m_BackendRenderer->initialize(params) && []() -> IFFmpegRenderer* { return new MmalRenderer(); })) {
completeInitialization(mmalDecoder, params, m_TestOnly)) {
return true; return true;
} }
else {
reset();
}
}
} }
#endif #endif
// We must fall back to a non-hardware accelerated decoder as // We must fall back to a non-hardware accelerated decoder as
// all other possibilities have been exhausted. // all other possibilities have been exhausted.
m_HwDecodeCfg = nullptr; if (tryInitializeRenderer(decoder, params, nullptr,
m_BackendRenderer = new SdlRenderer(); []() -> IFFmpegRenderer* { return new SdlRenderer(); })) {
if (params->vds != StreamingPreferences::VDS_FORCE_HARDWARE &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, m_TestOnly)) {
return true; return true;
} }
else {
reset(); // No decoder worked
return false; return false;
}
} }
void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset) void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <functional>
#include "decoder.h" #include "decoder.h"
#include "ffmpeg-renderers/renderer.h" #include "ffmpeg-renderers/renderer.h"
#include "ffmpeg-renderers/pacer/pacer.h" #include "ffmpeg-renderers/pacer/pacer.h"
@ -31,7 +33,12 @@ private:
bool createFrontendRenderer(PDECODER_PARAMETERS params); bool createFrontendRenderer(PDECODER_PARAMETERS params);
IFFmpegRenderer* createHwAccelRenderer(const AVCodecHWConfig* hwDecodeCfg); bool tryInitializeRenderer(AVCodec* decoder,
PDECODER_PARAMETERS params,
const AVCodecHWConfig* hwConfig,
std::function<IFFmpegRenderer*()> createRendererFunc);
static IFFmpegRenderer* createHwAccelRenderer(const AVCodecHWConfig* hwDecodeCfg);
void reset(); void reset();