Video instance is now a singleton. Allocate new buffer when a video of largest size being played. Keeping pipeline open when changing videos.

This commit is contained in:
emb 2015-01-08 23:29:01 -06:00
parent 76032584ac
commit 4dd2c97fd6
6 changed files with 81 additions and 75 deletions

View File

@ -41,7 +41,6 @@ RetroFE::RetroFE(CollectionDatabase &db, Configuration &c)
, Input(Config) , Input(Config)
, KeyInputDisable(0) , KeyInputDisable(0)
, CurrentTime(0) , CurrentTime(0)
, VideoInst(NULL)
{ {
} }
@ -83,8 +82,6 @@ bool RetroFE::Initialize()
VideoFactory::SetEnabled(videoEnable); VideoFactory::SetEnabled(videoEnable);
VideoFactory::SetNumLoops(videoLoop); VideoFactory::SetNumLoops(videoLoop);
VideoFactory vf;
VideoInst = vf.CreateVideo();
return true; return true;
} }
@ -153,12 +150,6 @@ bool RetroFE::DeInitialize()
PageChain.pop_back(); PageChain.pop_back();
} }
if(VideoInst)
{
delete VideoInst;
VideoInst = NULL;
}
//todo: handle video deallocation //todo: handle video deallocation
return retVal; return retVal;
} }

View File

@ -58,7 +58,6 @@ private:
float CurrentTime; float CurrentTime;
Item *NextPageItem; Item *NextPageItem;
FontCache FC; FontCache FC;
IVideo *VideoInst;
AttractMode Attract; AttractMode Attract;
}; };

View File

@ -49,6 +49,7 @@ GStreamerVideo::GStreamerVideo()
, Height(0) , Height(0)
, Width(0) , Width(0)
, VideoBuffer(NULL) , VideoBuffer(NULL)
, VideoBufferSize(0)
, FrameReady(false) , FrameReady(false)
, IsPlaying(false) , IsPlaying(false)
, PlayCount(0) , PlayCount(0)
@ -58,6 +59,15 @@ GStreamerVideo::GStreamerVideo()
GStreamerVideo::~GStreamerVideo() GStreamerVideo::~GStreamerVideo()
{ {
Stop(); Stop();
if(VideoBuffer)
{
delete[] VideoBuffer;
VideoBuffer = NULL;
VideoBufferSize = 0;
}
FreeElements();
} }
void GStreamerVideo::SetNumLoops(int n) void GStreamerVideo::SetNumLoops(int n)
@ -89,10 +99,18 @@ void GStreamerVideo::ProcessNewBuffer (GstElement *fakesink, GstBuffer *buf, Gst
if(video->Height && video->Width) if(video->Height && video->Width)
{ {
if(!video->VideoBuffer) // keep the largest video buffer allocated to avoid the penalty of reallocating and deallocating
if(!video->VideoBuffer || video->VideoBufferSize < map.size)
{ {
if(video->VideoBuffer)
{
delete[] video->VideoBuffer;
}
video->VideoBuffer = new char[map.size]; video->VideoBuffer = new char[map.size];
video->VideoBufferSize = map.size;
} }
memcpy(video->VideoBuffer, map.data, map.size); memcpy(video->VideoBuffer, map.data, map.size);
gst_buffer_unmap(buf, &map); gst_buffer_unmap(buf, &map);
video->FrameReady = true; video->FrameReady = true;
@ -108,8 +126,11 @@ bool GStreamerVideo::Initialize()
std::string path = Configuration::GetAbsolutePath() + "/Core"; std::string path = Configuration::GetAbsolutePath() + "/Core";
gst_init(NULL, NULL); gst_init(NULL, NULL);
#ifdef WIN32
GstRegistry *registry = gst_registry_get(); GstRegistry *registry = gst_registry_get();
gst_registry_scan_path(registry, path.c_str()); gst_registry_scan_path(registry, path.c_str());
#endif
Initialized = true; Initialized = true;
@ -141,7 +162,7 @@ bool GStreamerVideo::Stop()
(void)gst_element_set_state(Playbin, GST_STATE_NULL); (void)gst_element_set_state(Playbin, GST_STATE_NULL);
} }
FreeElements(); // FreeElements();
IsPlaying = false; IsPlaying = false;
@ -155,11 +176,6 @@ bool GStreamerVideo::Stop()
Width = 0; Width = 0;
FrameReady = false; FrameReady = false;
if(VideoBuffer)
{
delete VideoBuffer;
VideoBuffer = NULL;
}
return true; return true;
} }
@ -184,67 +200,67 @@ bool GStreamerVideo::Play(std::string file)
Configuration::ConvertToAbsolutePath(Configuration::GetAbsolutePath(), file); Configuration::ConvertToAbsolutePath(Configuration::GetAbsolutePath(), file);
file = uriFile; file = uriFile;
// Pipeline = gst_pipeline_new("pipeline");
Playbin = gst_element_factory_make("playbin", "player");
VideoBin = gst_bin_new("SinkBin");
VideoSink = gst_element_factory_make("fakesink", "video_sink");
VideoConvert = gst_element_factory_make("capsfilter", "video_convert");
VideoConvertCaps = gst_caps_from_string("video/x-raw,format=(string)YUY2");
Height = 0;
Width = 0;
if(!Playbin) if(!Playbin)
{ {
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create playbin"); Playbin = gst_element_factory_make("playbin", "player");
FreeElements(); VideoBin = gst_bin_new("SinkBin");
return false; VideoSink = gst_element_factory_make("fakesink", "video_sink");
} VideoConvert = gst_element_factory_make("capsfilter", "video_convert");
if(!VideoSink) VideoConvertCaps = gst_caps_from_string("video/x-raw,format=(string)YUY2");
{ Height = 0;
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video sink"); Width = 0;
FreeElements(); if(!Playbin)
return false; {
} Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create playbin");
if(!VideoConvert) FreeElements();
{ return false;
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video converter"); }
FreeElements(); if(!VideoSink)
return false; {
} Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video sink");
if(!VideoConvertCaps) FreeElements();
{ return false;
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video caps"); }
FreeElements(); if(!VideoConvert)
return false; {
} Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video converter");
FreeElements();
return false;
}
if(!VideoConvertCaps)
{
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not create video caps");
FreeElements();
return false;
}
gst_bin_add_many(GST_BIN(VideoBin), VideoConvert, VideoSink, NULL); gst_bin_add_many(GST_BIN(VideoBin), VideoConvert, VideoSink, NULL);
gst_element_link_filtered(VideoConvert, VideoSink, VideoConvertCaps); gst_element_link_filtered(VideoConvert, VideoSink, VideoConvertCaps);
GstPad *videoConvertSinkPad = gst_element_get_static_pad(VideoConvert, "sink"); GstPad *videoConvertSinkPad = gst_element_get_static_pad(VideoConvert, "sink");
if(!videoConvertSinkPad) if(!videoConvertSinkPad)
{ {
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not get video convert sink pad"); Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not get video convert sink pad");
FreeElements(); FreeElements();
return false; return false;
} }
g_object_set(G_OBJECT(VideoSink), "sync", TRUE, "qos", FALSE, NULL);
g_object_set(G_OBJECT(VideoSink), "sync", TRUE, "qos", FALSE, NULL); GstPad *videoSinkPad = gst_ghost_pad_new("sink", videoConvertSinkPad);
if(!videoSinkPad)
{
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not get video bin sink pad");
FreeElements();
gst_object_unref(videoConvertSinkPad);
videoConvertSinkPad = NULL;
return false;
}
GstPad *videoSinkPad = gst_ghost_pad_new("sink", videoConvertSinkPad); gst_element_add_pad(VideoBin, videoSinkPad);
if(!videoSinkPad)
{
Logger::Write(Logger::ZONE_DEBUG, "Video", "Could not get video bin sink pad");
FreeElements();
gst_object_unref(videoConvertSinkPad); gst_object_unref(videoConvertSinkPad);
videoConvertSinkPad = NULL; videoConvertSinkPad = NULL;
return false;
} }
gst_element_add_pad(VideoBin, videoSinkPad);
gst_object_unref(videoConvertSinkPad);
videoConvertSinkPad = NULL;
g_object_set(G_OBJECT(Playbin), "uri", file.c_str(), "video-sink", VideoBin, NULL); g_object_set(G_OBJECT(Playbin), "uri", file.c_str(), "video-sink", VideoBin, NULL);
IsPlaying = true; IsPlaying = true;
@ -337,8 +353,6 @@ void GStreamerVideo::Update(float dt)
{ {
if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_EOS) if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_EOS)
{ {
Logger::Write(Logger::ZONE_ERROR, "Video", "EOS!");
PlayCount++; PlayCount++;
//todo: nesting hazard //todo: nesting hazard

View File

@ -41,6 +41,7 @@ private:
gint Height; gint Height;
gint Width; gint Width;
char *VideoBuffer; char *VideoBuffer;
gsize VideoBufferSize;
bool FrameReady; bool FrameReady;
bool IsPlaying; bool IsPlaying;
static bool Initialized; static bool Initialized;

View File

@ -20,19 +20,19 @@
bool VideoFactory::Enabled = true; bool VideoFactory::Enabled = true;
int VideoFactory::NumLoops = 0; int VideoFactory::NumLoops = 0;
IVideo *VideoFactory::Instance = NULL;
IVideo *VideoFactory::CreateVideo() IVideo *VideoFactory::CreateVideo()
{ {
IVideo *instance = NULL;
if(Enabled) if(Enabled)
{ {
instance = new GStreamerVideo(); Instance = new GStreamerVideo();
instance->Initialize(); Instance->Initialize();
((GStreamerVideo *)(instance))->SetNumLoops(NumLoops); ((GStreamerVideo *)(Instance))->SetNumLoops(NumLoops);
} }
return instance; return Instance;
} }
void VideoFactory::SetEnabled(bool enabled) void VideoFactory::SetEnabled(bool enabled)

View File

@ -15,4 +15,5 @@ public:
private: private:
static bool Enabled; static bool Enabled;
static int NumLoops; static int NumLoops;
static IVideo *Instance;
}; };