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