1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | #include <stdlib.h> |
28 | #include <string.h> |
29 | |
30 | #define CONTAINER_IS_BIG_ENDIAN |
31 | //#define ENABLE_CONTAINERS_LOG_FORMAT |
32 | //#define ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE |
33 | #include "containers/core/containers_bits.h" |
34 | #include "containers/core/containers_private.h" |
35 | #include "containers/core/containers_io_helpers.h" |
36 | #include "containers/core/containers_utils.h" |
37 | #include "containers/core/containers_logging.h" |
38 | #undef CONTAINER_HELPER_LOG_INDENT |
39 | #define CONTAINER_HELPER_LOG_INDENT(a) (2*(a)->priv->module->level) |
40 | |
41 | /****************************************************************************** |
42 | Defines. |
43 | ******************************************************************************/ |
44 | #define PS_TRACKS_MAX 2 |
45 | #define 256 |
46 | |
47 | #define PS_SYNC_FAIL_MAX 65536 /** Maximum number of byte-wise sync attempts, |
48 | should be enough to stride at least one |
49 | PES packet (length encoded using 16 bits). */ |
50 | |
51 | /** Maximum number of pack/packet start codes scanned when searching for tracks |
52 | at open time or when resyncing. */ |
53 | #define PS_PACK_SCAN_MAX 128 |
54 | |
55 | /****************************************************************************** |
56 | Type definitions. |
57 | ******************************************************************************/ |
58 | typedef struct VC_CONTAINER_TRACK_MODULE_T |
59 | { |
60 | /** Coding and elementary stream id of the track */ |
61 | uint32_t stream_id; |
62 | |
63 | /** Sub-stream id (for private_stream_1 only) */ |
64 | uint32_t substream_id; |
65 | |
66 | /** PES packet payload offset (for private_stream_1) */ |
67 | unsigned int payload_offset; |
68 | |
69 | uint8_t [PS_EXTRADATA_MAX]; |
70 | |
71 | } VC_CONTAINER_TRACK_MODULE_T; |
72 | |
73 | typedef struct VC_CONTAINER_MODULE_T |
74 | { |
75 | /** Logging indentation level */ |
76 | uint32_t level; |
77 | |
78 | /** Track data */ |
79 | int tracks_num; |
80 | VC_CONTAINER_TRACK_T *tracks[PS_TRACKS_MAX]; |
81 | |
82 | /** State flag denoting whether or not we are searching |
83 | for tracks (at open time) */ |
84 | bool searching_tracks; |
85 | |
86 | /** Size of program stream data (if known) */ |
87 | uint64_t data_size; |
88 | |
89 | /** Offset to the first pack or PES packet start code we've seen */ |
90 | uint64_t data_offset; |
91 | |
92 | /** The first system_clock_reference value we've seen, in (27MHz ticks) */ |
93 | int64_t scr_offset; |
94 | |
95 | /** Most recent system_clock_reference value we've seen, in (27MHz ticks) */ |
96 | int64_t scr; |
97 | |
98 | /** Global offset we add to PES timestamps to make them zero based and |
99 | to work around discontinuity in the system_clock_reference */ |
100 | int64_t scr_bias; |
101 | |
102 | /** Most recent program stream mux rate (in units of 50 bytes/second). */ |
103 | uint32_t mux_rate; |
104 | |
105 | /** Offset to the most recent pack start code we've seen */ |
106 | uint64_t pack_offset; |
107 | |
108 | /** Program stream mux rate is often incorrect or fixed to 25200 (10.08 |
109 | Mbit/s) which yields inaccurate duration estimate for most files. We |
110 | maintain a moving average data rate (in units of bytes/second) based |
111 | on the system_clock_reference to give better estimates. */ |
112 | int64_t data_rate; |
113 | |
114 | /** Offset to the most recent PES packet start code prefix we've seen */ |
115 | unsigned int packet_data_size; |
116 | unsigned int packet_data_left; |
117 | int64_t packet_pts; |
118 | int64_t packet_dts; |
119 | int packet_track; |
120 | |
121 | } VC_CONTAINER_MODULE_T; |
122 | |
123 | /****************************************************************************** |
124 | Function prototypes |
125 | ******************************************************************************/ |
126 | |
127 | VC_CONTAINER_STATUS_T ps_reader_open( VC_CONTAINER_T * ); |
128 | |
129 | /****************************************************************************** |
130 | Prototypes for local functions |
131 | ******************************************************************************/ |
132 | |
133 | /****************************************************************************** |
134 | Local Functions |
135 | ******************************************************************************/ |
136 | |
137 | /** Find the track associated with a PS stream_id */ |
138 | static VC_CONTAINER_TRACK_T *ps_find_track( VC_CONTAINER_T *ctx, uint32_t stream_id, |
139 | uint32_t substream_id, bool b_create ) |
140 | { |
141 | VC_CONTAINER_TRACK_T *track = 0; |
142 | unsigned int i; |
143 | |
144 | for(i = 0; i < ctx->tracks_num; i++) |
145 | if(ctx->tracks[i]->priv->module->stream_id == stream_id && |
146 | ctx->tracks[i]->priv->module->substream_id == substream_id) break; |
147 | |
148 | if(i < ctx->tracks_num) /* We found it */ |
149 | track = ctx->tracks[i]; |
150 | |
151 | if(!track && b_create && i < PS_TRACKS_MAX) |
152 | { |
153 | /* Allocate and initialise a new track */ |
154 | ctx->tracks[i] = track = |
155 | vc_container_allocate_track(ctx, sizeof(*ctx->tracks[0]->priv->module)); |
156 | if(track) |
157 | { |
158 | track->priv->module->stream_id = stream_id; |
159 | track->priv->module->substream_id = substream_id; |
160 | ctx->tracks_num++; |
161 | } |
162 | } |
163 | |
164 | if(!track && b_create) |
165 | LOG_DEBUG(ctx, "could not create track for stream id: %i" , stream_id); |
166 | |
167 | return track; |
168 | } |
169 | |
170 | /*****************************************************************************/ |
171 | STATIC_INLINE VC_CONTAINER_STATUS_T ps_find_start_code( VC_CONTAINER_T *ctx, uint8_t *buffer ) |
172 | { |
173 | unsigned int i; |
174 | |
175 | /* Scan for a pack or PES packet start code prefix */ |
176 | for (i = 0; i < PS_SYNC_FAIL_MAX; ++i) |
177 | { |
178 | if(PEEK_BYTES(ctx, buffer, 4) < 4) |
179 | return VC_CONTAINER_ERROR_EOS; |
180 | |
181 | if(buffer[0] == 0x0 && buffer[1] == 0x0 && buffer[2] == 0x1 && buffer[3] >= 0xB9) |
182 | break; |
183 | |
184 | if (SKIP_BYTES(ctx, 1) != 1) |
185 | return VC_CONTAINER_ERROR_EOS; |
186 | } |
187 | |
188 | if(i == PS_SYNC_FAIL_MAX) /* We didn't find a valid pack or PES packet */ |
189 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
190 | |
191 | if (buffer[3] == 0xB9) /* MPEG_program_end_code */ |
192 | return VC_CONTAINER_ERROR_EOS; |
193 | |
194 | return VC_CONTAINER_SUCCESS; |
195 | } |
196 | |
197 | /*****************************************************************************/ |
198 | static VC_CONTAINER_STATUS_T ( VC_CONTAINER_T *ctx ) |
199 | { |
200 | uint8_t [8]; |
201 | uint32_t length; |
202 | VC_CONTAINER_BITS_T bits; |
203 | |
204 | if(_READ_U32(ctx) != 0x1BB) return VC_CONTAINER_ERROR_CORRUPTED; |
205 | LOG_FORMAT(ctx, "system_header" ); |
206 | ctx->priv->module->level++; |
207 | |
208 | length = READ_U16(ctx, "header_length" ); |
209 | if(length < 6) return VC_CONTAINER_ERROR_CORRUPTED; |
210 | if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS; |
211 | |
212 | BITS_INIT(ctx, &bits, header, 6); |
213 | |
214 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
215 | BITS_SKIP(ctx, &bits, 22, "rate_bound" ); |
216 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
217 | BITS_SKIP(ctx, &bits, 6, "audio_bound" ); |
218 | BITS_SKIP(ctx, &bits, 1, "fixed_flag" ); |
219 | BITS_SKIP(ctx, &bits, 1, "CSPS_flag" ); |
220 | BITS_SKIP(ctx, &bits, 1, "system_audio_lock_flag" ); |
221 | BITS_SKIP(ctx, &bits, 1, "system_video_lock_flag" ); |
222 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
223 | BITS_SKIP(ctx, &bits, 5, "video_bound" ); |
224 | BITS_SKIP(ctx, &bits, 1, "packet_rate_restriction_flag" ); |
225 | BITS_SKIP(ctx, &bits, 7, "reserved_bits" ); |
226 | length -= 6; |
227 | |
228 | while(length >= 3 && (PEEK_U8(ctx) & 0x80)) |
229 | { |
230 | SKIP_U8(ctx, "stream_id" ); |
231 | SKIP_BYTES(ctx, 2); |
232 | length -= 3; |
233 | } |
234 | SKIP_BYTES(ctx, length); |
235 | |
236 | ctx->priv->module->level--; |
237 | return STREAM_STATUS(ctx); |
238 | } |
239 | |
240 | /*****************************************************************************/ |
241 | static VC_CONTAINER_STATUS_T ( VC_CONTAINER_T *ctx ) |
242 | { |
243 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
244 | uint8_t [10]; |
245 | int64_t scr, scr_base, scr_ext = INT64_C(0); |
246 | uint64_t pack_offset = STREAM_POSITION(ctx); |
247 | uint32_t mux_rate, stuffing; |
248 | VC_CONTAINER_BITS_T bits; |
249 | VC_CONTAINER_STATUS_T status; |
250 | |
251 | if(_READ_U32(ctx) != 0x1BA) return VC_CONTAINER_ERROR_CORRUPTED; |
252 | LOG_FORMAT(ctx, "pack_header" ); |
253 | |
254 | module->level++; |
255 | |
256 | if (PEEK_U8(ctx) & 0x40) /* program stream */ |
257 | { |
258 | if(READ_BYTES(ctx, header, 10) != 10) return VC_CONTAINER_ERROR_EOS; |
259 | BITS_INIT(ctx, &bits, header, 10); |
260 | if(BITS_READ_U32(ctx, &bits, 2, "'01' marker bits" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
261 | scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]" ) << 30; |
262 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
263 | scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]" ) << 15; |
264 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
265 | scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]" ); |
266 | LOG_FORMAT(ctx, "system_clock_reference_base %" PRId64, scr_base); |
267 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
268 | scr_ext = BITS_READ_U32(ctx, &bits, 9, "system_clock_reference_extension" ); |
269 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
270 | mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate" ); |
271 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
272 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
273 | BITS_SKIP(ctx, &bits, 5, "reserved" ); |
274 | stuffing = BITS_READ_U32(ctx, &bits, 3, "pack_stuffing_length" ); |
275 | SKIP_BYTES(ctx, stuffing); |
276 | } |
277 | else /* system stream */ |
278 | { |
279 | if(READ_BYTES(ctx, header, 8) != 8) return VC_CONTAINER_ERROR_EOS; |
280 | BITS_INIT(ctx, &bits, header, 8); |
281 | if(BITS_READ_U32(ctx, &bits, 4, "'0010' marker bits" ) != 0x2) return VC_CONTAINER_ERROR_CORRUPTED; |
282 | scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]" ) << 30; |
283 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
284 | scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]" ) << 15; |
285 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
286 | scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]" ); |
287 | LOG_FORMAT(ctx, "system_clock_reference_base %" PRId64, scr_base); |
288 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
289 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
290 | mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate" ); |
291 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
292 | } |
293 | |
294 | if ((status = STREAM_STATUS(ctx)) != VC_CONTAINER_SUCCESS) return status; |
295 | |
296 | module->level--; |
297 | |
298 | /* Set or update system_clock_reference, adjust bias if necessary */ |
299 | scr = scr_base * INT64_C(300) + scr_ext; |
300 | |
301 | if (module->scr_offset == VC_CONTAINER_TIME_UNKNOWN) |
302 | module->scr_offset = scr; |
303 | |
304 | if (module->scr == VC_CONTAINER_TIME_UNKNOWN) |
305 | module->scr_bias = -scr; |
306 | else if (scr < module->scr) |
307 | module->scr_bias = module->scr - scr; |
308 | |
309 | if (module->scr != VC_CONTAINER_TIME_UNKNOWN) |
310 | { |
311 | /* system_clock_reference is not necessarily continuous across the entire stream */ |
312 | if (scr > module->scr) |
313 | { |
314 | int64_t data_rate; |
315 | data_rate = INT64_C(27000000) * (pack_offset - module->pack_offset) / (scr - module->scr); |
316 | |
317 | if (module->data_rate) |
318 | { |
319 | /* Simple moving average over data rate seen so far */ |
320 | module->data_rate = (module->data_rate * 31 + data_rate) >> 5; |
321 | } |
322 | else |
323 | { |
324 | module->data_rate = mux_rate * 50; |
325 | } |
326 | } |
327 | |
328 | module->pack_offset = pack_offset; |
329 | } |
330 | |
331 | module->scr = scr; |
332 | module->mux_rate = mux_rate; |
333 | |
334 | /* Check for a system header */ |
335 | if(PEEK_U32(ctx) == 0x1BB) |
336 | return ps_read_system_header(ctx); |
337 | |
338 | return STREAM_STATUS(ctx); |
339 | } |
340 | |
341 | /*****************************************************************************/ |
342 | static void ps_get_stream_coding( VC_CONTAINER_T *ctx, unsigned int stream_id, |
343 | VC_CONTAINER_ES_TYPE_T *p_type, VC_CONTAINER_FOURCC_T *p_codec, |
344 | VC_CONTAINER_FOURCC_T *p_variant) |
345 | { |
346 | VC_CONTAINER_ES_TYPE_T type = VC_CONTAINER_ES_TYPE_UNKNOWN; |
347 | VC_CONTAINER_FOURCC_T codec = VC_CONTAINER_CODEC_UNKNOWN; |
348 | VC_CONTAINER_FOURCC_T variant = 0; |
349 | |
350 | VC_CONTAINER_PARAM_UNUSED(ctx); |
351 | |
352 | if (stream_id == 0xE2) /* FIXME: why is this stream number reserved for H264? */ |
353 | { |
354 | type = VC_CONTAINER_ES_TYPE_VIDEO; |
355 | codec = VC_CONTAINER_CODEC_H264; |
356 | } |
357 | else if ((stream_id & 0xF0) == 0xE0) |
358 | { |
359 | type = VC_CONTAINER_ES_TYPE_VIDEO; |
360 | codec = VC_CONTAINER_CODEC_MP2V; |
361 | } |
362 | else if ((stream_id & 0xE0) == 0xC0) |
363 | { |
364 | type = VC_CONTAINER_ES_TYPE_AUDIO; |
365 | codec = VC_CONTAINER_CODEC_MPGA; |
366 | variant = VC_CONTAINER_VARIANT_MPGA_L2; |
367 | } |
368 | |
369 | /* FIXME: PRIVATE_EVOB_PES_PACKET with stream_id 0xFD ? */ |
370 | |
371 | *p_type = type; |
372 | *p_codec = codec; |
373 | *p_variant = variant; |
374 | } |
375 | |
376 | /*****************************************************************************/ |
377 | static int64_t ps_pes_time_to_us( VC_CONTAINER_T *ctx, int64_t time ) |
378 | { |
379 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
380 | |
381 | if (time == VC_CONTAINER_TIME_UNKNOWN) |
382 | return VC_CONTAINER_TIME_UNKNOWN; |
383 | |
384 | /* Need to wait for system_clock_reference first */ |
385 | if (module->scr_bias == VC_CONTAINER_TIME_UNKNOWN) |
386 | return VC_CONTAINER_TIME_UNKNOWN; |
387 | |
388 | /* Can't have valid bias without known system_clock_reference */ |
389 | vc_container_assert(module->scr != VC_CONTAINER_TIME_UNKNOWN); |
390 | |
391 | /* 90kHz (PES) clock --> (zero based) 27MHz system clock --> microseconds */ |
392 | return (INT64_C(300) * time + module->scr_bias) / INT64_C(27); |
393 | } |
394 | |
395 | /*****************************************************************************/ |
396 | static VC_CONTAINER_STATUS_T ps_read_pes_time( VC_CONTAINER_T *ctx, |
397 | uint32_t *p_length, unsigned int pts_dts, int64_t *p_pts, int64_t *p_dts ) |
398 | { |
399 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
400 | uint8_t [10]; |
401 | uint32_t length = *p_length; |
402 | VC_CONTAINER_BITS_T bits; |
403 | int64_t pts, dts; |
404 | |
405 | if (p_pts) *p_pts = VC_CONTAINER_TIME_UNKNOWN; |
406 | if (p_dts) *p_dts = VC_CONTAINER_TIME_UNKNOWN; |
407 | |
408 | if (pts_dts == 0x2) |
409 | { |
410 | /* PTS only */ |
411 | LOG_FORMAT(ctx, "PTS" ); |
412 | ctx->priv->module->level++; |
413 | if(length < 5) return VC_CONTAINER_ERROR_CORRUPTED; |
414 | if(READ_BYTES(ctx, header, 5) != 5) return VC_CONTAINER_ERROR_EOS; |
415 | BITS_INIT(ctx, &bits, header, 5); |
416 | |
417 | if(BITS_READ_U32(ctx, &bits, 4, "'0010' marker bits" ) != 0x2) return VC_CONTAINER_ERROR_CORRUPTED; |
418 | pts = BITS_READ_U32(ctx, &bits, 3, "PTS [32..30]" ) << 30; |
419 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
420 | pts |= BITS_READ_U32(ctx, &bits, 15, "PTS [29..15]" ) << 15; |
421 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
422 | pts |= BITS_READ_U32(ctx, &bits, 15, "PTS [14..0]" ); |
423 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
424 | LOG_FORMAT(ctx, "PTS %" PRId64, pts); |
425 | if (p_pts) *p_pts = pts; |
426 | length -= 5; |
427 | ctx->priv->module->level--; |
428 | } |
429 | else if (pts_dts == 0x3) |
430 | { |
431 | /* PTS & DTS */ |
432 | LOG_FORMAT(ctx, "PTS DTS" ); |
433 | ctx->priv->module->level++; |
434 | if(length < 10) return VC_CONTAINER_ERROR_CORRUPTED; |
435 | if(READ_BYTES(ctx, header, 10) != 10) return VC_CONTAINER_ERROR_EOS; |
436 | BITS_INIT(ctx, &bits, header, 10); |
437 | |
438 | /* PTS */ |
439 | if(BITS_READ_U32(ctx, &bits, 4, "'0011' marker bits" ) != 0x3) return VC_CONTAINER_ERROR_CORRUPTED; |
440 | pts = BITS_READ_U32(ctx, &bits, 3, "PTS [32..30]" ) << 30; |
441 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
442 | pts |= BITS_READ_U32(ctx, &bits, 15, "PTS [29..15]" ) << 15; |
443 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
444 | pts |= BITS_READ_U32(ctx, &bits, 15, "PTS [14..0]" ); |
445 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
446 | |
447 | /* DTS */ |
448 | if(BITS_READ_U32(ctx, &bits, 4, "'0001' marker bits" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
449 | dts = BITS_READ_U32(ctx, &bits, 3, "DTS [32..30]" ) << 30; |
450 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
451 | dts |= BITS_READ_U32(ctx, &bits, 15, "DTS [29..15]" ) << 15; |
452 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
453 | dts |= BITS_READ_U32(ctx, &bits, 15, "DTS [14..0]" ); |
454 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
455 | LOG_FORMAT(ctx, "PTS %" PRId64, pts); |
456 | LOG_FORMAT(ctx, "DTS %" PRId64, dts); |
457 | if (p_pts) *p_pts = pts; |
458 | if (p_dts) *p_dts = dts; |
459 | length -= 10; |
460 | ctx->priv->module->level--; |
461 | } |
462 | else |
463 | { |
464 | status = VC_CONTAINER_ERROR_NOT_FOUND; |
465 | } |
466 | |
467 | *p_length = *p_length - length; |
468 | |
469 | return status; |
470 | } |
471 | |
472 | /*****************************************************************************/ |
473 | static VC_CONTAINER_STATUS_T ps_read_pes_extension( VC_CONTAINER_T *ctx, |
474 | uint32_t *p_length ) |
475 | { |
476 | unsigned int pes_private_data, , packet_seq_counter, pstd_buffer, extension2; |
477 | uint8_t [2]; |
478 | uint32_t length = *p_length; |
479 | VC_CONTAINER_BITS_T bits; |
480 | unsigned int i; |
481 | |
482 | LOG_FORMAT(ctx, "PES_extension" ); |
483 | ctx->priv->module->level++; |
484 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
485 | if(READ_BYTES(ctx, header, 1) != 1) return VC_CONTAINER_ERROR_EOS; |
486 | BITS_INIT(ctx, &bits, header, 1); |
487 | |
488 | pes_private_data = BITS_READ_U32(ctx, &bits, 1, "PES_private_data_flag" ); |
489 | pack_header = BITS_READ_U32(ctx, &bits, 1, "pack_header_field_flag" ); |
490 | packet_seq_counter = BITS_READ_U32(ctx, &bits, 1, "program_packet_sequence_counter_flag" ); |
491 | pstd_buffer = BITS_READ_U32(ctx, &bits, 1, "P-STD_buffer_flag" ); |
492 | BITS_SKIP(ctx, &bits, 3, "3 reserved_bits" ); |
493 | extension2 = BITS_READ_U32(ctx, &bits, 1, "PES_extension_flag_2" ); |
494 | length -= 1; |
495 | |
496 | if (pes_private_data) |
497 | { |
498 | if(length < 16) return VC_CONTAINER_ERROR_CORRUPTED; |
499 | SKIP_BYTES(ctx, 16); /* PES_private_data */ |
500 | length -= 16; |
501 | } |
502 | |
503 | if (pack_header) |
504 | { |
505 | unsigned int pack_field_len; |
506 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
507 | pack_field_len = READ_U8(ctx, "pack_field_length" ); |
508 | length -= 1; |
509 | if(length < pack_field_len) return VC_CONTAINER_ERROR_CORRUPTED; |
510 | SKIP_BYTES(ctx, pack_field_len); /* pack_header */ |
511 | length -= pack_field_len; |
512 | } |
513 | |
514 | if (packet_seq_counter) |
515 | { |
516 | if(length < 2) return VC_CONTAINER_ERROR_CORRUPTED; |
517 | if(READ_BYTES(ctx, header, 2) != 2) return VC_CONTAINER_ERROR_EOS; |
518 | BITS_INIT(ctx, &bits, header, 2); |
519 | |
520 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
521 | BITS_SKIP(ctx, &bits, 7, "program_packet_sequence_counter" ); |
522 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
523 | BITS_SKIP(ctx, &bits, 1, "MPEG1_MPEG2_identifier" ); |
524 | BITS_SKIP(ctx, &bits, 6, "original_stuff_length" ); |
525 | length -= 2; |
526 | } |
527 | |
528 | if (pstd_buffer) |
529 | { |
530 | if(length < 2) return VC_CONTAINER_ERROR_CORRUPTED; |
531 | if(READ_BYTES(ctx, header, 2) != 2) return VC_CONTAINER_ERROR_EOS; |
532 | BITS_INIT(ctx, &bits, header, 2); |
533 | |
534 | if(BITS_READ_U32(ctx, &bits, 2, "'01' marker bits" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
535 | BITS_SKIP(ctx, &bits, 1, "P-STD_buffer_scale" ); |
536 | BITS_SKIP(ctx, &bits, 13, "P-STD_buffer_size" ); |
537 | length -= 2; |
538 | } |
539 | |
540 | if (extension2) |
541 | { |
542 | uint8_t ext_field_len; |
543 | |
544 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
545 | if(READ_BYTES(ctx, &ext_field_len, 1) != 1) return VC_CONTAINER_ERROR_EOS; |
546 | length -= 1; |
547 | |
548 | if((ext_field_len & 0x80) != 0x80) return VC_CONTAINER_ERROR_CORRUPTED; /* marker_bit */ |
549 | ext_field_len &= ~0x80; |
550 | LOG_FORMAT(ctx, "PES_extension_field_length %d" , ext_field_len); |
551 | |
552 | for (i = 0; i < ext_field_len; i++) |
553 | { |
554 | SKIP_U8(ctx, "reserved" ); |
555 | length--; |
556 | } |
557 | } |
558 | |
559 | ctx->priv->module->level--; |
560 | |
561 | *p_length = *p_length - length; /* Number of bytes read from stream */ |
562 | |
563 | return VC_CONTAINER_SUCCESS; |
564 | } |
565 | |
566 | /*****************************************************************************/ |
567 | static VC_CONTAINER_STATUS_T ( VC_CONTAINER_T *ctx, |
568 | uint32_t *p_length, int64_t *p_pts, int64_t *p_dts ) |
569 | { |
570 | VC_CONTAINER_STATUS_T status; |
571 | VC_CONTAINER_BITS_T bits; |
572 | uint32_t size, length = *p_length; |
573 | unsigned int pts_dts; |
574 | uint8_t [10]; |
575 | |
576 | if(length < 3) return VC_CONTAINER_ERROR_CORRUPTED; |
577 | |
578 | if ((PEEK_U8(ctx) & 0xC0) == 0x80) /* program stream */ |
579 | { |
580 | unsigned int escr, es_rate, dsm_trick_mode, additional_copy_info, pes_crc, pes_extension; |
581 | unsigned int ; |
582 | |
583 | if(READ_BYTES(ctx, header, 3) != 3) return VC_CONTAINER_ERROR_EOS; |
584 | BITS_INIT(ctx, &bits, header, 3); |
585 | |
586 | if (BITS_READ_U32(ctx, &bits, 2, "'10' marker bits" ) != 0x2) return VC_CONTAINER_ERROR_CORRUPTED; |
587 | BITS_SKIP(ctx, &bits, 2, "PES_scrambling_control" ); |
588 | BITS_SKIP(ctx, &bits, 1, "PES_priority" ); |
589 | BITS_SKIP(ctx, &bits, 1, "data_alignment_indicator" ); |
590 | BITS_SKIP(ctx, &bits, 1, "copyright" ); |
591 | BITS_SKIP(ctx, &bits, 1, "original_or_copy" ); |
592 | pts_dts = BITS_READ_U32(ctx, &bits, 2, "PTS_DTS_flags" ); |
593 | escr = BITS_READ_U32(ctx, &bits, 1, "ESCR_flag" ); |
594 | es_rate = BITS_READ_U32(ctx, &bits, 1, "ES_rate_flag" ); |
595 | dsm_trick_mode = BITS_READ_U32(ctx, &bits, 1, "DSM_trick_mode_flag" ); |
596 | additional_copy_info = BITS_READ_U32(ctx, &bits, 1, "additional_copy_info_flag" ); |
597 | pes_crc = BITS_READ_U32(ctx, &bits, 1, "PES_CRC_flag" ); |
598 | pes_extension = BITS_READ_U32(ctx, &bits, 1, "PES_extension_flag" ); |
599 | header_length = BITS_READ_U32(ctx, &bits, 8, "PES_header_data_length" ); |
600 | length -= 3; |
601 | |
602 | size = length; |
603 | status = ps_read_pes_time(ctx, &size, pts_dts, p_pts, p_dts); |
604 | if (status && status != VC_CONTAINER_ERROR_NOT_FOUND) return status; |
605 | length -= size; |
606 | header_length -= size; |
607 | |
608 | if (escr) |
609 | { |
610 | /* Elementary stream clock reference */ |
611 | int64_t escr; |
612 | |
613 | ctx->priv->module->level++; |
614 | if(length < 6) return VC_CONTAINER_ERROR_CORRUPTED; |
615 | if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS; |
616 | BITS_INIT(ctx, &bits, header, 6); |
617 | |
618 | BITS_SKIP(ctx, &bits, 2, "reserved_bits" ); |
619 | escr = BITS_READ_U32(ctx, &bits, 3, "ESCR_base [32..30]" ) << 30; |
620 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
621 | escr |= BITS_READ_U32(ctx, &bits, 15, "ESCR_base [29..15]" ) << 15; |
622 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
623 | escr |= BITS_READ_U32(ctx, &bits, 15, "ESCR_base [14..0]" ); |
624 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
625 | BITS_READ_U32(ctx, &bits, 9, "ESCR_extension" ); |
626 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
627 | |
628 | LOG_FORMAT(ctx, "ESCR_base %" PRId64, escr); |
629 | length -= 6; |
630 | header_length -= 6; |
631 | ctx->priv->module->level--; |
632 | } |
633 | |
634 | if (es_rate) |
635 | { |
636 | /* Elementary stream rate */ |
637 | if(length < 3) return VC_CONTAINER_ERROR_CORRUPTED; |
638 | if(READ_BYTES(ctx, header, 3) != 3) return VC_CONTAINER_ERROR_EOS; |
639 | BITS_INIT(ctx, &bits, header, 3); |
640 | |
641 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
642 | BITS_READ_U32(ctx, &bits, 22, "ES_rate" ); |
643 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
644 | length -= 3; |
645 | header_length -= 3; |
646 | } |
647 | |
648 | if (dsm_trick_mode) |
649 | { |
650 | unsigned int trick_mode; |
651 | |
652 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
653 | if(READ_BYTES(ctx, header, 1) != 1) return VC_CONTAINER_ERROR_EOS; |
654 | BITS_INIT(ctx, &bits, header, 1); |
655 | |
656 | trick_mode = BITS_READ_U32(ctx, &bits, 3, "trick_mode_control" ); |
657 | if (trick_mode == 0x0 /* fast_forward */) |
658 | { |
659 | BITS_SKIP(ctx, &bits, 2, "field_id" ); |
660 | BITS_SKIP(ctx, &bits, 1, "intra_slice_refresh" ); |
661 | BITS_SKIP(ctx, &bits, 2, "frequency_truncation" ); |
662 | } |
663 | else if (trick_mode == 0x1 /* slow_motion */) |
664 | { |
665 | BITS_SKIP(ctx, &bits, 5, "rep_cntrl" ); |
666 | } |
667 | else if (trick_mode == 0x2 /* freeze_frame */) |
668 | { |
669 | BITS_SKIP(ctx, &bits, 2, "field_id" ); |
670 | BITS_SKIP(ctx, &bits, 3, "reserved_bits" ); |
671 | } |
672 | else if (trick_mode == 0x3 /* fast_reverse */) |
673 | { |
674 | BITS_SKIP(ctx, &bits, 2, "field_id" ); |
675 | BITS_SKIP(ctx, &bits, 1, "intra_slice_refresh" ); |
676 | BITS_SKIP(ctx, &bits, 2, "frequency_truncation" ); |
677 | } |
678 | else if (trick_mode == 0x4 /* slow_reverse */) |
679 | BITS_SKIP(ctx, &bits, 5, "rep_cntrl" ); |
680 | else |
681 | BITS_SKIP(ctx, &bits, 5, "5 reserved_bits" ); |
682 | |
683 | length -= 1; |
684 | header_length -= 1; |
685 | } |
686 | |
687 | if (additional_copy_info) |
688 | { |
689 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
690 | if(READ_BYTES(ctx, header, 1) != 1) return VC_CONTAINER_ERROR_EOS; |
691 | BITS_INIT(ctx, &bits, header, 1); |
692 | |
693 | if(BITS_READ_U32(ctx, &bits, 1, "marker_bit" ) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
694 | BITS_SKIP(ctx, &bits, 7, "additional_copy_info" ); |
695 | |
696 | length -= 1; |
697 | header_length -= 1; |
698 | } |
699 | |
700 | if (pes_crc) |
701 | { |
702 | SKIP_U16(ctx, "previous_PES_packet_CRC" ); |
703 | length -= 2; |
704 | header_length -= 2; |
705 | } |
706 | |
707 | if (pes_extension) |
708 | { |
709 | size = length; |
710 | if ((status = ps_read_pes_extension(ctx, &size)) != VC_CONTAINER_SUCCESS) return status; |
711 | length -= size; |
712 | header_length -= size; |
713 | } |
714 | |
715 | if (header_length <= length) |
716 | { |
717 | SKIP_BYTES(ctx, header_length); /* header stuffing */ |
718 | length -= header_length; |
719 | } |
720 | } |
721 | else /* MPEG 1 PES header */ |
722 | { |
723 | if(length < 12) return VC_CONTAINER_ERROR_CORRUPTED; |
724 | |
725 | while (PEEK_U8(ctx) == 0xFF && length > 0) |
726 | { |
727 | SKIP_U8(ctx, "stuffing" ); |
728 | length--; |
729 | } |
730 | |
731 | if (length == 0) return VC_CONTAINER_ERROR_CORRUPTED; |
732 | |
733 | if ((PEEK_U8(ctx) & 0xC0) == 0x40) |
734 | { |
735 | if(length < 2) return VC_CONTAINER_ERROR_CORRUPTED; |
736 | SKIP_U8(ctx, "???" ); |
737 | SKIP_U8(ctx, "???" ); |
738 | length -= 2; |
739 | } |
740 | |
741 | pts_dts = (PEEK_U8(ctx) & 0x30) >> 4; |
742 | size = length; |
743 | status = ps_read_pes_time(ctx, &size, pts_dts, p_pts, p_dts); |
744 | if (status && status != VC_CONTAINER_ERROR_NOT_FOUND) |
745 | return status; |
746 | length -= size; |
747 | |
748 | if (status == VC_CONTAINER_ERROR_NOT_FOUND) |
749 | { |
750 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
751 | SKIP_U8(ctx, "???" ); |
752 | length -= 1; |
753 | } |
754 | } |
755 | |
756 | *p_length = length; |
757 | return STREAM_STATUS(ctx); |
758 | } |
759 | |
760 | /*****************************************************************************/ |
761 | static VC_CONTAINER_STATUS_T ps_read_private_stream_1_coding( VC_CONTAINER_T *ctx, |
762 | VC_CONTAINER_ES_TYPE_T *p_type, VC_CONTAINER_FOURCC_T *p_codec, |
763 | uint32_t *substream_id, uint32_t *p_length ) |
764 | { |
765 | VC_CONTAINER_ES_TYPE_T type = VC_CONTAINER_ES_TYPE_UNKNOWN; |
766 | VC_CONTAINER_FOURCC_T codec = VC_CONTAINER_CODEC_UNKNOWN; |
767 | uint32_t length; |
768 | uint8_t id = 0; |
769 | |
770 | length = *p_length; |
771 | |
772 | if(length < 1) return VC_CONTAINER_ERROR_CORRUPTED; |
773 | if(READ_BYTES(ctx, &id, 1) != 1) return VC_CONTAINER_ERROR_EOS; |
774 | length -= 1; |
775 | |
776 | LOG_FORMAT(ctx, "private_stream_1 byte: 0x%x (%u)" , id, id); |
777 | |
778 | if (id >= 0x20 && id <= 0x3f) |
779 | { |
780 | type = VC_CONTAINER_ES_TYPE_SUBPICTURE; |
781 | codec = VC_CONTAINER_CODEC_UNKNOWN; |
782 | } |
783 | else if ((id >= 0x80 && id <= 0x87) || (id >= 0xC0 && id <= 0xCF)) |
784 | { |
785 | type = VC_CONTAINER_ES_TYPE_AUDIO; |
786 | codec = VC_CONTAINER_CODEC_AC3; |
787 | } |
788 | else if ((id >= 0x88 && id <= 0x8F) || (id >= 0x98 && id <= 0x9F)) |
789 | { |
790 | type = VC_CONTAINER_ES_TYPE_AUDIO; |
791 | codec = VC_CONTAINER_CODEC_DTS; |
792 | } |
793 | else if (id >= 0xA0 && id <= 0xBF) |
794 | { |
795 | type = VC_CONTAINER_ES_TYPE_AUDIO; |
796 | codec = VC_CONTAINER_CODEC_PCM_SIGNED; |
797 | } |
798 | else |
799 | { |
800 | LOG_FORMAT(ctx, "Unknown private_stream_1 byte: 0x%x (%u)" , id, id); |
801 | } |
802 | |
803 | *substream_id = id; |
804 | *p_type = type; |
805 | *p_codec = codec; |
806 | *p_length = length; |
807 | |
808 | return VC_CONTAINER_SUCCESS; |
809 | } |
810 | |
811 | /*****************************************************************************/ |
812 | static VC_CONTAINER_STATUS_T ps_read_private_stream_1_format( VC_CONTAINER_T *ctx, |
813 | VC_CONTAINER_ES_FORMAT_T *format, uint32_t *length ) |
814 | { |
815 | uint8_t [8]; |
816 | VC_CONTAINER_BITS_T bits; |
817 | |
818 | if (format->codec == VC_CONTAINER_CODEC_PCM_SIGNED) |
819 | { |
820 | static const unsigned fs_tab[4] = { 48000, 96000, 44100, 32000 }; |
821 | static const unsigned bps_tab[] = {16, 20, 24, 0}; |
822 | |
823 | unsigned fs, bps, nchan; |
824 | |
825 | if(*length < 6) return VC_CONTAINER_ERROR_CORRUPTED; |
826 | if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS; |
827 | BITS_INIT(ctx, &bits, header, 6); |
828 | |
829 | BITS_SKIP(ctx, &bits, 8, "???" ); |
830 | BITS_SKIP(ctx, &bits, 8, "???" ); |
831 | BITS_SKIP(ctx, &bits, 8, "???" ); |
832 | BITS_SKIP(ctx, &bits, 1, "emphasis" ); |
833 | BITS_SKIP(ctx, &bits, 1, "mute" ); |
834 | BITS_SKIP(ctx, &bits, 1, "reserved" ); |
835 | BITS_SKIP(ctx, &bits, 5, "frame number" ); |
836 | bps = BITS_READ_U32(ctx, &bits, 2, "quant" ); |
837 | fs = BITS_READ_U32(ctx, &bits, 2, "freq" ); |
838 | BITS_SKIP(ctx, &bits, 1, "reserved" ); |
839 | nchan = BITS_READ_U32(ctx, &bits, 3, "channels" ); |
840 | *length -= 6; |
841 | |
842 | format->type->audio.sample_rate = fs_tab[fs]; |
843 | format->type->audio.bits_per_sample = bps_tab[bps]; |
844 | format->type->audio.channels = nchan + 1; |
845 | format->type->audio.block_align = |
846 | (format->type->audio.channels * format->type->audio.bits_per_sample + 7 ) / 8; |
847 | } |
848 | else |
849 | { |
850 | if(*length < 3) return VC_CONTAINER_ERROR_CORRUPTED; |
851 | SKIP_U8(ctx, "num of frames" ); |
852 | SKIP_U8(ctx, "start pos hi" ); |
853 | SKIP_U8(ctx, "start pos lo" ); |
854 | *length -= 3; |
855 | } |
856 | |
857 | return STREAM_STATUS(ctx); |
858 | } |
859 | |
860 | /*****************************************************************************/ |
861 | static VC_CONTAINER_STATUS_T ps_read_pes_packet( VC_CONTAINER_T *ctx ) |
862 | { |
863 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
864 | VC_CONTAINER_STATUS_T status; |
865 | uint8_t [10]; |
866 | VC_CONTAINER_BITS_T bits; |
867 | uint32_t length, stream_id, substream_id = 0; |
868 | VC_CONTAINER_ES_TYPE_T type; |
869 | VC_CONTAINER_FOURCC_T codec, variant = 0; |
870 | VC_CONTAINER_TRACK_T *track; |
871 | int64_t pts, dts; |
872 | |
873 | if(_READ_U24(ctx) != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; |
874 | if(READ_BYTES(ctx, header, 3) != 3) return VC_CONTAINER_ERROR_EOS; |
875 | LOG_FORMAT(ctx, "pes_packet_header" ); |
876 | module->level++; |
877 | |
878 | BITS_INIT(ctx, &bits, header, 3); |
879 | stream_id = BITS_READ_U32(ctx, &bits, 8, "stream_id" ); |
880 | length = BITS_READ_U32(ctx, &bits, 16, "PES_packet_length" ); |
881 | |
882 | if (stream_id < 0xBC) return VC_CONTAINER_ERROR_CORRUPTED; |
883 | |
884 | if (stream_id == 0xBC /* program_stream_map */ || stream_id == 0xBE /* padding_stream */ || |
885 | stream_id == 0xBF /* private_stream_2 */ || stream_id == 0xF0 /* ECM */ || |
886 | stream_id == 0xF1 /* EMM */ || stream_id == 0xFF /* program_stream_directory */ || |
887 | stream_id == 0xF2 /* DSMCC_stream */ || stream_id == 0xF8 /* ITU-T Rec. H.222.1 type E */) |
888 | goto skip; |
889 | |
890 | /* Parse PES packet header */ |
891 | if ((status = ps_read_pes_packet_header(ctx, &length, &pts, &dts)) != VC_CONTAINER_SUCCESS) |
892 | return status; |
893 | |
894 | /* For private_stream_1, encoding format is stored in the payload */ |
895 | if (stream_id == 0xBD) |
896 | { |
897 | status = ps_read_private_stream_1_coding(ctx, &type, &codec, &substream_id, &length); |
898 | if (status) return status; |
899 | } |
900 | else |
901 | ps_get_stream_coding(ctx, stream_id, &type, &codec, &variant); |
902 | |
903 | /* Check that we know what to do with this track */ |
904 | if(type == VC_CONTAINER_ES_TYPE_UNKNOWN || codec == VC_CONTAINER_CODEC_UNKNOWN) |
905 | goto skip; |
906 | |
907 | track = ps_find_track(ctx, stream_id, substream_id, module->searching_tracks); |
908 | if(!track) goto skip; |
909 | |
910 | if (module->searching_tracks) |
911 | { |
912 | track->is_enabled = true; |
913 | track->format->es_type = type; |
914 | track->format->codec = codec; |
915 | track->format->codec_variant = variant; |
916 | |
917 | /* For private_stream_1, we need to parse payload further to get elementary stream |
918 | format */ |
919 | if (stream_id == 0xBD) |
920 | { |
921 | uint32_t current_length = length; |
922 | status = ps_read_private_stream_1_format(ctx, track->format, &length); |
923 | if (status) return status; |
924 | track->priv->module->payload_offset = current_length - length; |
925 | } |
926 | |
927 | goto skip; |
928 | } |
929 | else |
930 | { |
931 | unsigned i; |
932 | SKIP_BYTES(ctx, track->priv->module->payload_offset); |
933 | length -= track->priv->module->payload_offset; |
934 | |
935 | /* Find track index */ |
936 | for(i = 0; i < ctx->tracks_num; i++) |
937 | if(ctx->tracks[i] == track) break; |
938 | vc_container_assert(i < ctx->tracks_num); |
939 | |
940 | module->packet_track = i; |
941 | module->packet_data_size = length; |
942 | module->packet_pts = pts; |
943 | module->packet_dts = dts; |
944 | } |
945 | |
946 | end: |
947 | module->level--; |
948 | return STREAM_STATUS(ctx); |
949 | |
950 | skip: |
951 | SKIP_BYTES(ctx, length); /* remaining PES_packet_data */ |
952 | goto end; |
953 | } |
954 | |
955 | /*****************************************************************************/ |
956 | STATIC_INLINE VC_CONTAINER_STATUS_T ps_find_pes_packet( VC_CONTAINER_T *ctx ) |
957 | { |
958 | VC_CONTAINER_STATUS_T status; |
959 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
960 | uint8_t buffer[4]; |
961 | unsigned int i; |
962 | |
963 | module->packet_data_size = 0; |
964 | |
965 | for (i = 0; i != PS_PACK_SCAN_MAX; ++i) |
966 | { |
967 | if((status = ps_find_start_code(ctx, buffer)) != VC_CONTAINER_SUCCESS) |
968 | break; |
969 | |
970 | if (buffer[3] == 0xBA && ((status = ps_read_pack_header(ctx)) != VC_CONTAINER_SUCCESS)) |
971 | continue; /* pack start code but parsing failed, goto resync */ |
972 | |
973 | if ((status = ps_read_pes_packet(ctx)) == VC_CONTAINER_SUCCESS) |
974 | break; |
975 | } |
976 | |
977 | return status; |
978 | } |
979 | |
980 | /***************************************************************************** |
981 | Functions exported as part of the Container Module API |
982 | *****************************************************************************/ |
983 | |
984 | /*****************************************************************************/ |
985 | static VC_CONTAINER_STATUS_T ps_reader_read( VC_CONTAINER_T *ctx, |
986 | VC_CONTAINER_PACKET_T *p_packet, uint32_t flags ) |
987 | { |
988 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
989 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
990 | |
991 | vc_container_assert(!module->searching_tracks); |
992 | |
993 | while(!module->packet_data_left) |
994 | { |
995 | if(ps_find_pes_packet(ctx) != VC_CONTAINER_SUCCESS) |
996 | { |
997 | status = VC_CONTAINER_ERROR_EOS; |
998 | goto error; |
999 | } |
1000 | |
1001 | module->packet_data_left = module->packet_data_size; |
1002 | } |
1003 | |
1004 | p_packet->track = module->packet_track; |
1005 | p_packet->size = module->packet_data_left; |
1006 | p_packet->flags = 0; |
1007 | p_packet->pts = ps_pes_time_to_us(ctx, module->packet_pts); |
1008 | p_packet->dts = ps_pes_time_to_us(ctx, module->packet_dts); |
1009 | |
1010 | if (flags & VC_CONTAINER_READ_FLAG_SKIP) |
1011 | { |
1012 | SKIP_BYTES(ctx, module->packet_data_left); |
1013 | module->packet_data_left = 0; |
1014 | return VC_CONTAINER_SUCCESS; |
1015 | } |
1016 | |
1017 | if (flags & VC_CONTAINER_READ_FLAG_INFO) |
1018 | return VC_CONTAINER_SUCCESS; |
1019 | |
1020 | p_packet->size = MIN(p_packet->buffer_size, module->packet_data_left); |
1021 | p_packet->size = READ_BYTES(ctx, p_packet->data, p_packet->size); |
1022 | module->packet_data_left -= p_packet->size; |
1023 | |
1024 | /* Temporary work-around for lpcm audio */ |
1025 | { |
1026 | VC_CONTAINER_TRACK_T *track = ctx->tracks[module->packet_track]; |
1027 | if (track->format->codec == VC_CONTAINER_CODEC_PCM_SIGNED) |
1028 | { |
1029 | unsigned i; |
1030 | uint16_t *ptr = (uint16_t *)p_packet->data; |
1031 | |
1032 | for (i = 0; i < p_packet->size / 2; i ++) |
1033 | { |
1034 | uint32_t v = *ptr; |
1035 | *ptr++ = v >> 8 | ( (v & 0xFF) << 8 ); |
1036 | } |
1037 | } |
1038 | } |
1039 | |
1040 | if (module->packet_data_left) |
1041 | module->packet_pts = module->packet_dts = VC_CONTAINER_TIME_UNKNOWN; |
1042 | |
1043 | return STREAM_STATUS(ctx); |
1044 | |
1045 | error: |
1046 | if (status == VC_CONTAINER_ERROR_EOS) |
1047 | { |
1048 | /* Reset time reference and calculation state */ |
1049 | ctx->priv->module->scr = VC_CONTAINER_TIME_UNKNOWN; |
1050 | ctx->priv->module->scr_bias = -module->scr_offset; |
1051 | } |
1052 | |
1053 | return status; |
1054 | } |
1055 | |
1056 | /*****************************************************************************/ |
1057 | static VC_CONTAINER_STATUS_T ps_reader_seek( VC_CONTAINER_T *ctx, |
1058 | int64_t *p_offset, VC_CONTAINER_SEEK_MODE_T mode, VC_CONTAINER_SEEK_FLAGS_T flags ) |
1059 | { |
1060 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
1061 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1062 | uint64_t seekpos, position; |
1063 | int64_t scr; |
1064 | |
1065 | VC_CONTAINER_PARAM_UNUSED(flags); |
1066 | |
1067 | if (mode != VC_CONTAINER_SEEK_MODE_TIME || !STREAM_SEEKABLE(ctx)) |
1068 | return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION; |
1069 | |
1070 | position = STREAM_POSITION(ctx); |
1071 | scr = module->scr; |
1072 | |
1073 | if (*p_offset == INT64_C(0)) |
1074 | seekpos = module->data_offset; |
1075 | else |
1076 | { |
1077 | if (!ctx->duration) |
1078 | return VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION; |
1079 | |
1080 | /* The following is an estimate that might be quite inaccurate */ |
1081 | seekpos = module->data_offset + (*p_offset * module->data_size) / ctx->duration; |
1082 | } |
1083 | |
1084 | SEEK(ctx, seekpos); |
1085 | module->scr = module->scr_offset; |
1086 | status = ps_find_pes_packet(ctx); |
1087 | if (status && status != VC_CONTAINER_ERROR_EOS) |
1088 | goto error; |
1089 | |
1090 | module->packet_data_left = module->packet_data_size; |
1091 | |
1092 | if (module->packet_pts != VC_CONTAINER_TIME_UNKNOWN) |
1093 | *p_offset = ps_pes_time_to_us(ctx, module->packet_pts); |
1094 | else if (module->data_size) |
1095 | *p_offset = (STREAM_POSITION(ctx) - module->data_offset) * ctx->duration / module->data_size; |
1096 | |
1097 | return STREAM_STATUS(ctx); |
1098 | |
1099 | error: |
1100 | module->scr = scr; |
1101 | SEEK(ctx, position); |
1102 | return status; |
1103 | } |
1104 | |
1105 | /*****************************************************************************/ |
1106 | static VC_CONTAINER_STATUS_T ps_reader_close( VC_CONTAINER_T *ctx ) |
1107 | { |
1108 | VC_CONTAINER_MODULE_T *module = ctx->priv->module; |
1109 | unsigned int i; |
1110 | |
1111 | for(i = 0; i < ctx->tracks_num; i++) |
1112 | vc_container_free_track(ctx, ctx->tracks[i]); |
1113 | free(module); |
1114 | return VC_CONTAINER_SUCCESS; |
1115 | } |
1116 | |
1117 | /*****************************************************************************/ |
1118 | VC_CONTAINER_STATUS_T ps_reader_open( VC_CONTAINER_T *ctx ) |
1119 | { |
1120 | const char *extension = vc_uri_path_extension(ctx->priv->uri); |
1121 | VC_CONTAINER_MODULE_T *module = 0; |
1122 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1123 | uint8_t buffer[4]; |
1124 | unsigned int i; |
1125 | |
1126 | /* Check if the user has specified a container */ |
1127 | vc_uri_find_query(ctx->priv->uri, 0, "container" , &extension); |
1128 | |
1129 | /* Since MPEG is difficult to auto-detect, we use the extension as |
1130 | part of the autodetection */ |
1131 | if(!extension) |
1132 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1133 | if(strcasecmp(extension, "ps" ) && strcasecmp(extension, "vob" ) && |
1134 | strcasecmp(extension, "mpg" ) && strcasecmp(extension, "mp2" ) && |
1135 | strcasecmp(extension, "mp3" ) && strcasecmp(extension, "mpeg" )) |
1136 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1137 | |
1138 | if((status = ps_find_start_code(ctx, buffer)) != VC_CONTAINER_SUCCESS) |
1139 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; /* We didn't find a valid pack or PES packet */ |
1140 | |
1141 | LOG_DEBUG(ctx, "using ps reader" ); |
1142 | |
1143 | /* We are probably dealing with a PS file */ |
1144 | LOG_FORMAT(ctx, "MPEG PS reader, found start code: 0x%02x%02x%02x%02x" , |
1145 | buffer[0], buffer[1], buffer[2], buffer[3]); |
1146 | |
1147 | /* Need to allocate context before searching for streams */ |
1148 | module = malloc(sizeof(*module)); |
1149 | if(!module) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; } |
1150 | memset(module, 0, sizeof(*module)); |
1151 | ctx->priv->module = module; |
1152 | ctx->tracks = module->tracks; |
1153 | |
1154 | /* Store offset so we can get back to what we consider the first pack or |
1155 | packet */ |
1156 | module->data_offset = STREAM_POSITION(ctx); |
1157 | |
1158 | /* Search for tracks, reset time reference and calculation state first */ |
1159 | ctx->priv->module->scr_offset = ctx->priv->module->scr = VC_CONTAINER_TIME_UNKNOWN; |
1160 | ctx->priv->module->searching_tracks = true; |
1161 | |
1162 | for (i = 0; i != PS_PACK_SCAN_MAX; ++i) |
1163 | { |
1164 | if (buffer[3] == 0xBA && (ps_read_pack_header(ctx) != VC_CONTAINER_SUCCESS)) |
1165 | goto resync; |
1166 | |
1167 | if (ps_read_pes_packet(ctx) == VC_CONTAINER_SUCCESS) |
1168 | continue; |
1169 | |
1170 | resync: |
1171 | LOG_DEBUG(ctx, "Lost sync, scanning for start code" ); |
1172 | if((status = ps_find_start_code(ctx, buffer)) != VC_CONTAINER_SUCCESS) |
1173 | return VC_CONTAINER_ERROR_CORRUPTED; |
1174 | LOG_DEBUG(ctx, "MPEG PS reader, found start code: 0x%" PRIx64" (%" PRId64"): 0x%02x%02x%02x%02x" , |
1175 | STREAM_POSITION(ctx), STREAM_POSITION(ctx), buffer[0], buffer[1], buffer[2], buffer[3]); |
1176 | } |
1177 | |
1178 | /* Seek back to the start of data */ |
1179 | SEEK(ctx, module->data_offset); |
1180 | |
1181 | /* Bail out if we didn't find any tracks */ |
1182 | if(!ctx->tracks_num) |
1183 | { |
1184 | status = VC_CONTAINER_ERROR_NO_TRACK_AVAILABLE; |
1185 | goto error; |
1186 | } |
1187 | |
1188 | /* Set data size (necessary for seeking) */ |
1189 | module->data_size = MAX(ctx->priv->io->size - module->data_offset, INT64_C(0)); |
1190 | |
1191 | /* Estimate data rate (necessary for seeking) */ |
1192 | if(STREAM_SEEKABLE(ctx)) |
1193 | { |
1194 | /* Estimate data rate by jumping in the stream */ |
1195 | #define PS_PACK_SEARCH_MAX 64 |
1196 | uint64_t position = module->data_offset; |
1197 | for (i = 0; i != PS_PACK_SEARCH_MAX; ++i) |
1198 | { |
1199 | position += (module->data_size / (PS_PACK_SEARCH_MAX + 1)); |
1200 | SEEK(ctx, position); |
1201 | |
1202 | for(;;) |
1203 | { |
1204 | if(ps_find_start_code(ctx, buffer) != VC_CONTAINER_SUCCESS) |
1205 | break; |
1206 | |
1207 | if (buffer[3] == 0xBA) |
1208 | { |
1209 | if (ps_read_pack_header(ctx) == VC_CONTAINER_SUCCESS) |
1210 | break; |
1211 | } |
1212 | else |
1213 | { |
1214 | /* Skip PES packet */ |
1215 | unsigned length; |
1216 | SKIP_U32(ctx, "PES packet startcode" ); |
1217 | length = READ_U16(ctx, "PES packet length" ); |
1218 | SKIP_BYTES(ctx, length); |
1219 | } |
1220 | } |
1221 | } |
1222 | |
1223 | ctx->duration = (INT64_C(1000000) * module->data_size) / (module->data_rate); |
1224 | |
1225 | if (module->scr > module->scr_offset) |
1226 | { |
1227 | int64_t delta = (module->scr - module->scr_offset) / INT64_C(27); |
1228 | |
1229 | if (delta > ctx->duration) |
1230 | ctx->duration = delta; |
1231 | } |
1232 | |
1233 | /* Seek back to the start of data */ |
1234 | SEEK(ctx, module->data_offset); |
1235 | } |
1236 | else |
1237 | { |
1238 | /* For most files, program_mux_rate is not reliable at all */ |
1239 | ctx->duration = (INT64_C(100000) * module->data_size) / (INT64_C(5) * module->mux_rate); |
1240 | } |
1241 | |
1242 | /* Reset time reference and calculation state, we're now ready to read data */ |
1243 | module->scr = VC_CONTAINER_TIME_UNKNOWN; |
1244 | module->scr_bias = VC_CONTAINER_TIME_UNKNOWN; |
1245 | |
1246 | ctx->priv->module->searching_tracks = false; |
1247 | |
1248 | if(STREAM_SEEKABLE(ctx)) ctx->capabilities |= VC_CONTAINER_CAPS_CAN_SEEK; |
1249 | |
1250 | ctx->priv->pf_close = ps_reader_close; |
1251 | ctx->priv->pf_read = ps_reader_read; |
1252 | ctx->priv->pf_seek = ps_reader_seek; |
1253 | |
1254 | return STREAM_STATUS(ctx); |
1255 | |
1256 | error: |
1257 | LOG_DEBUG(ctx, "ps: error opening stream (%i)" , status); |
1258 | if(module) ps_reader_close(ctx); |
1259 | return status; |
1260 | } |
1261 | |
1262 | /******************************************************************************** |
1263 | Entrypoint function |
1264 | ********************************************************************************/ |
1265 | |
1266 | #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__) |
1267 | # pragma weak reader_open ps_reader_open |
1268 | #endif |
1269 | |