]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core-contrib.git/blob
abca62a49145efe15b037c14429e72827eb0e5af
[thirdparty/openembedded/openembedded-core-contrib.git] /
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.
5
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.
8
9 Upstream-Status: Submitted [https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/178]
10
11 Signed-off-by: Mingke Wang <mingke.wang@freescale.com>
12 ---
13 gst/subparse/gstssaparse.c | 150 +++++++++++++++++++++++++++++++++----
14 1 file changed, 134 insertions(+), 16 deletions(-)
15 mode change 100644 => 100755 gst/subparse/gstssaparse.c
16
17 diff --git a/gst/subparse/gstssaparse.c b/gst/subparse/gstssaparse.c
18 old mode 100644
19 new mode 100755
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
26 * @txt: text to push
27 + * @size: text size need to be parse
28 * @start: timestamp for the buffer
29 * @duration: duration for the buffer
30 *
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
33 */
34 static GstFlowReturn
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)
38 {
39 GstFlowReturn ret;
40 GstBuffer *buf;
41 - gchar *t, *escaped;
42 + gchar *t, *text, *p, *escaped, *p_start, *p_end;
43 gint num, i, len;
44 + GstClockTime start_time = G_MAXUINT64, end_time = 0;
45
46 - num = atoi (txt);
47 - GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
48 - num, GST_TIME_ARGS (start));
49 -
50 - /* skip all non-text fields before the actual text */
51 + p = text = g_malloc(size + 1);
52 + *p = '\0';
53 t = txt;
54 - for (i = 0; i < 8; ++i) {
55 - t = strchr (t, ',');
56 +
57 + /* there are may have multiple dialogue lines at a time */
58 + while (*t) {
59 + /* ignore leading white space characters */
60 + while (isspace(*t))
61 + t++;
62 +
63 + /* ignore Format: and Style: lines */
64 + if (strncmp(t, "Format:", 7) == 0 || strncmp(t, "Style:", 6) == 0) {
65 + while (*t != '\0' && *t != '\n') {
66 + t++;
67 + }
68 + }
69 +
70 + if (*t == '\0')
71 + break;
72 +
73 + /* continue with next line */
74 + if (*t == '\n') {
75 + t++;
76 + continue;
77 + }
78 +
79 + if(strncmp(t, "Dialogue:", 9) != 0) {
80 + /* not started with "Dialogue:", it must be a line trimmed by demuxer */
81 + num = atoi (t);
82 + GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
83 + num, GST_TIME_ARGS (start));
84 +
85 + /* skip all non-text fields before the actual text */
86 + for (i = 0; i < 8; ++i) {
87 + t = strchr (t, ',');
88 + if (t == NULL)
89 + break;
90 + ++t;
91 + }
92 + } else {
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;
96 + GstClockTime tmp;
97 + gchar t_str[12] = {0};
98 +
99 + /* find the first ',' */
100 + p_start = strchr (t, ',');
101 + if (p_start)
102 + p_end = strchr (++p_start, ',');
103 +
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)
112 + start_time = tmp;
113 + } else {
114 + GST_WARNING_OBJECT (parse,
115 + "failed to parse ssa start timestamp string :%s", t_str);
116 + }
117 +
118 + p_start = p_end;
119 + p_end = strchr (++p_start, ',');
120 + if (p_end) {
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)
128 + end_time = tmp;
129 + } else {
130 + GST_WARNING_OBJECT (parse,
131 + "failed to parse ssa end timestamp string :%s", t_str);
132 + }
133 + }
134 + }
135 +
136 + /* now skip all non-text fields before the actual text */
137 + for (i = 0; i <= 8; ++i) {
138 + t = strchr (t, ',');
139 + if (t == NULL)
140 + break;
141 + ++t;
142 + }
143 + }
144 +
145 + /* line end before expected number of ',', not a Dialogue line */
146 if (t == NULL)
147 - return GST_FLOW_ERROR;
148 - ++t;
149 + break;
150 +
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') {
154 + *p++ = '\\';
155 + *p++ = 'N';
156 + }
157 +
158 + /* copy all actual text of this line */
159 + while ((*t != '\0') && (*t != '\n'))
160 + *p++ = *t++;
161 +
162 + /* add a terminator at the end */
163 + *p = '\0';
164 + }
165 +
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;
170 }
171
172 + t = text;
173 GST_LOG_OBJECT (parse, "Text : %s", t);
174
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);
179 g_free (escaped);
180 + g_free(t);
181 +
182 + if (start_time != G_MAXUINT64)
183 + GST_BUFFER_TIMESTAMP (buf) = start_time;
184 + else
185 + GST_BUFFER_TIMESTAMP (buf) = start;
186
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;
191 + else
192 + GST_BUFFER_DURATION (buf) = duration;
193
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)));
200
201 ret = gst_pad_push (parse->srcpad, buf);
202
203 @@ -343,6 +459,7 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
204 GstClockTime ts;
205 gchar *txt;
206 GstMapInfo map;
207 + gint size;
208
209 if (G_UNLIKELY (!parse->framed))
210 goto not_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);
215 + size = map.size;
216 gst_buffer_unmap (buf, &map);
217
218 if (txt == NULL)
219 goto empty_text;
220
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));
224
225 if (ret != GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (ts)) {
226 GstSegment segment;