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)
{
AVCodec* decoder;
@ -427,77 +471,36 @@ bool FFmpegVideoDecoder::initialize(PDECODER_PARAMETERS params)
break;
}
m_BackendRenderer = createHwAccelRenderer(config);
if (!m_BackendRenderer) {
continue;
}
// Initialize the hardware codec and submit a test frame if the renderer needs it
m_HwDecodeCfg = config;
if (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
if (tryInitializeRenderer(decoder, params, config,
[config]() -> IFFmpegRenderer* { return createHwAccelRenderer(config); })) {
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
// MMAL is a non-hwaccel hardware decoder for the Raspberry Pi
if ((params->videoFormat & VIDEO_FORMAT_MASK_H264) &&
(params->vds != StreamingPreferences::VDS_FORCE_SOFTWARE)) {
AVCodec* mmalDecoder = avcodec_find_decoder_by_name("h264_mmal");
if (mmalDecoder) {
m_BackendRenderer = new MmalRenderer();
if (m_BackendRenderer->initialize(params) &&
completeInitialization(mmalDecoder, params, m_TestOnly)) {
if (mmalDecoder != nullptr &&
tryInitializeRenderer(decoder, params, nullptr,
[]() -> IFFmpegRenderer* { return new MmalRenderer(); })) {
return true;
}
else {
reset();
}
}
}
#endif
// We must fall back to a non-hardware accelerated decoder as
// all other possibilities have been exhausted.
m_HwDecodeCfg = nullptr;
m_BackendRenderer = new SdlRenderer();
if (params->vds != StreamingPreferences::VDS_FORCE_HARDWARE &&
m_BackendRenderer->initialize(params) &&
completeInitialization(decoder, params, m_TestOnly)) {
if (tryInitializeRenderer(decoder, params, nullptr,
[]() -> IFFmpegRenderer* { return new SdlRenderer(); })) {
return true;
}
else {
reset();
// No decoder worked
return false;
}
}
void FFmpegVideoDecoder::writeBuffer(PLENTRY entry, int& offset)
{

View File

@ -1,5 +1,7 @@
#pragma once
#include <functional>
#include "decoder.h"
#include "ffmpeg-renderers/renderer.h"
#include "ffmpeg-renderers/pacer/pacer.h"
@ -31,7 +33,12 @@ private:
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();