1 From 918c96b24d10f61b7455b4cef3bab490849d0d77 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://bugzilla.gnome.org/show_bug.cgi?id=747496]
11 Signed-off-by: Mingke Wang <mingke.wang@freescale.com>
14 gst/subparse/gstssaparse.c | 150 ++++++++++++++++++++++++++++++++++++++++-----
15 1 file changed, 134 insertions(+), 16 deletions(-)
16 mode change 100644 => 100755 gst/subparse/gstssaparse.c
18 diff --git a/gst/subparse/gstssaparse.c b/gst/subparse/gstssaparse.c
21 index c849c08..4b9636c
22 --- a/gst/subparse/gstssaparse.c
23 +++ b/gst/subparse/gstssaparse.c
24 @@ -262,6 +262,7 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
25 * gst_ssa_parse_push_line:
26 * @parse: caller element
28 + * @size: text size need to be parse
29 * @start: timestamp for the buffer
30 * @duration: duration for the buffer
32 @@ -271,27 +272,133 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
33 * Returns: result of the push of the created buffer
36 -gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
37 +gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt, gint size,
38 GstClockTime start, GstClockTime duration)
43 + gchar *t, *text, *p, *escaped, *p_start, *p_end;
45 + GstClockTime start_time = G_MAXUINT64, end_time = 0;
48 - GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
49 - num, GST_TIME_ARGS (start));
51 - /* skip all non-text fields before the actual text */
52 + p = text = g_malloc(size + 1);
55 - for (i = 0; i < 8; ++i) {
56 - t = strchr (t, ',');
58 + /* there are may have multiple dialogue lines at a time */
60 + /* ignore leading white space characters */
64 + /* ignore Format: and Style: lines */
65 + if (strncmp(t, "Format:", 7) == 0 || strncmp(t, "Style:", 6) == 0) {
66 + while (*t != '\0' && *t != '\n') {
74 + /* continue with next line */
80 + if(strncmp(t, "Dialogue:", 9) != 0) {
81 + /* not started with "Dialogue:", it must be a line trimmed by demuxer */
83 + GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
84 + num, GST_TIME_ARGS (start));
86 + /* skip all non-text fields before the actual text */
87 + for (i = 0; i < 8; ++i) {
88 + t = strchr (t, ',');
94 + /* started with "Dialogue:", update timestamp and duration */
95 + /* time format are like Dialog:Mark,0:00:01.02,0:00:03.04,xx,xxx,... */
96 + guint hour, min, sec, msec, len;
98 + gchar t_str[12] = {0};
100 + /* find the first ',' */
101 + p_start = strchr (t, ',');
103 + p_end = strchr (++p_start, ',');
105 + if (p_start && p_end) {
106 + /* copy text between first ',' and second ',' */
107 + strncpy(t_str, p_start, p_end - p_start);
108 + if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
109 + tmp = ((hour*3600) + (min*60) + sec) * GST_SECOND + msec*GST_MSECOND;
110 + GST_DEBUG_OBJECT (parse, "Get start time:%02d:%02d:%02d:%03d\n",
111 + hour, min, sec, msec);
112 + if (start_time > tmp)
115 + GST_WARNING_OBJECT (parse,
116 + "failed to parse ssa start timestamp string :%s", t_str);
120 + p_end = strchr (++p_start, ',');
122 + /* copy text between second ',' and third ',' */
123 + strncpy(t_str, p_start, p_end - p_start);
124 + if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
125 + tmp = ((hour*3600) + (min*60) + sec)*GST_SECOND + msec*GST_MSECOND;
126 + GST_DEBUG_OBJECT(parse, "Get end time:%02d:%02d:%02d:%03d\n",
127 + hour, min, sec, msec);
128 + if (end_time < tmp)
131 + GST_WARNING_OBJECT (parse,
132 + "failed to parse ssa end timestamp string :%s", t_str);
137 + /* now skip all non-text fields before the actual text */
138 + for (i = 0; i <= 8; ++i) {
139 + t = strchr (t, ',');
146 + /* line end before expected number of ',', not a Dialogue line */
148 - return GST_FLOW_ERROR;
152 + /* if not the first line, and the last character of previous line is '\0',
153 + * then replace it with '\N' */
154 + if (p != text && *p == '\0') {
159 + /* copy all actual text of this line */
160 + while ((*t != '\0') && (*t != '\n'))
163 + /* add a terminator at the end */
167 + /* not valid text found in this buffer return OK to let caller unref buffer */
168 + if (strlen(text) <= 0) {
169 + GST_WARNING_OBJECT (parse, "Not valid text found in this buffer\n");
170 + return GST_FLOW_ERROR;
174 GST_LOG_OBJECT (parse, "Text : %s", t);
176 if (gst_ssa_parse_remove_override_codes (parse, t)) {
177 @@ -309,13 +416,22 @@ gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
178 gst_buffer_fill (buf, 0, escaped, len + 1);
179 gst_buffer_set_size (buf, len);
183 + if (start_time != G_MAXUINT64)
184 + GST_BUFFER_TIMESTAMP (buf) = start_time;
186 + GST_BUFFER_TIMESTAMP (buf) = start;
188 - GST_BUFFER_TIMESTAMP (buf) = start;
189 - GST_BUFFER_DURATION (buf) = duration;
190 + if (end_time > start_time)
191 + GST_BUFFER_DURATION (buf) = end_time - start_time;
193 + GST_BUFFER_DURATION (buf) = duration;
195 GST_LOG_OBJECT (parse, "Pushing buffer with timestamp %" GST_TIME_FORMAT
196 - " and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
197 - GST_TIME_ARGS (duration));
198 + " and duration %" GST_TIME_FORMAT,
199 + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
200 + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
202 ret = gst_pad_push (parse->srcpad, buf);
204 @@ -335,6 +451,7 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
210 if (G_UNLIKELY (!parse->framed))
212 @@ -352,13 +469,14 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
213 /* make double-sure it's 0-terminated and all */
214 gst_buffer_map (buf, &map, GST_MAP_READ);
215 txt = g_strndup ((gchar *) map.data, map.size);
217 gst_buffer_unmap (buf, &map);
222 ts = GST_BUFFER_TIMESTAMP (buf);
223 - ret = gst_ssa_parse_push_line (parse, txt, ts, GST_BUFFER_DURATION (buf));
224 + ret = gst_ssa_parse_push_line (parse, txt, size, ts, GST_BUFFER_DURATION (buf));
226 if (ret != GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (ts)) {