1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON 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
25SOFTWARE, 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/******************************************************************************
42Defines.
43******************************************************************************/
44#define PS_TRACKS_MAX 2
45#define PS_EXTRADATA_MAX 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/******************************************************************************
56Type definitions.
57******************************************************************************/
58typedef 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 extradata[PS_EXTRADATA_MAX];
70
71} VC_CONTAINER_TRACK_MODULE_T;
72
73typedef 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/******************************************************************************
124Function prototypes
125******************************************************************************/
126
127VC_CONTAINER_STATUS_T ps_reader_open( VC_CONTAINER_T * );
128
129/******************************************************************************
130Prototypes for local functions
131******************************************************************************/
132
133/******************************************************************************
134Local Functions
135******************************************************************************/
136
137/** Find the track associated with a PS stream_id */
138static 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/*****************************************************************************/
171STATIC_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/*****************************************************************************/
198static VC_CONTAINER_STATUS_T ps_read_system_header( VC_CONTAINER_T *ctx )
199{
200 uint8_t header[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/*****************************************************************************/
241static VC_CONTAINER_STATUS_T ps_read_pack_header( VC_CONTAINER_T *ctx )
242{
243 VC_CONTAINER_MODULE_T *module = ctx->priv->module;
244 uint8_t header[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/*****************************************************************************/
342static 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/*****************************************************************************/
377static 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/*****************************************************************************/
396static 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 header[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/*****************************************************************************/
473static VC_CONTAINER_STATUS_T ps_read_pes_extension( VC_CONTAINER_T *ctx,
474 uint32_t *p_length )
475{
476 unsigned int pes_private_data, pack_header, packet_seq_counter, pstd_buffer, extension2;
477 uint8_t header[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/*****************************************************************************/
567static VC_CONTAINER_STATUS_T ps_read_pes_packet_header( 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 header[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 header_length;
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/*****************************************************************************/
761static 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/*****************************************************************************/
812static 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 header[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/*****************************************************************************/
861static 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 header[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
946end:
947 module->level--;
948 return STREAM_STATUS(ctx);
949
950skip:
951 SKIP_BYTES(ctx, length); /* remaining PES_packet_data */
952 goto end;
953}
954
955/*****************************************************************************/
956STATIC_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/*****************************************************************************
981Functions exported as part of the Container Module API
982*****************************************************************************/
983
984/*****************************************************************************/
985static 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
1045error:
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/*****************************************************************************/
1057static 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
1099error:
1100 module->scr = scr;
1101 SEEK(ctx, position);
1102 return status;
1103}
1104
1105/*****************************************************************************/
1106static 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/*****************************************************************************/
1118VC_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
1170resync:
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