1 From 1cd4da7d4739dcfa2b66899ef8a49e5ed88d41b8 Mon Sep 17 00:00:00 2001
2 From: Mingke Wang <mingke.wang@freescale.com>
3 Date: Thu, 19 Mar 2015 14:17:10 +0800
4 Subject: [PATCH] ssaparse: enhance SSA text lines parsing.
6 some parser will pass in the original ssa text line which starts with "Dialog:"
7 and there's are maybe multiple Dialog lines in one input buffer.
9 Upstream-Status: Submitted [https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/178]
11 Signed-off-by: Mingke Wang <mingke.wang@freescale.com>
13 gst/subparse/gstssaparse.c | 150 +++++++++++++++++++++++++++++++++----
14 1 file changed, 134 insertions(+), 16 deletions(-)
15 mode change 100644 => 100755 gst/subparse/gstssaparse.c
17 diff --git a/gst/subparse/gstssaparse.c b/gst/subparse/gstssaparse.c
20 index 42fbb42..2dab51c
21 --- a/gst/subparse/gstssaparse.c
22 +++ b/gst/subparse/gstssaparse.c
23 @@ -270,6 +270,7 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
24 * gst_ssa_parse_push_line:
25 * @parse: caller element
27 + * @size: text size need to be parse
28 * @start: timestamp for the buffer
29 * @duration: duration for the buffer
31 @@ -279,27 +280,133 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
32 * Returns: result of the push of the created buffer
35 -gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
36 +gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt, gint size,
37 GstClockTime start, GstClockTime duration)
42 + gchar *t, *text, *p, *escaped, *p_start, *p_end;
44 + GstClockTime start_time = G_MAXUINT64, end_time = 0;
47 - GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
48 - num, GST_TIME_ARGS (start));
50 - /* skip all non-text fields before the actual text */
51 + p = text = g_malloc(size + 1);
54 - for (i = 0; i < 8; ++i) {
55 - t = strchr (t, ',');
57 + /* there are may have multiple dialogue lines at a time */
59 + /* ignore leading white space characters */
63 + /* ignore Format: and Style: lines */
64 + if (strncmp(t, "Format:", 7) == 0 || strncmp(t, "Style:", 6) == 0) {
65 + while (*t != '\0' && *t != '\n') {
73 + /* continue with next line */
79 + if(strncmp(t, "Dialogue:", 9) != 0) {
80 + /* not started with "Dialogue:", it must be a line trimmed by demuxer */
82 + GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
83 + num, GST_TIME_ARGS (start));
85 + /* skip all non-text fields before the actual text */
86 + for (i = 0; i < 8; ++i) {
87 + t = strchr (t, ',');
93 + /* started with "Dialogue:", update timestamp and duration */
94 + /* time format are like Dialog:Mark,0:00:01.02,0:00:03.04,xx,xxx,... */
95 + guint hour, min, sec, msec, len;
97 + gchar t_str[12] = {0};
99 + /* find the first ',' */
100 + p_start = strchr (t, ',');
102 + p_end = strchr (++p_start, ',');
104 + if (p_start && p_end) {
105 + /* copy text between first ',' and second ',' */
106 + strncpy(t_str, p_start, p_end - p_start);
107 + if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
108 + tmp = ((hour*3600) + (min*60) + sec) * GST_SECOND + msec*GST_MSECOND;
109 + GST_DEBUG_OBJECT (parse, "Get start time:%02d:%02d:%02d:%03d\n",
110 + hour, min, sec, msec);
111 + if (start_time > tmp)
114 + GST_WARNING_OBJECT (parse,
115 + "failed to parse ssa start timestamp string :%s", t_str);
119 + p_end = strchr (++p_start, ',');
121 + /* copy text between second ',' and third ',' */
122 + strncpy(t_str, p_start, p_end - p_start);
123 + if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
124 + tmp = ((hour*3600) + (min*60) + sec)*GST_SECOND + msec*GST_MSECOND;
125 + GST_DEBUG_OBJECT(parse, "Get end time:%02d:%02d:%02d:%03d\n",
126 + hour, min, sec, msec);
127 + if (end_time < tmp)
130 + GST_WARNING_OBJECT (parse,
131 + "failed to parse ssa end timestamp string :%s", t_str);
136 + /* now skip all non-text fields before the actual text */
137 + for (i = 0; i <= 8; ++i) {
138 + t = strchr (t, ',');
145 + /* line end before expected number of ',', not a Dialogue line */
147 - return GST_FLOW_ERROR;
151 + /* if not the first line, and the last character of previous line is '\0',
152 + * then replace it with '\N' */
153 + if (p != text && *p == '\0') {
158 + /* copy all actual text of this line */
159 + while ((*t != '\0') && (*t != '\n'))
162 + /* add a terminator at the end */
166 + /* not valid text found in this buffer return OK to let caller unref buffer */
167 + if (strlen(text) <= 0) {
168 + GST_WARNING_OBJECT (parse, "Not valid text found in this buffer\n");
169 + return GST_FLOW_ERROR;
173 GST_LOG_OBJECT (parse, "Text : %s", t);
175 if (gst_ssa_parse_remove_override_codes (parse, t)) {
176 @@ -317,13 +424,22 @@ gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
177 gst_buffer_fill (buf, 0, escaped, len + 1);
178 gst_buffer_set_size (buf, len);
182 + if (start_time != G_MAXUINT64)
183 + GST_BUFFER_TIMESTAMP (buf) = start_time;
185 + GST_BUFFER_TIMESTAMP (buf) = start;
187 - GST_BUFFER_TIMESTAMP (buf) = start;
188 - GST_BUFFER_DURATION (buf) = duration;
189 + if (end_time > start_time)
190 + GST_BUFFER_DURATION (buf) = end_time - start_time;
192 + GST_BUFFER_DURATION (buf) = duration;
194 GST_LOG_OBJECT (parse, "Pushing buffer with timestamp %" GST_TIME_FORMAT
195 - " and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
196 - GST_TIME_ARGS (duration));
197 + " and duration %" GST_TIME_FORMAT,
198 + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
199 + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
201 ret = gst_pad_push (parse->srcpad, buf);
203 @@ -343,6 +459,7 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
209 if (G_UNLIKELY (!parse->framed))
211 @@ -360,13 +477,14 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
212 /* make double-sure it's 0-terminated and all */
213 gst_buffer_map (buf, &map, GST_MAP_READ);
214 txt = g_strndup ((gchar *) map.data, map.size);
216 gst_buffer_unmap (buf, &map);
221 ts = GST_BUFFER_TIMESTAMP (buf);
222 - ret = gst_ssa_parse_push_line (parse, txt, ts, GST_BUFFER_DURATION (buf));
223 + ret = gst_ssa_parse_push_line (parse, txt, size, ts, GST_BUFFER_DURATION (buf));
225 if (ret != GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (ts)) {