static VC_CONTAINER_STATUS_T ps_read_system_header( VC_CONTAINER_T *ctx ) { uint8_t header[8]; uint32_t length; VC_CONTAINER_BITS_T bits; if(_READ_U32(ctx) != 0x1BB) return VC_CONTAINER_ERROR_CORRUPTED; LOG_FORMAT(ctx, "system_header"); ctx->priv->module->level++; length = READ_U16(ctx, "header_length"); if(length < 6) return VC_CONTAINER_ERROR_CORRUPTED; if(READ_BYTES(ctx, header, 6) != 6) return VC_CONTAINER_ERROR_EOS; BITS_INIT(ctx, &bits, header, 6); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 22, "rate_bound"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 6, "audio_bound"); BITS_SKIP(ctx, &bits, 1, "fixed_flag"); BITS_SKIP(ctx, &bits, 1, "CSPS_flag"); BITS_SKIP(ctx, &bits, 1, "system_audio_lock_flag"); BITS_SKIP(ctx, &bits, 1, "system_video_lock_flag"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 5, "video_bound"); BITS_SKIP(ctx, &bits, 1, "packet_rate_restriction_flag"); BITS_SKIP(ctx, &bits, 7, "reserved_bits"); length -= 6; while(length >= 3 && (PEEK_U8(ctx) & 0x80)) { SKIP_U8(ctx, "stream_id"); SKIP_BYTES(ctx, 2); length -= 3; } SKIP_BYTES(ctx, length); ctx->priv->module->level--; return STREAM_STATUS(ctx); }
/**************************************************************************//** * Extract the fields of an RTP packet and validate it. * * @param p_ctx The reader context. * @param t_module The track module. * @return True if successful, false if there were not enough bits in the * packet or the packet was invalid. */ static void decode_rtp_packet_header(VC_CONTAINER_T *p_ctx, VC_CONTAINER_TRACK_MODULE_T *t_module) { VC_CONTAINER_BITS_T *payload = &t_module->payload; uint32_t version, has_padding, has_extension, csrc_count, has_marker; uint32_t payload_type, ssrc; uint16_t seq_num; /* Break down fixed header area into component parts */ version = BITS_READ_U32(p_ctx, payload, 2, "Version"); has_padding = BITS_READ_U32(p_ctx, payload, 1, "Has padding"); has_extension = BITS_READ_U32(p_ctx, payload, 1, "Has extension"); csrc_count = BITS_READ_U32(p_ctx, payload, 4, "CSRC count"); has_marker = BITS_READ_U32(p_ctx, payload, 1, "Has marker"); payload_type = BITS_READ_U32(p_ctx, payload, 7, "Payload type"); seq_num = BITS_READ_U16(p_ctx, payload, 16, "Sequence number"); t_module->timestamp = BITS_READ_U32(p_ctx, payload, 32, "Timestamp"); ssrc = BITS_READ_U32(p_ctx, payload, 32, "SSRC"); /* If there was only a partial header, abort immediately */ if (!BITS_VALID(p_ctx, payload)) return; /* Validate version, payload type, sequence number and SSRC, if set */ if (version != 2 || payload_type != t_module->payload_type) { BITS_INVALIDATE(p_ctx, payload); return; } if (BIT_IS_SET(t_module->flags, TRACK_SSRC_SET) && (ssrc != t_module->expected_ssrc)) { LOG_DEBUG(p_ctx, "RTP: Unexpected SSRC (0x%8.8X)", ssrc); BITS_INVALIDATE(p_ctx, payload); return; } /* Check sequence number indicates packet is usable */ if (!update_sequence_number(t_module, seq_num)) { BITS_INVALIDATE(p_ctx, payload); return; } /* Adjust to account for padding, CSRCs and extension */ if (has_padding) { VC_CONTAINER_BITS_T bit_stream; uint32_t available = BITS_BYTES_AVAILABLE(p_ctx, payload); uint8_t padding; BITS_COPY_STREAM(p_ctx, &bit_stream, payload); /* The last byte of the payload is the number of padding bytes, including itself */ BITS_SKIP_BYTES(p_ctx, &bit_stream, available - 1, "Skip to padding length"); padding = BITS_READ_U8(p_ctx, &bit_stream, 8, "Padding length"); BITS_REDUCE_BYTES(p_ctx, payload, padding, "Remove padding"); } /* Each CSRC is 32 bits, so shift count up to skip the right number of bits */ BITS_SKIP(p_ctx, payload, csrc_count << 5, "CSRC section"); if (has_extension) { uint32_t extension_bits; /* Extension header is 16-bit ID (which isn't needed), then 16-bit length in 32-bit words */ BITS_SKIP(p_ctx, payload, 16, "Extension ID"); extension_bits = BITS_READ_U32(p_ctx, payload, 16, "Extension length") << 5; BITS_SKIP(p_ctx, payload, extension_bits, "Extension data"); } /* Record whether or not this RTP packet had the marker bit set */ if (has_marker) SET_BIT(t_module->flags, TRACK_HAS_MARKER); else CLEAR_BIT(t_module->flags, TRACK_HAS_MARKER); /* If it hasn't been set independently, use the first timestamp as a baseline */ if (!t_module->timestamp_base) t_module->timestamp_base = t_module->timestamp; t_module->timestamp -= t_module->timestamp_base; }
static VC_CONTAINER_STATUS_T ps_read_pack_header( VC_CONTAINER_T *ctx ) { VC_CONTAINER_MODULE_T *module = ctx->priv->module; uint8_t header[10]; int64_t scr, scr_base, scr_ext = INT64_C(0); uint64_t pack_offset = STREAM_POSITION(ctx); uint32_t mux_rate, stuffing; VC_CONTAINER_BITS_T bits; VC_CONTAINER_STATUS_T status; if(_READ_U32(ctx) != 0x1BA) return VC_CONTAINER_ERROR_CORRUPTED; LOG_FORMAT(ctx, "pack_header"); module->level++; if (PEEK_U8(ctx) & 0x40) /* program stream */ { if(READ_BYTES(ctx, header, 10) != 10) return VC_CONTAINER_ERROR_EOS; BITS_INIT(ctx, &bits, header, 10); if(BITS_READ_U32(ctx, &bits, 2, "'01' marker bits") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]") << 30; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]") << 15; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]"); LOG_FORMAT(ctx, "system_clock_reference_base %"PRId64, scr_base); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_ext = BITS_READ_U32(ctx, &bits, 9, "system_clock_reference_extension"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; BITS_SKIP(ctx, &bits, 5, "reserved"); stuffing = BITS_READ_U32(ctx, &bits, 3, "pack_stuffing_length"); SKIP_BYTES(ctx, stuffing); } else /* system stream */ { if(READ_BYTES(ctx, header, 8) != 8) return VC_CONTAINER_ERROR_EOS; BITS_INIT(ctx, &bits, header, 8); if(BITS_READ_U32(ctx, &bits, 4, "'0010' marker bits") != 0x2) return VC_CONTAINER_ERROR_CORRUPTED; scr_base = BITS_READ_U32(ctx, &bits, 3, "system_clock_reference_base [32..30]") << 30; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [29..15]") << 15; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; scr_base |= BITS_READ_U32(ctx, &bits, 15, "system_clock_reference_base [14..0]"); LOG_FORMAT(ctx, "system_clock_reference_base %"PRId64, scr_base); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; mux_rate = BITS_READ_U32(ctx, &bits, 22, "program_mux_rate"); if(BITS_READ_U32(ctx, &bits, 1, "marker_bit") != 0x1) return VC_CONTAINER_ERROR_CORRUPTED; } if ((status = STREAM_STATUS(ctx)) != VC_CONTAINER_SUCCESS) return status; module->level--; /* Set or update system_clock_reference, adjust bias if necessary */ scr = scr_base * INT64_C(300) + scr_ext; if (module->scr_offset == VC_CONTAINER_TIME_UNKNOWN) module->scr_offset = scr; if (module->scr == VC_CONTAINER_TIME_UNKNOWN) module->scr_bias = -scr; else if (scr < module->scr) module->scr_bias = module->scr - scr; if (module->scr != VC_CONTAINER_TIME_UNKNOWN) { /* system_clock_reference is not necessarily continuous across the entire stream */ if (scr > module->scr) { int64_t data_rate; data_rate = INT64_C(27000000) * (pack_offset - module->pack_offset) / (scr - module->scr); if (module->data_rate) { /* Simple moving average over data rate seen so far */ module->data_rate = (module->data_rate * 31 + data_rate) >> 5; } else {