1 |
luigiwalser |
1185974 |
From 948b87bf1514de55ee96575d204140eeec3a80a8 Mon Sep 17 00:00:00 2001 |
2 |
|
|
From: Jan Schmidt <jan@centricular.com> |
3 |
|
|
Date: Wed, 1 Feb 2017 14:25:32 +1100 |
4 |
|
|
Subject: [PATCH] psdemux: Rewrite PSM parsing using GstByteReader |
5 |
|
|
|
6 |
|
|
Avoid possible buffer overflows and ignore invalid PSM packets better |
7 |
|
|
by using GstByteReader. |
8 |
|
|
|
9 |
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=777957 |
10 |
|
|
--- |
11 |
|
|
gst/mpegdemux/Makefile.am | 2 +- |
12 |
|
|
gst/mpegdemux/gstmpegdemux.c | 322 ++++++++++++++++--------------------------- |
13 |
|
|
2 files changed, 117 insertions(+), 207 deletions(-) |
14 |
|
|
|
15 |
|
|
Index: gst-plugins-bad1.0-1.4.4/gst/mpegdemux/Makefile.am |
16 |
|
|
=================================================================== |
17 |
|
|
--- gst-plugins-bad1.0-1.4.4.orig/gst/mpegdemux/Makefile.am |
18 |
|
|
+++ gst-plugins-bad1.0-1.4.4/gst/mpegdemux/Makefile.am |
19 |
|
|
@@ -11,7 +11,7 @@ libgstmpegpsdemux_la_CFLAGS = \ |
20 |
|
|
libgstmpegpsdemux_la_LIBADD = \ |
21 |
|
|
$(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_API_VERSION) \ |
22 |
|
|
-lgstpbutils-$(GST_API_VERSION) \ |
23 |
|
|
- $(GST_BASE_LIBS) $(GST_LIBS) |
24 |
|
|
+ $(GST_BASE_LIBS) -lgstbase-$(GST_API_VERSION) $(GST_LIBS) |
25 |
|
|
libgstmpegpsdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) |
26 |
|
|
libgstmpegpsdemux_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) |
27 |
|
|
|
28 |
|
|
Index: gst-plugins-bad1.0-1.4.4/gst/mpegdemux/gstmpegdemux.c |
29 |
|
|
=================================================================== |
30 |
|
|
--- gst-plugins-bad1.0-1.4.4.orig/gst/mpegdemux/gstmpegdemux.c |
31 |
|
|
+++ gst-plugins-bad1.0-1.4.4/gst/mpegdemux/gstmpegdemux.c |
32 |
|
|
@@ -50,6 +50,7 @@ |
33 |
|
|
|
34 |
|
|
#include <gst/tag/tag.h> |
35 |
|
|
#include <gst/pbutils/pbutils.h> |
36 |
|
|
+#include <gst/base/gstbytereader.h> |
37 |
|
|
|
38 |
|
|
#include "gstmpegdefs.h" |
39 |
|
|
#include "gstmpegdemux.h" |
40 |
|
|
@@ -77,6 +78,34 @@ typedef enum |
41 |
|
|
|
42 |
|
|
#define ADAPTER_OFFSET_FLUSH(_bytes_) demux->adapter_offset += (_bytes_) |
43 |
|
|
|
44 |
|
|
+#if !GST_CHECK_VERSION(1, 6, 0) |
45 |
|
|
+static inline gboolean |
46 |
|
|
+gst_byte_reader_peek_sub_reader (GstByteReader * reader, |
47 |
|
|
+ GstByteReader * sub_reader, guint size) |
48 |
|
|
+{ |
49 |
|
|
+ g_return_val_if_fail (reader != NULL, FALSE); |
50 |
|
|
+ g_return_val_if_fail (sub_reader != NULL, FALSE); |
51 |
|
|
+ |
52 |
|
|
+ if (gst_byte_reader_get_remaining (reader) < size) |
53 |
|
|
+ return FALSE; |
54 |
|
|
+ |
55 |
|
|
+ sub_reader->data = reader->data + reader->byte; |
56 |
|
|
+ sub_reader->byte = 0; |
57 |
|
|
+ sub_reader->size = size; |
58 |
|
|
+ return TRUE; |
59 |
|
|
+} |
60 |
|
|
+ |
61 |
|
|
+static inline gboolean |
62 |
|
|
+gst_byte_reader_get_sub_reader (GstByteReader * reader, |
63 |
|
|
+ GstByteReader * sub_reader, guint size) |
64 |
|
|
+{ |
65 |
|
|
+ if (!gst_byte_reader_peek_sub_reader (reader, sub_reader, size)) |
66 |
|
|
+ return FALSE; |
67 |
|
|
+ gst_byte_reader_skip_unchecked (reader, size); |
68 |
|
|
+ return TRUE; |
69 |
|
|
+} |
70 |
|
|
+#endif |
71 |
|
|
+ |
72 |
|
|
GST_DEBUG_CATEGORY_STATIC (gstflupsdemux_debug); |
73 |
|
|
#define GST_CAT_DEFAULT (gstflupsdemux_debug) |
74 |
|
|
|
75 |
|
|
@@ -2029,42 +2058,48 @@ need_more_data: |
76 |
|
|
static GstFlowReturn |
77 |
|
|
gst_flups_demux_parse_psm (GstFluPSDemux * demux) |
78 |
|
|
{ |
79 |
|
|
- guint16 length = 0, info_length = 0, es_map_length = 0; |
80 |
|
|
+ guint16 psm_length, info_length = 0, es_map_length = 0; |
81 |
|
|
guint8 psm_version = 0; |
82 |
|
|
- const guint8 *data, *es_map_base; |
83 |
|
|
+ GstByteReader br; |
84 |
|
|
#ifndef GST_DISABLE_GST_DEBUG |
85 |
|
|
gboolean applicable; |
86 |
|
|
#endif |
87 |
|
|
|
88 |
|
|
+ /* Need at least 6 bytes for start code + length */ |
89 |
|
|
if (gst_adapter_available (demux->adapter) < 6) |
90 |
|
|
goto need_more_data; |
91 |
|
|
|
92 |
|
|
- /* start code + length */ |
93 |
|
|
- data = gst_adapter_map (demux->adapter, 6); |
94 |
|
|
+ { |
95 |
|
|
+ const guint8 *data; |
96 |
|
|
|
97 |
|
|
- /* skip start code */ |
98 |
|
|
- data += 4; |
99 |
|
|
+ /* start code + length */ |
100 |
|
|
+ data = gst_adapter_map (demux->adapter, 6); |
101 |
|
|
+ /* skip start code */ |
102 |
|
|
+ data += 4; |
103 |
|
|
+ psm_length = GST_READ_UINT16_BE (data); |
104 |
|
|
+ GST_DEBUG_OBJECT (demux, "PSM length %u", psm_length); |
105 |
|
|
|
106 |
|
|
- length = GST_READ_UINT16_BE (data); |
107 |
|
|
- GST_DEBUG_OBJECT (demux, "length %u", length); |
108 |
|
|
+ if (G_UNLIKELY (psm_length > 0x3FA)) |
109 |
|
|
+ goto psm_len_error; |
110 |
|
|
+ psm_length += 6; /* Add start code + size to length */ |
111 |
|
|
|
112 |
|
|
- if (G_UNLIKELY (length > 0x3FA)) |
113 |
|
|
- goto psm_len_error; |
114 |
|
|
+ gst_adapter_unmap (demux->adapter); |
115 |
|
|
|
116 |
|
|
- length += 6; |
117 |
|
|
+ if (gst_adapter_available (demux->adapter) < psm_length) |
118 |
|
|
+ goto need_more_data; |
119 |
|
|
|
120 |
|
|
- gst_adapter_unmap (demux->adapter); |
121 |
|
|
+ data = gst_adapter_map (demux->adapter, psm_length); |
122 |
|
|
|
123 |
|
|
- if (gst_adapter_available (demux->adapter) < length) |
124 |
|
|
- goto need_more_data; |
125 |
|
|
- |
126 |
|
|
- data = gst_adapter_map (demux->adapter, length); |
127 |
|
|
+ gst_byte_reader_init (&br, data, psm_length); |
128 |
|
|
+ } |
129 |
|
|
|
130 |
|
|
/* skip start code and length */ |
131 |
|
|
- data += 6; |
132 |
|
|
+ if (!gst_byte_reader_skip (&br, 6)) |
133 |
|
|
+ goto fail_invalid; |
134 |
|
|
|
135 |
|
|
/* Read PSM applicable bit together with version */ |
136 |
|
|
- psm_version = GST_READ_UINT8 (data); |
137 |
|
|
+ if (!gst_byte_reader_get_uint8 (&br, &psm_version)) |
138 |
|
|
+ goto fail_invalid; |
139 |
|
|
#ifndef GST_DISABLE_GST_DEBUG |
140 |
|
|
applicable = (psm_version & 0x80) >> 7; |
141 |
|
|
#endif |
142 |
|
|
@@ -2072,62 +2107,70 @@ gst_flups_demux_parse_psm (GstFluPSDemux |
143 |
|
|
GST_DEBUG_OBJECT (demux, "PSM version %u (applicable now %u)", psm_version, |
144 |
|
|
applicable); |
145 |
|
|
|
146 |
|
|
- /* Jump over version and marker bit */ |
147 |
|
|
- data += 2; |
148 |
|
|
+ /* Jump over the next byte (marker bit) */ |
149 |
|
|
+ if (!gst_byte_reader_skip (&br, 1)) |
150 |
|
|
+ goto fail_invalid; |
151 |
|
|
|
152 |
|
|
/* Read PS info length */ |
153 |
|
|
- info_length = GST_READ_UINT16_BE (data); |
154 |
|
|
- /* Cap it to PSM length - needed bytes for ES map length and CRC */ |
155 |
|
|
- info_length = MIN (length - 16, info_length); |
156 |
|
|
+ if (!gst_byte_reader_get_uint16_be (&br, &info_length)) |
157 |
|
|
+ goto fail_invalid; |
158 |
|
|
GST_DEBUG_OBJECT (demux, "PS info length %u bytes", info_length); |
159 |
|
|
- |
160 |
|
|
- /* Jump over that section */ |
161 |
|
|
- data += (2 + info_length); |
162 |
|
|
+ /* Skip the PS info, we don't use it */ |
163 |
|
|
+ if (!gst_byte_reader_skip (&br, info_length)) |
164 |
|
|
+ goto fail_invalid; |
165 |
|
|
|
166 |
|
|
/* Read ES map length */ |
167 |
|
|
- es_map_length = GST_READ_UINT16_BE (data); |
168 |
|
|
- /* Cap it to PSM remaining length - CRC */ |
169 |
|
|
- es_map_length = MIN (length - (16 + info_length), es_map_length); |
170 |
|
|
+ if (!gst_byte_reader_get_uint16_be (&br, &es_map_length)) |
171 |
|
|
+ goto fail_invalid; |
172 |
|
|
GST_DEBUG_OBJECT (demux, "ES map length %u bytes", es_map_length); |
173 |
|
|
|
174 |
|
|
- /* Jump over the size */ |
175 |
|
|
- data += 2; |
176 |
|
|
- |
177 |
|
|
/* Now read the ES map */ |
178 |
|
|
- es_map_base = data; |
179 |
|
|
- while (es_map_base + 4 <= data + es_map_length) { |
180 |
|
|
- guint8 stream_type = 0, stream_id = 0; |
181 |
|
|
- guint16 stream_info_length = 0; |
182 |
|
|
- |
183 |
|
|
- stream_type = GST_READ_UINT8 (es_map_base); |
184 |
|
|
- es_map_base++; |
185 |
|
|
- stream_id = GST_READ_UINT8 (es_map_base); |
186 |
|
|
- es_map_base++; |
187 |
|
|
- stream_info_length = GST_READ_UINT16_BE (es_map_base); |
188 |
|
|
- es_map_base += 2; |
189 |
|
|
- /* Cap stream_info_length */ |
190 |
|
|
- stream_info_length = MIN (data + es_map_length - es_map_base, |
191 |
|
|
- stream_info_length); |
192 |
|
|
- |
193 |
|
|
- GST_DEBUG_OBJECT (demux, "Stream type %02X with id %02X and %u bytes info", |
194 |
|
|
- stream_type, stream_id, stream_info_length); |
195 |
|
|
- if (G_LIKELY (stream_id != 0xbd)) |
196 |
|
|
- demux->psm[stream_id] = stream_type; |
197 |
|
|
- else { |
198 |
|
|
- /* Ignore stream type for private_stream_1 and discover it looking at |
199 |
|
|
- * the stream data. |
200 |
|
|
- * Fixes demuxing some clips with lpcm that was wrongly declared as |
201 |
|
|
- * mpeg audio */ |
202 |
|
|
- GST_DEBUG_OBJECT (demux, "stream type for private_stream_1 ignored"); |
203 |
|
|
+ { |
204 |
|
|
+ GstByteReader es_map_br; |
205 |
|
|
+ if (!gst_byte_reader_get_sub_reader (&br, &es_map_br, es_map_length)) |
206 |
|
|
+ goto fail_invalid; |
207 |
|
|
+ |
208 |
|
|
+ while (gst_byte_reader_get_remaining (&es_map_br) >= 4) { |
209 |
|
|
+ guint8 stream_type = 0, stream_id = 0; |
210 |
|
|
+ guint16 stream_info_length = 0; |
211 |
|
|
+ |
212 |
|
|
+ if (!gst_byte_reader_get_uint8 (&es_map_br, &stream_type) || |
213 |
|
|
+ !gst_byte_reader_get_uint8 (&es_map_br, &stream_id) || |
214 |
|
|
+ !gst_byte_reader_get_uint16_be (&es_map_br, &stream_info_length)) |
215 |
|
|
+ break; |
216 |
|
|
+ |
217 |
|
|
+ GST_DEBUG_OBJECT (demux, |
218 |
|
|
+ "Stream type %02X with id %02X and %u bytes info", stream_type, |
219 |
|
|
+ stream_id, stream_info_length); |
220 |
|
|
+ |
221 |
|
|
+ if (G_LIKELY (stream_id != 0xbd)) |
222 |
|
|
+ demux->psm[stream_id] = stream_type; |
223 |
|
|
+ else { |
224 |
|
|
+ /* Ignore stream type for private_stream_1 and discover it looking at |
225 |
|
|
+ * the stream data. |
226 |
|
|
+ * Fixes demuxing some clips with lpcm that was wrongly declared as |
227 |
|
|
+ * mpeg audio */ |
228 |
|
|
+ GST_DEBUG_OBJECT (demux, "stream type for private_stream_1 ignored"); |
229 |
|
|
+ } |
230 |
|
|
+ |
231 |
|
|
+ /* FIXME: We could use the descriptors instead of skipping them */ |
232 |
|
|
+ if (!gst_byte_reader_skip (&es_map_br, stream_info_length)) |
233 |
|
|
+ break; |
234 |
|
|
} |
235 |
|
|
- es_map_base += stream_info_length; |
236 |
|
|
} |
237 |
|
|
+ /* We ignore the 4-byte CRC at the end */ |
238 |
|
|
|
239 |
|
|
gst_adapter_unmap (demux->adapter); |
240 |
|
|
- gst_adapter_flush (demux->adapter, length); |
241 |
|
|
- ADAPTER_OFFSET_FLUSH (length); |
242 |
|
|
+ gst_adapter_flush (demux->adapter, psm_length); |
243 |
|
|
+ ADAPTER_OFFSET_FLUSH (psm_length); |
244 |
|
|
return GST_FLOW_OK; |
245 |
|
|
|
246 |
|
|
+fail_invalid: |
247 |
|
|
+ GST_DEBUG_OBJECT (demux, "Failed to parse PSM. Skipping"); |
248 |
|
|
+ gst_adapter_unmap (demux->adapter); |
249 |
|
|
+ gst_adapter_flush (demux->adapter, psm_length); |
250 |
|
|
+ ADAPTER_OFFSET_FLUSH (psm_length); |
251 |
|
|
+ return GST_FLOW_LOST_SYNC; |
252 |
|
|
psm_len_error: |
253 |
|
|
{ |
254 |
|
|
GST_DEBUG_OBJECT (demux, "error in PSM length"); |
255 |
|
|
@@ -2158,13 +2201,10 @@ gst_flups_demux_data_cb (GstPESFilter * |
256 |
|
|
GstMapInfo map; |
257 |
|
|
gsize datalen; |
258 |
|
|
guint offset = 0; |
259 |
|
|
- |
260 |
|
|
gst_buffer_map (buffer, &map, GST_MAP_READ); |
261 |
|
|
datalen = map.size; |
262 |
|
|
- |
263 |
|
|
start_code = filter->start_code; |
264 |
|
|
id = filter->id; |
265 |
|
|
- |
266 |
|
|
if (first) { |
267 |
|
|
/* find the stream type */ |
268 |
|
|
stream_type = demux->psm[id]; |
269 |
|
|
@@ -2175,7 +2215,6 @@ gst_flups_demux_data_cb (GstPESFilter * |
270 |
|
|
* (see ftp://ftp.mplayerhq.hu/MPlayer/samples/MPEG-VOB/vdr-AC3) */ |
271 |
|
|
if (datalen >= 4) { |
272 |
|
|
guint hdr = GST_READ_UINT32_BE (map.data); |
273 |
|
|
- |
274 |
|
|
if (G_UNLIKELY ((hdr & 0xffff0000) == AC3_SYNC_WORD)) { |
275 |
|
|
id = 0x80; |
276 |
|
|
stream_type = demux->psm[id] = ST_GST_AUDIO_RAWA52; |
277 |
|
|
@@ -2187,10 +2226,8 @@ gst_flups_demux_data_cb (GstPESFilter * |
278 |
|
|
/* new id is in the first byte */ |
279 |
|
|
id = map.data[offset++]; |
280 |
|
|
datalen--; |
281 |
|
|
- |
282 |
|
|
/* and remap */ |
283 |
|
|
stream_type = demux->psm[id]; |
284 |
|
|
- |
285 |
|
|
/* Now, if it's a subpicture stream - no more, otherwise |
286 |
|
|
* take the first byte too, since it's the frame count in audio |
287 |
|
|
* streams and our backwards compat convention is to strip it off */ |
288 |
|
|
@@ -2198,7 +2235,6 @@ gst_flups_demux_data_cb (GstPESFilter * |
289 |
|
|
/* Number of audio frames in this packet */ |
290 |
|
|
#ifndef GST_DISABLE_GST_DEBUG |
291 |
|
|
guint8 nframes; |
292 |
|
|
- |
293 |
|
|
nframes = map.data[offset]; |
294 |
|
|
GST_LOG_OBJECT (demux, "private type 0x%02x, %d frames", id, |
295 |
|
|
nframes); |
296 |
|
|
@@ -2206,8 +2242,8 @@ gst_flups_demux_data_cb (GstPESFilter * |
297 |
|
|
offset++; |
298 |
|
|
datalen--; |
299 |
|
|
} else { |
300 |
|
|
- GST_LOG_OBJECT (demux, "private type 0x%02x, stream type %d", id, |
301 |
|
|
- stream_type); |
302 |
|
|
+ GST_LOG_OBJECT (demux, "private type 0x%02x, stream type %d", |
303 |
|
|
+ id, stream_type); |
304 |
|
|
} |
305 |
|
|
} |
306 |
|
|
} |
307 |
|
|
@@ -2220,7 +2256,6 @@ gst_flups_demux_data_cb (GstPESFilter * |
308 |
|
|
"(%" G_GUINT64_FORMAT ")", filter->pts, demux->next_pts); |
309 |
|
|
} else |
310 |
|
|
demux->next_pts = G_MAXUINT64; |
311 |
|
|
- |
312 |
|
|
if (filter->dts != -1) { |
313 |
|
|
demux->next_dts = filter->dts + demux->scr_adjust; |
314 |
|
|
} else { |
315 |
|
|
@@ -2267,9 +2302,7 @@ gst_flups_demux_data_cb (GstPESFilter * |
316 |
|
|
done: |
317 |
|
|
gst_buffer_unmap (buffer, &map); |
318 |
|
|
gst_buffer_unref (buffer); |
319 |
|
|
- |
320 |
|
|
return ret; |
321 |
|
|
- |
322 |
|
|
/* ERRORS */ |
323 |
|
|
unknown_stream_type: |
324 |
|
|
{ |
325 |
|
|
@@ -2287,17 +2320,13 @@ gst_flups_demux_resync (GstFluPSDemux * |
326 |
|
|
guint32 code; |
327 |
|
|
gint offset; |
328 |
|
|
gboolean found; |
329 |
|
|
- |
330 |
|
|
avail = gst_adapter_available (demux->adapter); |
331 |
|
|
if (G_UNLIKELY (avail < 4)) |
332 |
|
|
goto need_data; |
333 |
|
|
- |
334 |
|
|
/* Common case, read 4 bytes an check it */ |
335 |
|
|
data = gst_adapter_map (demux->adapter, 4); |
336 |
|
|
- |
337 |
|
|
/* read currect code */ |
338 |
|
|
code = GST_READ_UINT32_BE (data); |
339 |
|
|
- |
340 |
|
|
/* The common case is that the sync code is at 0 bytes offset */ |
341 |
|
|
if (G_LIKELY ((code & 0xffffff00) == 0x100L)) { |
342 |
|
|
GST_LOG_OBJECT (demux, "Found resync code %08x after 0 bytes", code); |
343 |
|
|
@@ -2311,16 +2340,12 @@ gst_flups_demux_resync (GstFluPSDemux * |
344 |
|
|
offset = 4; |
345 |
|
|
if (offset >= avail) |
346 |
|
|
goto need_data; /* Not enough data to find sync */ |
347 |
|
|
- |
348 |
|
|
data = gst_adapter_map (demux->adapter, avail); |
349 |
|
|
- |
350 |
|
|
do { |
351 |
|
|
code = (code << 8) | data[offset++]; |
352 |
|
|
found = (code & 0xffffff00) == 0x100L; |
353 |
|
|
} while (offset < avail && !found); |
354 |
|
|
- |
355 |
|
|
gst_adapter_unmap (demux->adapter); |
356 |
|
|
- |
357 |
|
|
if (!save || demux->sink_segment.rate >= 0.0) { |
358 |
|
|
GST_LOG_OBJECT (demux, "flushing %d bytes", offset - 4); |
359 |
|
|
/* forward playback, we can discard and flush the skipped bytes */ |
360 |
|
|
@@ -2351,7 +2376,6 @@ gst_flups_demux_resync (GstFluPSDemux * |
361 |
|
|
} |
362 |
|
|
|
363 |
|
|
return found; |
364 |
|
|
- |
365 |
|
|
need_data: |
366 |
|
|
{ |
367 |
|
|
GST_LOG_OBJECT (demux, "we need more data for resync %d", avail); |
368 |
|
|
@@ -2420,7 +2444,6 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
369 |
|
|
next32 = GST_READ_UINT32_BE (data); |
370 |
|
|
if ((next32 & 0x00000300) != 0x00000300) |
371 |
|
|
goto beach; |
372 |
|
|
- |
373 |
|
|
stuffing_bytes = (next32 & 0x07); |
374 |
|
|
data += 4; |
375 |
|
|
while (stuffing_bytes--) { |
376 |
|
|
@@ -2431,10 +2454,8 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
377 |
|
|
/* check markers */ |
378 |
|
|
if ((scr1 & 0xf1000100) != 0x21000100) |
379 |
|
|
goto beach; |
380 |
|
|
- |
381 |
|
|
if ((scr2 & 0x01800001) != 0x01800001) |
382 |
|
|
goto beach; |
383 |
|
|
- |
384 |
|
|
/* :4=0010 ! scr:3 ! marker:1==1 ! scr:15 ! marker:1==1 ! scr:15 ! marker:1==1 */ |
385 |
|
|
scr = ((guint64) scr1 & 0x0e000000) << 5; |
386 |
|
|
scr |= ((guint64) scr1 & 0x00fffe00) << 6; |
387 |
|
|
@@ -2469,9 +2490,7 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
388 |
|
|
|
389 |
|
|
/* skip sync code and size */ |
390 |
|
|
data += 6; |
391 |
|
|
- |
392 |
|
|
pts = dts = -1; |
393 |
|
|
- |
394 |
|
|
/* stuffing bits, first two bits are '10' for mpeg2 pes so this code is |
395 |
|
|
* not triggered. */ |
396 |
|
|
while (TRUE) { |
397 |
|
|
@@ -2483,7 +2502,6 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
398 |
|
|
/* STD buffer size, never for mpeg2 */ |
399 |
|
|
if ((*data & 0xc0) == 0x40) |
400 |
|
|
data += 2; |
401 |
|
|
- |
402 |
|
|
/* PTS but no DTS, never for mpeg2 */ |
403 |
|
|
if ((*data & 0xf0) == 0x20) { |
404 |
|
|
READ_TS (data, pts, beach); |
405 |
|
|
@@ -2495,7 +2513,6 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
406 |
|
|
} else if ((*data & 0xc0) == 0x80) { |
407 |
|
|
/* mpeg2 case */ |
408 |
|
|
guchar flags; |
409 |
|
|
- |
410 |
|
|
/* 2: '10' |
411 |
|
|
* 2: PES_scrambling_control |
412 |
|
|
* 1: PES_priority |
413 |
|
|
@@ -2504,10 +2521,8 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
414 |
|
|
* 1: original_or_copy |
415 |
|
|
*/ |
416 |
|
|
flags = *data++; |
417 |
|
|
- |
418 |
|
|
if ((flags & 0xc0) != 0x80) |
419 |
|
|
goto beach; |
420 |
|
|
- |
421 |
|
|
/* 2: PTS_DTS_flags |
422 |
|
|
* 1: ESCR_flag |
423 |
|
|
* 1: ES_rate_flag |
424 |
|
|
@@ -2517,14 +2532,11 @@ gst_flups_demux_scan_ts (GstFluPSDemux * |
425 |
|
|
* 1: PES_extension_flag |
426 |
|
|
*/ |
427 |
|
|
flags = *data++; |
428 |
|
|
- |
429 |
|
|
/* 8: PES_header_data_length */ |
430 |
|
|
data++; |
431 |
|
|
- |
432 |
|
|
/* only DTS: this is invalid */ |
433 |
|
|
if ((flags & 0xc0) == 0x40) |
434 |
|
|
goto beach; |
435 |
|
|
- |
436 |
|
|
/* check for PTS */ |
437 |
|
|
if ((flags & 0x80)) { |
438 |
|
|
READ_TS (data, pts, beach); |
439 |
|
|
@@ -2587,7 +2599,6 @@ gst_flups_demux_scan_forward_ts (GstFluP |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
end_scan = map.size - scan_sz; |
443 |
|
|
- |
444 |
|
|
/* scan the block */ |
445 |
|
|
for (cursor = 0; !found && cursor <= end_scan; cursor++) { |
446 |
|
|
found = gst_flups_demux_scan_ts (demux, map.data + cursor, mode, &ts); |
447 |
|
|
@@ -2596,7 +2607,6 @@ gst_flups_demux_scan_forward_ts (GstFluP |
448 |
|
|
/* done with the buffer, unref it */ |
449 |
|
|
gst_buffer_unmap (buffer, &map); |
450 |
|
|
gst_buffer_unref (buffer); |
451 |
|
|
- |
452 |
|
|
if (found) { |
453 |
|
|
*rts = ts; |
454 |
|
|
*pos = offset + cursor - 1; |
455 |
|
|
@@ -2604,7 +2614,6 @@ gst_flups_demux_scan_forward_ts (GstFluP |
456 |
|
|
offset += cursor; |
457 |
|
|
} |
458 |
|
|
} while (!found && offset < demux->sink_segment.stop); |
459 |
|
|
- |
460 |
|
|
return found; |
461 |
|
|
} |
462 |
|
|
|
463 |
|
|
@@ -2641,9 +2650,7 @@ gst_flups_demux_scan_backward_ts (GstFlu |
464 |
|
|
ret = gst_pad_pull_range (demux->sinkpad, offset, to_read, &buffer); |
465 |
|
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) |
466 |
|
|
return FALSE; |
467 |
|
|
- |
468 |
|
|
gst_buffer_map (buffer, &map, GST_MAP_READ); |
469 |
|
|
- |
470 |
|
|
/* may get a short buffer at the end of the file */ |
471 |
|
|
if (G_UNLIKELY (map.size <= scan_sz)) { |
472 |
|
|
gst_buffer_unmap (buffer, &map); |
473 |
|
|
@@ -2653,7 +2660,6 @@ gst_flups_demux_scan_backward_ts (GstFlu |
474 |
|
|
|
475 |
|
|
start_scan = map.size - scan_sz; |
476 |
|
|
data = map.data + start_scan; |
477 |
|
|
- |
478 |
|
|
/* scan the block */ |
479 |
|
|
for (cursor = (start_scan + 1); !found && cursor > 0; cursor--) { |
480 |
|
|
found = gst_flups_demux_scan_ts (demux, data--, mode, &ts); |
481 |
|
|
@@ -2662,14 +2668,12 @@ gst_flups_demux_scan_backward_ts (GstFlu |
482 |
|
|
/* done with the buffer, unref it */ |
483 |
|
|
gst_buffer_unmap (buffer, &map); |
484 |
|
|
gst_buffer_unref (buffer); |
485 |
|
|
- |
486 |
|
|
if (found) { |
487 |
|
|
*rts = ts; |
488 |
|
|
*pos = offset + cursor; |
489 |
|
|
} |
490 |
|
|
|
491 |
|
|
} while (!found && offset > 0); |
492 |
|
|
- |
493 |
|
|
return found; |
494 |
|
|
} |
495 |
|
|
|
496 |
|
|
@@ -2707,30 +2711,30 @@ gst_flups_sink_get_duration (GstFluPSDem |
497 |
|
|
/* Scan for notorious SCR and PTS to calculate the duration */ |
498 |
|
|
/* scan for first SCR in the stream */ |
499 |
|
|
offset = demux->sink_segment.start; |
500 |
|
|
- gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &demux->first_scr, |
501 |
|
|
- DURATION_SCAN_LIMIT); |
502 |
|
|
- GST_DEBUG_OBJECT (demux, "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
503 |
|
|
- " in packet starting at %" G_GUINT64_FORMAT, |
504 |
|
|
- demux->first_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), |
505 |
|
|
- offset); |
506 |
|
|
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, |
507 |
|
|
+ &demux->first_scr, DURATION_SCAN_LIMIT); |
508 |
|
|
+ GST_DEBUG_OBJECT (demux, |
509 |
|
|
+ "First SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
510 |
|
|
+ " in packet starting at %" G_GUINT64_FORMAT, demux->first_scr, |
511 |
|
|
+ GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), offset); |
512 |
|
|
demux->first_scr_offset = offset; |
513 |
|
|
/* scan for last SCR in the stream */ |
514 |
|
|
offset = demux->sink_segment.stop; |
515 |
|
|
gst_flups_demux_scan_backward_ts (demux, &offset, SCAN_SCR, |
516 |
|
|
- &demux->last_scr, 0); |
517 |
|
|
- GST_DEBUG_OBJECT (demux, "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
518 |
|
|
- " in packet starting at %" G_GUINT64_FORMAT, |
519 |
|
|
- demux->last_scr, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)), |
520 |
|
|
- offset); |
521 |
|
|
+ &demux->last_scr, DURATION_SCAN_LIMIT); |
522 |
|
|
+ GST_DEBUG_OBJECT (demux, |
523 |
|
|
+ "Last SCR: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
524 |
|
|
+ " in packet starting at %" G_GUINT64_FORMAT, demux->last_scr, |
525 |
|
|
+ GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->last_scr)), offset); |
526 |
|
|
demux->last_scr_offset = offset; |
527 |
|
|
/* scan for first PTS in the stream */ |
528 |
|
|
offset = demux->sink_segment.start; |
529 |
|
|
- gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, &demux->first_pts, |
530 |
|
|
- DURATION_SCAN_LIMIT); |
531 |
|
|
- GST_DEBUG_OBJECT (demux, "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
532 |
|
|
- " in packet starting at %" G_GUINT64_FORMAT, |
533 |
|
|
- demux->first_pts, GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)), |
534 |
|
|
- offset); |
535 |
|
|
+ gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_PTS, |
536 |
|
|
+ &demux->first_pts, DURATION_SCAN_LIMIT); |
537 |
|
|
+ GST_DEBUG_OBJECT (demux, |
538 |
|
|
+ "First PTS: %" G_GINT64_FORMAT " %" GST_TIME_FORMAT |
539 |
|
|
+ " in packet starting at %" G_GUINT64_FORMAT, demux->first_pts, |
540 |
|
|
+ GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_pts)), offset); |
541 |
|
|
if (demux->first_pts != G_MAXUINT64) { |
542 |
|
|
/* scan for last PTS in the stream */ |
543 |
|
|
offset = demux->sink_segment.stop; |
544 |
|
|
@@ -2755,8 +2759,8 @@ gst_flups_sink_get_duration (GstFluPSDem |
545 |
|
|
/* Start demuxing from the right place */ |
546 |
|
|
demux->sink_segment.position = offset; |
547 |
|
|
GST_DEBUG_OBJECT (demux, "Replaced First SCR: %" G_GINT64_FORMAT |
548 |
|
|
- " %" GST_TIME_FORMAT " in packet starting at %" G_GUINT64_FORMAT, |
549 |
|
|
- demux->first_scr, |
550 |
|
|
+ " %" GST_TIME_FORMAT " in packet starting at %" |
551 |
|
|
+ G_GUINT64_FORMAT, demux->first_scr, |
552 |
|
|
GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (demux->first_scr)), offset); |
553 |
|
|
break; |
554 |
|
|
} |
555 |
|
|
@@ -2766,7 +2770,6 @@ gst_flups_sink_get_duration (GstFluPSDem |
556 |
|
|
demux->base_time = MPEGTIME_TO_GSTTIME (demux->first_scr); |
557 |
|
|
demux->scr_rate_n = demux->last_scr_offset - demux->first_scr_offset; |
558 |
|
|
demux->scr_rate_d = demux->last_scr - demux->first_scr; |
559 |
|
|
- |
560 |
|
|
if (G_LIKELY (demux->first_pts != G_MAXUINT64 && |
561 |
|
|
demux->last_pts != G_MAXUINT64)) { |
562 |
|
|
/* update the src segment */ |
563 |
|
|
@@ -2783,9 +2786,7 @@ gst_flups_sink_get_duration (GstFluPSDem |
564 |
|
|
&demux->sink_segment); |
565 |
|
|
GST_INFO_OBJECT (demux, "src segment configured %" GST_SEGMENT_FORMAT, |
566 |
|
|
&demux->src_segment); |
567 |
|
|
- |
568 |
|
|
res = TRUE; |
569 |
|
|
- |
570 |
|
|
beach: |
571 |
|
|
return res; |
572 |
|
|
} |
573 |
|
|
@@ -2796,7 +2797,6 @@ gst_flups_demux_pull_block (GstPad * pad |
574 |
|
|
{ |
575 |
|
|
GstFlowReturn ret = GST_FLOW_OK; |
576 |
|
|
GstBuffer *buffer = NULL; |
577 |
|
|
- |
578 |
|
|
ret = gst_pad_pull_range (pad, offset, size, &buffer); |
579 |
|
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) { |
580 |
|
|
GST_DEBUG_OBJECT (demux, "pull range at %" G_GUINT64_FORMAT |
581 |
|
|
@@ -2855,10 +2855,11 @@ gst_flups_demux_loop (GstPad * pad) |
582 |
|
|
((demux->sink_segment.position >= demux->sink_segment.stop) || |
583 |
|
|
(demux->src_segment.stop != (guint64) - 1 && |
584 |
|
|
demux->src_segment.position >= demux->src_segment.stop))) { |
585 |
|
|
- GST_DEBUG_OBJECT (demux, "forward mode using segment reached end of " |
586 |
|
|
- "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT |
587 |
|
|
- " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %" |
588 |
|
|
- G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.position), |
589 |
|
|
+ GST_DEBUG_OBJECT (demux, |
590 |
|
|
+ "forward mode using segment reached end of " "segment pos %" |
591 |
|
|
+ GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " pos in bytes %" |
592 |
|
|
+ G_GUINT64_FORMAT " stop in bytes %" G_GUINT64_FORMAT, |
593 |
|
|
+ GST_TIME_ARGS (demux->src_segment.position), |
594 |
|
|
GST_TIME_ARGS (demux->src_segment.stop), |
595 |
|
|
demux->sink_segment.position, demux->sink_segment.stop); |
596 |
|
|
ret = GST_FLOW_EOS; |
597 |
|
|
@@ -2881,10 +2882,11 @@ gst_flups_demux_loop (GstPad * pad) |
598 |
|
|
/* check EOS condition */ |
599 |
|
|
if (demux->sink_segment.position <= demux->sink_segment.start || |
600 |
|
|
demux->src_segment.position <= demux->src_segment.start) { |
601 |
|
|
- GST_DEBUG_OBJECT (demux, "reverse mode using segment reached end of " |
602 |
|
|
- "segment pos %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT |
603 |
|
|
- " pos in bytes %" G_GUINT64_FORMAT " stop in bytes %" |
604 |
|
|
- G_GUINT64_FORMAT, GST_TIME_ARGS (demux->src_segment.position), |
605 |
|
|
+ GST_DEBUG_OBJECT (demux, |
606 |
|
|
+ "reverse mode using segment reached end of " "segment pos %" |
607 |
|
|
+ GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " pos in bytes %" |
608 |
|
|
+ G_GUINT64_FORMAT " stop in bytes %" G_GUINT64_FORMAT, |
609 |
|
|
+ GST_TIME_ARGS (demux->src_segment.position), |
610 |
|
|
GST_TIME_ARGS (demux->src_segment.start), |
611 |
|
|
demux->sink_segment.position, demux->sink_segment.start); |
612 |
|
|
ret = GST_FLOW_EOS; |
613 |
|
|
@@ -2893,27 +2895,21 @@ gst_flups_demux_loop (GstPad * pad) |
614 |
|
|
} |
615 |
|
|
|
616 |
|
|
gst_object_unref (demux); |
617 |
|
|
- |
618 |
|
|
return; |
619 |
|
|
- |
620 |
|
|
pause: |
621 |
|
|
{ |
622 |
|
|
const gchar *reason = gst_flow_get_name (ret); |
623 |
|
|
- |
624 |
|
|
GST_LOG_OBJECT (demux, "pausing task, reason %s", reason); |
625 |
|
|
gst_pad_pause_task (pad); |
626 |
|
|
- |
627 |
|
|
if (ret == GST_FLOW_EOS) { |
628 |
|
|
/* perform EOS logic */ |
629 |
|
|
gst_element_no_more_pads (GST_ELEMENT_CAST (demux)); |
630 |
|
|
if (demux->src_segment.flags & GST_SEEK_FLAG_SEGMENT) { |
631 |
|
|
gint64 stop; |
632 |
|
|
- |
633 |
|
|
/* for segment playback we need to post when (in stream time) |
634 |
|
|
* we stopped, this is either stop (when set) or the duration. */ |
635 |
|
|
if ((stop = demux->src_segment.stop) == -1) |
636 |
|
|
stop = demux->src_segment.duration; |
637 |
|
|
- |
638 |
|
|
if (demux->sink_segment.rate >= 0) { |
639 |
|
|
GST_LOG_OBJECT (demux, "Sending segment done, at end of segment"); |
640 |
|
|
gst_element_post_message (GST_ELEMENT_CAST (demux), |
641 |
|
|
@@ -2922,8 +2918,8 @@ pause: |
642 |
|
|
gst_flups_demux_send_event (demux, |
643 |
|
|
gst_event_new_segment_done (GST_FORMAT_TIME, stop)); |
644 |
|
|
} else { /* Reverse playback */ |
645 |
|
|
- GST_LOG_OBJECT (demux, "Sending segment done, at beginning of " |
646 |
|
|
- "segment"); |
647 |
|
|
+ GST_LOG_OBJECT (demux, |
648 |
|
|
+ "Sending segment done, at beginning of " "segment"); |
649 |
|
|
gst_element_post_message (GST_ELEMENT_CAST (demux), |
650 |
|
|
gst_message_new_segment_done (GST_OBJECT_CAST (demux), |
651 |
|
|
GST_FORMAT_TIME, demux->src_segment.start)); |
652 |
|
|
@@ -2960,7 +2956,6 @@ gst_flups_demux_sink_activate (GstPad * |
653 |
|
|
{ |
654 |
|
|
gboolean res = FALSE; |
655 |
|
|
GstQuery *query = gst_query_new_scheduling (); |
656 |
|
|
- |
657 |
|
|
if (gst_pad_peer_query (sinkpad, query)) { |
658 |
|
|
if (gst_query_has_scheduling_mode_with_flags (query, |
659 |
|
|
GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE)) { |
660 |
|
|
@@ -2973,7 +2968,6 @@ gst_flups_demux_sink_activate (GstPad * |
661 |
|
|
} |
662 |
|
|
|
663 |
|
|
gst_query_unref (query); |
664 |
|
|
- |
665 |
|
|
return res; |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
@@ -3030,12 +3024,9 @@ static GstFlowReturn |
669 |
|
|
gst_flups_demux_combine_flows (GstFluPSDemux * demux, GstFlowReturn ret) |
670 |
|
|
{ |
671 |
|
|
GST_LOG_OBJECT (demux, "flow return: %s", gst_flow_get_name (ret)); |
672 |
|
|
- |
673 |
|
|
ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret); |
674 |
|
|
- |
675 |
|
|
if (G_UNLIKELY (demux->need_no_more_pads && ret == GST_FLOW_NOT_LINKED)) |
676 |
|
|
ret = GST_FLOW_OK; |
677 |
|
|
- |
678 |
|
|
GST_LOG_OBJECT (demux, "combined flow return: %s", gst_flow_get_name (ret)); |
679 |
|
|
return ret; |
680 |
|
|
} |
681 |
|
|
@@ -3085,7 +3076,6 @@ gst_flups_demux_chain (GstPad * pad, Gst |
682 |
|
|
|
683 |
|
|
avail = gst_adapter_available (demux->adapter); |
684 |
|
|
GST_LOG_OBJECT (demux, "avail now: %d, state %d", avail, demux->filter.state); |
685 |
|
|
- |
686 |
|
|
switch (demux->filter.state) { |
687 |
|
|
case STATE_DATA_SKIP: |
688 |
|
|
case STATE_DATA_PUSH: |
689 |
|
|
@@ -3155,7 +3145,6 @@ gst_flups_demux_chain (GstPad * pad, Gst |
690 |
|
|
* saved up to the next ps sync. */ |
691 |
|
|
if (ps_sync) |
692 |
|
|
save = FALSE; |
693 |
|
|
- |
694 |
|
|
switch (ret) { |
695 |
|
|
case GST_FLOW_NEED_MORE_DATA: |
696 |
|
|
GST_DEBUG_OBJECT (demux, "need more data"); |
697 |
|
|
@@ -3189,7 +3178,6 @@ gst_flups_demux_change_state (GstElement |
698 |
|
|
{ |
699 |
|
|
GstFluPSDemux *demux = GST_FLUPS_DEMUX (element); |
700 |
|
|
GstStateChangeReturn result; |
701 |
|
|
- |
702 |
|
|
switch (transition) { |
703 |
|
|
case GST_STATE_CHANGE_NULL_TO_READY: |
704 |
|
|
gst_pes_filter_init (&demux->filter, demux->adapter, |
705 |
|
|
@@ -3206,7 +3194,6 @@ gst_flups_demux_change_state (GstElement |
706 |
|
|
} |
707 |
|
|
|
708 |
|
|
result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); |
709 |
|
|
- |
710 |
|
|
switch (transition) { |
711 |
|
|
case GST_STATE_CHANGE_PAUSED_TO_READY: |
712 |
|
|
gst_flups_demux_reset (demux); |