[gst-cvs] gst-plugins-bad: assrender: Synchronize subtitle buffers with the video
Sebastian Dröge
slomo at kemper.freedesktop.org
Wed Nov 4 03:52:26 PST 2009
Module: gst-plugins-bad
Branch: master
Commit: 3b2ab1299cbfd9079a0b90cfde3041b9a08d3dd7
URL: http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=3b2ab1299cbfd9079a0b90cfde3041b9a08d3dd7
Author: Sebastian Dröge <sebastian.droege at collabora.co.uk>
Date: Wed Nov 4 12:50:18 2009 +0100
assrender: Synchronize subtitle buffers with the video
Fixes bug #600662.
---
ext/assrender/gstassrender.c | 118 +++++++++++++++++++++++++++++++++++++-----
ext/assrender/gstassrender.h | 5 ++
2 files changed, 109 insertions(+), 14 deletions(-)
diff --git a/ext/assrender/gstassrender.c b/ext/assrender/gstassrender.c
index a7b926b..40fd03b 100644
--- a/ext/assrender/gstassrender.c
+++ b/ext/assrender/gstassrender.c
@@ -68,6 +68,9 @@ static void gst_assrender_get_property (GObject * object, guint prop_id,
static void gst_assrender_finalize (GObject * object);
+static GstStateChangeReturn gst_assrender_change_state (GstElement * element,
+ GstStateChange transition);
+
GST_BOILERPLATE (Gstassrender, gst_assrender, GstElement, GST_TYPE_ELEMENT);
static GstCaps *gst_assrender_getcaps (GstPad * pad);
@@ -122,6 +125,9 @@ gst_assrender_class_init (GstassrenderClass * klass)
g_param_spec_boolean ("embeddedfonts", "Use embedded fonts",
"Extract and use fonts embedded in the stream", TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_assrender_change_state);
}
static void
@@ -160,6 +166,9 @@ gst_assrender_init (Gstassrender * render, GstassrenderClass * gclass)
render->width = 0;
render->height = 0;
+ render->subtitle_mutex = g_mutex_new ();
+ render->subtitle_cond = g_cond_new ();
+
render->renderer_init_ok = FALSE;
render->track_init_ok = FALSE;
render->enable = TRUE;
@@ -187,6 +196,12 @@ gst_assrender_finalize (GObject * object)
{
Gstassrender *render = GST_ASSRENDER (object);
+ if (render->subtitle_mutex)
+ g_mutex_free (render->subtitle_mutex);
+
+ if (render->subtitle_cond)
+ g_cond_free (render->subtitle_cond);
+
if (render->ass_track) {
ass_free_track (render->ass_track);
}
@@ -240,6 +255,49 @@ gst_assrender_get_property (GObject * object, guint prop_id,
}
}
+static GstStateChangeReturn
+gst_assrender_change_state (GstElement * element, GstStateChange transition)
+{
+ Gstassrender *render = GST_ASSRENDER (element);
+ GstStateChangeReturn ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ default:
+ break;
+
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ g_mutex_lock (render->subtitle_mutex);
+ if (render->subtitle_pending)
+ gst_buffer_unref (render->subtitle_pending);
+ render->subtitle_pending = NULL;
+ g_cond_signal (render->subtitle_cond);
+ g_mutex_unlock (render->subtitle_mutex);
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ if (render->ass_track)
+ ass_free_track (render->ass_track);
+ render->ass_track = NULL;
+ render->track_init_ok = FALSE;
+ render->renderer_init_ok = FALSE;
+ break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ default:
+ break;
+ }
+
+
+ return ret;
+}
+
static GstCaps *
gst_assrender_getcaps (GstPad * pad)
{
@@ -388,6 +446,23 @@ gst_assrender_setcaps_text (GstPad * pad, GstCaps * caps)
return ret;
}
+
+static void
+gst_assrender_process_text (Gstassrender * render, GstBuffer * buffer)
+{
+ char *data = (gchar *) GST_BUFFER_DATA (buffer);
+ guint size = GST_BUFFER_SIZE (buffer);
+ double pts_start, pts_end;
+
+ pts_start = GST_BUFFER_TIMESTAMP (buffer);
+ pts_start /= GST_MSECOND;
+ pts_end = GST_BUFFER_DURATION (buffer);
+ pts_end /= GST_MSECOND;
+
+ ass_process_chunk (render->ass_track, data, size, pts_start, pts_end);
+ gst_buffer_unref (buffer);
+}
+
static GstFlowReturn
gst_assrender_chain_video (GstPad * pad, GstBuffer * buffer)
{
@@ -440,6 +515,23 @@ gst_assrender_chain_video (GstPad * pad, GstBuffer * buffer)
gst_segment_set_last_stop (&render->video_segment, GST_FORMAT_TIME,
clip_start);
+ g_mutex_lock (render->subtitle_mutex);
+ if (render->subtitle_pending) {
+ if (GST_BUFFER_TIMESTAMP (render->subtitle_pending) <=
+ GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)) {
+ gst_assrender_process_text (render, render->subtitle_pending);
+ render->subtitle_pending = NULL;
+ g_cond_signal (render->subtitle_cond);
+ } else if (GST_BUFFER_TIMESTAMP (render->subtitle_pending) +
+ GST_BUFFER_DURATION (render->subtitle_pending) <=
+ GST_BUFFER_TIMESTAMP (buffer)) {
+ gst_buffer_unref (render->subtitle_pending);
+ render->subtitle_pending = NULL;
+ g_cond_signal (render->subtitle_cond);
+ }
+ }
+ g_mutex_unlock (render->subtitle_mutex);
+
/* now start rendering subtitles, if all conditions are met */
if (render->renderer_init_ok && render->track_init_ok && render->enable) {
int counter;
@@ -516,27 +608,25 @@ gst_assrender_chain_text (GstPad * pad, GstBuffer * buffer)
{
GstFlowReturn ret = GST_FLOW_OK;
Gstassrender *render;
- gchar *data;
- guint size;
- double pts_start;
- double pts_end;
+ GstClockTime timestamp;
render = GST_ASSRENDER (GST_PAD_PARENT (pad));
- data = (gchar *) GST_BUFFER_DATA (buffer);
- size = GST_BUFFER_SIZE (buffer);
- pts_start = GST_BUFFER_TIMESTAMP (buffer);
- pts_start = pts_start / GST_MSECOND;
- pts_end = GST_BUFFER_DURATION (buffer);
- pts_end = pts_end / GST_MSECOND;
+ timestamp = GST_BUFFER_TIMESTAMP (buffer);
- ass_process_chunk (render->ass_track, data, size, pts_start, pts_end);
+ if (timestamp > render->video_segment.last_stop) {
+ g_assert (render->subtitle_pending == NULL);
+ g_mutex_lock (render->subtitle_mutex);
+ render->subtitle_pending = buffer;
+ g_cond_wait (render->subtitle_cond, render->subtitle_mutex);
+ g_mutex_unlock (render->subtitle_mutex);
+ } else {
+ gst_assrender_process_text (render, buffer);
+ }
GST_DEBUG_OBJECT (render,
"processed text packet with timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
-
- gst_buffer_unref (buffer);
+ GST_TIME_ARGS (timestamp));
return ret;
}
diff --git a/ext/assrender/gstassrender.h b/ext/assrender/gstassrender.h
index 39edd0a..04babcf 100644
--- a/ext/assrender/gstassrender.h
+++ b/ext/assrender/gstassrender.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Benjamin Schmitz <vortex at wolpzone.de>
+ * Copyright (c) 2009 Sebastian Dröge <sebastian.droege at collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
@@ -51,6 +52,10 @@ struct _Gstassrender
gint width, height;
+ GMutex *subtitle_mutex;
+ GCond *subtitle_cond;
+ GstBuffer *subtitle_pending;
+
ASS_Library *ass_library;
ASS_Renderer *ass_renderer;
ASS_Track *ass_track;
More information about the Gstreamer-commits
mailing list