1*4882a593SmuzhiyunFrom f587861bbe12ad0b10370f835592746aafedbf56 Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Mingke Wang <mingke.wang@freescale.com>
3*4882a593SmuzhiyunDate: Thu, 19 Mar 2015 14:17:10 +0800
4*4882a593SmuzhiyunSubject: [PATCH 2/4] ssaparse: enhance SSA text lines parsing.
5*4882a593Smuzhiyun
6*4882a593Smuzhiyunsome parser will pass in the original ssa text line which starts with "Dialog:"
7*4882a593Smuzhiyunand there's are maybe multiple Dialog lines in one input buffer.
8*4882a593Smuzhiyun
9*4882a593SmuzhiyunUpstream-Status: Submitted [https://bugzilla.gnome.org/show_bug.cgi?id=747496]
10*4882a593Smuzhiyun
11*4882a593SmuzhiyunSigned-off-by: Mingke Wang <mingke.wang@freescale.com>
12*4882a593Smuzhiyun---
13*4882a593Smuzhiyun gst/subparse/gstssaparse.c | 150 +++++++++++++++++++++++++++++++++----
14*4882a593Smuzhiyun 1 file changed, 134 insertions(+), 16 deletions(-)
15*4882a593Smuzhiyun mode change 100644 => 100755 gst/subparse/gstssaparse.c
16*4882a593Smuzhiyun
17*4882a593Smuzhiyundiff --git a/gst/subparse/gstssaparse.c b/gst/subparse/gstssaparse.c
18*4882a593Smuzhiyunold mode 100644
19*4882a593Smuzhiyunnew mode 100755
20*4882a593Smuzhiyunindex c849c08..4b9636c
21*4882a593Smuzhiyun--- a/gst/subparse/gstssaparse.c
22*4882a593Smuzhiyun+++ b/gst/subparse/gstssaparse.c
23*4882a593Smuzhiyun@@ -262,6 +262,7 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
24*4882a593Smuzhiyun  * gst_ssa_parse_push_line:
25*4882a593Smuzhiyun  * @parse: caller element
26*4882a593Smuzhiyun  * @txt: text to push
27*4882a593Smuzhiyun+ * @size: text size need to be parse
28*4882a593Smuzhiyun  * @start: timestamp for the buffer
29*4882a593Smuzhiyun  * @duration: duration for the buffer
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun@@ -271,27 +272,133 @@ gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt)
32*4882a593Smuzhiyun  * Returns: result of the push of the created buffer
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun static GstFlowReturn
35*4882a593Smuzhiyun-gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
36*4882a593Smuzhiyun+gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt, gint size,
37*4882a593Smuzhiyun     GstClockTime start, GstClockTime duration)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun   GstFlowReturn ret;
40*4882a593Smuzhiyun   GstBuffer *buf;
41*4882a593Smuzhiyun-  gchar *t, *escaped;
42*4882a593Smuzhiyun+  gchar *t, *text, *p, *escaped, *p_start, *p_end;
43*4882a593Smuzhiyun   gint num, i, len;
44*4882a593Smuzhiyun+  GstClockTime start_time = G_MAXUINT64, end_time = 0;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun-  num = atoi (txt);
47*4882a593Smuzhiyun-  GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
48*4882a593Smuzhiyun-      num, GST_TIME_ARGS (start));
49*4882a593Smuzhiyun-
50*4882a593Smuzhiyun-  /* skip all non-text fields before the actual text */
51*4882a593Smuzhiyun+  p = text = g_malloc(size + 1);
52*4882a593Smuzhiyun+  *p = '\0';
53*4882a593Smuzhiyun   t = txt;
54*4882a593Smuzhiyun-  for (i = 0; i < 8; ++i) {
55*4882a593Smuzhiyun-    t = strchr (t, ',');
56*4882a593Smuzhiyun+
57*4882a593Smuzhiyun+  /* there are may have multiple dialogue lines at a time */
58*4882a593Smuzhiyun+  while (*t) {
59*4882a593Smuzhiyun+    /* ignore leading white space characters */
60*4882a593Smuzhiyun+    while (isspace(*t))
61*4882a593Smuzhiyun+      t++;
62*4882a593Smuzhiyun+
63*4882a593Smuzhiyun+    /* ignore Format: and Style: lines */
64*4882a593Smuzhiyun+    if (strncmp(t, "Format:", 7) == 0 || strncmp(t, "Style:", 6) == 0) {
65*4882a593Smuzhiyun+      while (*t != '\0' && *t != '\n') {
66*4882a593Smuzhiyun+        t++;
67*4882a593Smuzhiyun+      }
68*4882a593Smuzhiyun+    }
69*4882a593Smuzhiyun+
70*4882a593Smuzhiyun+    if (*t == '\0')
71*4882a593Smuzhiyun+      break;
72*4882a593Smuzhiyun+
73*4882a593Smuzhiyun+    /* continue with next line */
74*4882a593Smuzhiyun+    if (*t == '\n') {
75*4882a593Smuzhiyun+      t++;
76*4882a593Smuzhiyun+      continue;
77*4882a593Smuzhiyun+    }
78*4882a593Smuzhiyun+
79*4882a593Smuzhiyun+    if(strncmp(t, "Dialogue:", 9) != 0) {
80*4882a593Smuzhiyun+      /* not started with "Dialogue:", it must be a line trimmed by demuxer */
81*4882a593Smuzhiyun+      num = atoi (t);
82*4882a593Smuzhiyun+      GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT,
83*4882a593Smuzhiyun+          num, GST_TIME_ARGS (start));
84*4882a593Smuzhiyun+
85*4882a593Smuzhiyun+      /* skip all non-text fields before the actual text */
86*4882a593Smuzhiyun+      for (i = 0; i < 8; ++i) {
87*4882a593Smuzhiyun+        t = strchr (t, ',');
88*4882a593Smuzhiyun+        if (t == NULL)
89*4882a593Smuzhiyun+          break;
90*4882a593Smuzhiyun+        ++t;
91*4882a593Smuzhiyun+      }
92*4882a593Smuzhiyun+    } else {
93*4882a593Smuzhiyun+      /* started with "Dialogue:", update timestamp and duration */
94*4882a593Smuzhiyun+      /* time format are like Dialog:Mark,0:00:01.02,0:00:03.04,xx,xxx,... */
95*4882a593Smuzhiyun+      guint hour, min, sec, msec, len;
96*4882a593Smuzhiyun+      GstClockTime tmp;
97*4882a593Smuzhiyun+      gchar t_str[12] = {0};
98*4882a593Smuzhiyun+
99*4882a593Smuzhiyun+      /* find the first ',' */
100*4882a593Smuzhiyun+      p_start = strchr (t, ',');
101*4882a593Smuzhiyun+      if (p_start)
102*4882a593Smuzhiyun+        p_end = strchr (++p_start, ',');
103*4882a593Smuzhiyun+
104*4882a593Smuzhiyun+      if (p_start && p_end) {
105*4882a593Smuzhiyun+        /* copy text between first ',' and second ',' */
106*4882a593Smuzhiyun+        strncpy(t_str, p_start, p_end - p_start);
107*4882a593Smuzhiyun+        if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
108*4882a593Smuzhiyun+          tmp = ((hour*3600) + (min*60) + sec) * GST_SECOND + msec*GST_MSECOND;
109*4882a593Smuzhiyun+          GST_DEBUG_OBJECT (parse, "Get start time:%02d:%02d:%02d:%03d\n",
110*4882a593Smuzhiyun+              hour, min, sec, msec);
111*4882a593Smuzhiyun+          if (start_time > tmp)
112*4882a593Smuzhiyun+            start_time = tmp;
113*4882a593Smuzhiyun+        } else {
114*4882a593Smuzhiyun+          GST_WARNING_OBJECT (parse,
115*4882a593Smuzhiyun+              "failed to parse ssa start timestamp string :%s", t_str);
116*4882a593Smuzhiyun+        }
117*4882a593Smuzhiyun+
118*4882a593Smuzhiyun+        p_start = p_end;
119*4882a593Smuzhiyun+        p_end = strchr (++p_start, ',');
120*4882a593Smuzhiyun+        if (p_end) {
121*4882a593Smuzhiyun+          /* copy text between second ',' and third ',' */
122*4882a593Smuzhiyun+          strncpy(t_str, p_start, p_end - p_start);
123*4882a593Smuzhiyun+          if (sscanf (t_str, "%u:%u:%u.%u", &hour, &min, &sec, &msec) == 4) {
124*4882a593Smuzhiyun+            tmp = ((hour*3600) + (min*60) + sec)*GST_SECOND + msec*GST_MSECOND;
125*4882a593Smuzhiyun+            GST_DEBUG_OBJECT(parse, "Get end time:%02d:%02d:%02d:%03d\n",
126*4882a593Smuzhiyun+                hour, min, sec, msec);
127*4882a593Smuzhiyun+            if (end_time < tmp)
128*4882a593Smuzhiyun+              end_time = tmp;
129*4882a593Smuzhiyun+          } else {
130*4882a593Smuzhiyun+            GST_WARNING_OBJECT (parse,
131*4882a593Smuzhiyun+                "failed to parse ssa end timestamp string :%s", t_str);
132*4882a593Smuzhiyun+          }
133*4882a593Smuzhiyun+        }
134*4882a593Smuzhiyun+      }
135*4882a593Smuzhiyun+
136*4882a593Smuzhiyun+      /* now skip all non-text fields before the actual text */
137*4882a593Smuzhiyun+      for (i = 0; i <= 8; ++i) {
138*4882a593Smuzhiyun+        t = strchr (t, ',');
139*4882a593Smuzhiyun+        if (t == NULL)
140*4882a593Smuzhiyun+          break;
141*4882a593Smuzhiyun+        ++t;
142*4882a593Smuzhiyun+      }
143*4882a593Smuzhiyun+    }
144*4882a593Smuzhiyun+
145*4882a593Smuzhiyun+    /* line end before expected number of ',', not a Dialogue line */
146*4882a593Smuzhiyun     if (t == NULL)
147*4882a593Smuzhiyun-      return GST_FLOW_ERROR;
148*4882a593Smuzhiyun-    ++t;
149*4882a593Smuzhiyun+      break;
150*4882a593Smuzhiyun+
151*4882a593Smuzhiyun+    /* if not the first line, and the last character of previous line is '\0',
152*4882a593Smuzhiyun+     * then replace it with '\N' */
153*4882a593Smuzhiyun+    if (p != text && *p == '\0') {
154*4882a593Smuzhiyun+      *p++ = '\\';
155*4882a593Smuzhiyun+      *p++ = 'N';
156*4882a593Smuzhiyun+    }
157*4882a593Smuzhiyun+
158*4882a593Smuzhiyun+    /* copy all actual text of this line */
159*4882a593Smuzhiyun+    while ((*t != '\0') && (*t != '\n'))
160*4882a593Smuzhiyun+      *p++ = *t++;
161*4882a593Smuzhiyun+
162*4882a593Smuzhiyun+    /* add a terminator at the end */
163*4882a593Smuzhiyun+    *p = '\0';
164*4882a593Smuzhiyun+  }
165*4882a593Smuzhiyun+
166*4882a593Smuzhiyun+  /* not valid text found in this buffer return OK to let caller unref buffer */
167*4882a593Smuzhiyun+  if (strlen(text) <= 0) {
168*4882a593Smuzhiyun+    GST_WARNING_OBJECT (parse, "Not valid text found in this buffer\n");
169*4882a593Smuzhiyun+    return GST_FLOW_ERROR;
170*4882a593Smuzhiyun   }
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun+  t = text;
173*4882a593Smuzhiyun   GST_LOG_OBJECT (parse, "Text : %s", t);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun   if (gst_ssa_parse_remove_override_codes (parse, t)) {
176*4882a593Smuzhiyun@@ -309,13 +416,22 @@ gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt,
177*4882a593Smuzhiyun   gst_buffer_fill (buf, 0, escaped, len + 1);
178*4882a593Smuzhiyun   gst_buffer_set_size (buf, len);
179*4882a593Smuzhiyun   g_free (escaped);
180*4882a593Smuzhiyun+  g_free(t);
181*4882a593Smuzhiyun+
182*4882a593Smuzhiyun+  if (start_time != G_MAXUINT64)
183*4882a593Smuzhiyun+    GST_BUFFER_TIMESTAMP (buf) = start_time;
184*4882a593Smuzhiyun+  else
185*4882a593Smuzhiyun+    GST_BUFFER_TIMESTAMP (buf) = start;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun-  GST_BUFFER_TIMESTAMP (buf) = start;
188*4882a593Smuzhiyun-  GST_BUFFER_DURATION (buf) = duration;
189*4882a593Smuzhiyun+  if (end_time > start_time)
190*4882a593Smuzhiyun+    GST_BUFFER_DURATION (buf) = end_time - start_time;
191*4882a593Smuzhiyun+  else
192*4882a593Smuzhiyun+    GST_BUFFER_DURATION (buf) = duration;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun   GST_LOG_OBJECT (parse, "Pushing buffer with timestamp %" GST_TIME_FORMAT
195*4882a593Smuzhiyun-      " and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
196*4882a593Smuzhiyun-      GST_TIME_ARGS (duration));
197*4882a593Smuzhiyun+      " and duration %" GST_TIME_FORMAT,
198*4882a593Smuzhiyun+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
199*4882a593Smuzhiyun+      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun   ret = gst_pad_push (parse->srcpad, buf);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun@@ -335,6 +451,7 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
204*4882a593Smuzhiyun   GstClockTime ts;
205*4882a593Smuzhiyun   gchar *txt;
206*4882a593Smuzhiyun   GstMapInfo map;
207*4882a593Smuzhiyun+  gint size;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun   if (G_UNLIKELY (!parse->framed))
210*4882a593Smuzhiyun     goto not_framed;
211*4882a593Smuzhiyun@@ -352,13 +469,14 @@ gst_ssa_parse_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buf)
212*4882a593Smuzhiyun   /* make double-sure it's 0-terminated and all */
213*4882a593Smuzhiyun   gst_buffer_map (buf, &map, GST_MAP_READ);
214*4882a593Smuzhiyun   txt = g_strndup ((gchar *) map.data, map.size);
215*4882a593Smuzhiyun+  size = map.size;
216*4882a593Smuzhiyun   gst_buffer_unmap (buf, &map);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun   if (txt == NULL)
219*4882a593Smuzhiyun     goto empty_text;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun   ts = GST_BUFFER_TIMESTAMP (buf);
222*4882a593Smuzhiyun-  ret = gst_ssa_parse_push_line (parse, txt, ts, GST_BUFFER_DURATION (buf));
223*4882a593Smuzhiyun+  ret = gst_ssa_parse_push_line (parse, txt, size, ts, GST_BUFFER_DURATION (buf));
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun   if (ret != GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (ts)) {
226*4882a593Smuzhiyun     GstSegment segment;
227*4882a593Smuzhiyun--
228*4882a593Smuzhiyun2.28.0
229*4882a593Smuzhiyun
230