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