GStreamer 1.0: fix some problems with QGstVideoRendererSink.

- Correctly free resources on deletion.
- Correctly stop the sink. We were stopping only when null caps
  were passed to set_caps() but that doesn't seem to always happen.
  Implement GstBaseSink.stop() which is always and consistently
  called by GStreamer.
- Remove pre-roll support (as done previously for 0.10, see
  commit 3b20608f).

Change-Id: I4c5808938f244f4f8a35e121a3a4a862588b752d
Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
This commit is contained in:
Yoann Lopes
2015-01-28 15:17:57 +01:00
parent e4bf7d90bf
commit d4f88c3ec9
2 changed files with 22 additions and 97 deletions

View File

@@ -114,10 +114,9 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surfac
, m_activeRenderer(0) , m_activeRenderer(0)
, m_surfaceCaps(0) , m_surfaceCaps(0)
, m_startCaps(0) , m_startCaps(0)
, m_lastBuffer(0) , m_renderBuffer(0)
, m_notified(false) , m_notified(false)
, m_stop(false) , m_stop(false)
, m_render(false)
, m_flush(false) , m_flush(false)
{ {
foreach (QObject *instance, rendererLoader()->instances(QGstVideoRendererPluginKey)) { foreach (QObject *instance, rendererLoader()->instances(QGstVideoRendererPluginKey)) {
@@ -137,6 +136,8 @@ QVideoSurfaceGstDelegate::~QVideoSurfaceGstDelegate()
if (m_surfaceCaps) if (m_surfaceCaps)
gst_caps_unref(m_surfaceCaps); gst_caps_unref(m_surfaceCaps);
if (m_startCaps)
gst_caps_unref(m_startCaps);
} }
GstCaps *QVideoSurfaceGstDelegate::caps() GstCaps *QVideoSurfaceGstDelegate::caps()
@@ -157,13 +158,6 @@ bool QVideoSurfaceGstDelegate::start(GstCaps *caps)
m_stop = true; m_stop = true;
} }
m_render = false;
if (m_lastBuffer) {
gst_buffer_unref(m_lastBuffer);
m_lastBuffer = 0;
}
if (m_startCaps) if (m_startCaps)
gst_caps_unref(m_startCaps); gst_caps_unref(m_startCaps);
m_startCaps = caps; m_startCaps = caps;
@@ -204,11 +198,6 @@ void QVideoSurfaceGstDelegate::stop()
m_startCaps = 0; m_startCaps = 0;
} }
if (m_lastBuffer) {
gst_buffer_unref(m_lastBuffer);
m_lastBuffer = 0;
}
waitForAsyncEvent(&locker, &m_setupCondition, 500); waitForAsyncEvent(&locker, &m_setupCondition, 500);
} }
@@ -225,68 +214,19 @@ bool QVideoSurfaceGstDelegate::proposeAllocation(GstQuery *query)
} }
} }
void QVideoSurfaceGstDelegate::flush() GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer)
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
m_flush = true; m_renderBuffer = buffer;
m_render = false;
if (m_lastBuffer) { GstFlowReturn flowReturn = waitForAsyncEvent(&locker, &m_renderCondition, 300)
gst_buffer_unref(m_lastBuffer); ? m_renderReturn
m_lastBuffer = 0; : GST_FLOW_ERROR;
}
notify(); m_renderBuffer = 0;
}
GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer, bool show) return flowReturn;
{
QMutexLocker locker(&m_mutex);
if (m_lastBuffer)
gst_buffer_unref(m_lastBuffer);
m_lastBuffer = buffer;
gst_buffer_ref(m_lastBuffer);
if (show) {
m_render = true;
return waitForAsyncEvent(&locker, &m_renderCondition, 300)
? m_renderReturn
: GST_FLOW_ERROR;
} else {
return GST_FLOW_OK;
}
}
void QVideoSurfaceGstDelegate::handleShowPrerollChange(GObject *object, GParamSpec *, gpointer d)
{
QVideoSurfaceGstDelegate * const delegate = static_cast<QVideoSurfaceGstDelegate *>(d);
gboolean showPreroll = true; // "show-preroll-frame" property is true by default
g_object_get(object, "show-preroll-frame", &showPreroll, NULL);
GstState state = GST_STATE_NULL;
GstState pendingState = GST_STATE_NULL;
gst_element_get_state(GST_ELEMENT(object), &state, &pendingState, 0);
const bool paused
= (pendingState == GST_STATE_VOID_PENDING && state == GST_STATE_PAUSED)
|| pendingState == GST_STATE_PAUSED;
if (paused) {
QMutexLocker locker(&delegate->m_mutex);
if (!showPreroll && delegate->m_lastBuffer) {
delegate->m_render = false;
delegate->m_flush = true;
delegate->notify();
} else if (delegate->m_lastBuffer) {
delegate->m_render = true;
delegate->notify();
}
}
} }
bool QVideoSurfaceGstDelegate::event(QEvent *event) bool QVideoSurfaceGstDelegate::event(QEvent *event)
@@ -350,11 +290,9 @@ bool QVideoSurfaceGstDelegate::handleEvent(QMutexLocker *locker)
} }
gst_caps_unref(startCaps); gst_caps_unref(startCaps);
} else if (m_render) { } else if (m_renderBuffer) {
m_render = false; if (m_activeRenderer && m_surface) {
GstBuffer *buffer = m_renderBuffer;
if (m_activeRenderer && m_surface && m_lastBuffer) {
GstBuffer *buffer = m_lastBuffer;
gst_buffer_ref(buffer); gst_buffer_ref(buffer);
locker->unlock(); locker->unlock();
@@ -442,12 +380,6 @@ QGstVideoRendererSink *QGstVideoRendererSink::createSink(QAbstractVideoSurface *
sink->delegate = new QVideoSurfaceGstDelegate(surface); sink->delegate = new QVideoSurfaceGstDelegate(surface);
g_signal_connect(
G_OBJECT(sink),
"notify::show-preroll-frame",
G_CALLBACK(QVideoSurfaceGstDelegate::handleShowPrerollChange),
sink->delegate);
return sink; return sink;
} }
@@ -487,7 +419,7 @@ void QGstVideoRendererSink::class_init(gpointer g_class, gpointer class_data)
base_sink_class->get_caps = QGstVideoRendererSink::get_caps; base_sink_class->get_caps = QGstVideoRendererSink::get_caps;
base_sink_class->set_caps = QGstVideoRendererSink::set_caps; base_sink_class->set_caps = QGstVideoRendererSink::set_caps;
base_sink_class->propose_allocation = QGstVideoRendererSink::propose_allocation; base_sink_class->propose_allocation = QGstVideoRendererSink::propose_allocation;
base_sink_class->preroll = QGstVideoRendererSink::preroll; base_sink_class->stop = QGstVideoRendererSink::stop;
base_sink_class->render = QGstVideoRendererSink::render; base_sink_class->render = QGstVideoRendererSink::render;
GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class); GstElementClass *element_class = reinterpret_cast<GstElementClass *>(g_class);
@@ -578,20 +510,17 @@ gboolean QGstVideoRendererSink::propose_allocation(GstBaseSink *base, GstQuery *
return sink->delegate->proposeAllocation(query); return sink->delegate->proposeAllocation(query);
} }
GstFlowReturn QGstVideoRendererSink::preroll(GstBaseSink *base, GstBuffer *buffer) gboolean QGstVideoRendererSink::stop(GstBaseSink *base)
{ {
VO_SINK(base); VO_SINK(base);
sink->delegate->stop();
gboolean showPreroll = true; // "show-preroll-frame" property is true by default return TRUE;
g_object_get(G_OBJECT(base), "show-preroll-frame", &showPreroll, NULL);
return sink->delegate->render(buffer, showPreroll); // display frame
} }
GstFlowReturn QGstVideoRendererSink::render(GstBaseSink *base, GstBuffer *buffer) GstFlowReturn QGstVideoRendererSink::render(GstBaseSink *base, GstBuffer *buffer)
{ {
VO_SINK(base); VO_SINK(base);
return sink->delegate->render(buffer, true); return sink->delegate->render(buffer);
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@@ -98,14 +98,10 @@ public:
void stop(); void stop();
bool proposeAllocation(GstQuery *query); bool proposeAllocation(GstQuery *query);
void flush(); GstFlowReturn render(GstBuffer *buffer);
GstFlowReturn render(GstBuffer *buffer, bool show);
bool event(QEvent *event); bool event(QEvent *event);
static void handleShowPrerollChange(GObject *o, GParamSpec *p, gpointer d);
private slots: private slots:
bool handleEvent(QMutexLocker *locker); bool handleEvent(QMutexLocker *locker);
void updateSupportedFormats(); void updateSupportedFormats();
@@ -126,11 +122,10 @@ private:
GstCaps *m_surfaceCaps; GstCaps *m_surfaceCaps;
GstCaps *m_startCaps; GstCaps *m_startCaps;
GstBuffer *m_lastBuffer; GstBuffer *m_renderBuffer;
bool m_notified; bool m_notified;
bool m_stop; bool m_stop;
bool m_render;
bool m_flush; bool m_flush;
}; };
@@ -156,7 +151,8 @@ private:
static gboolean propose_allocation(GstBaseSink *sink, GstQuery *query); static gboolean propose_allocation(GstBaseSink *sink, GstQuery *query);
static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); static gboolean stop(GstBaseSink *sink);
static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer);
private: private: