| 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 | |