/**************************************************************************//** * Read/skip data from the container. * Can also be used to query information about the next block of data. * * @param p_ctx The reader context. * @param p_packet The container packet information, or NULL. * @param flags The container read flags. * @return The resulting status of the function. */ static VC_CONTAINER_STATUS_T rtp_reader_read( VC_CONTAINER_T *p_ctx, VC_CONTAINER_PACKET_T *p_packet, uint32_t flags ) { VC_CONTAINER_TRACK_T *track; VC_CONTAINER_TRACK_MODULE_T *t_module; VC_CONTAINER_STATUS_T status; if((flags & VC_CONTAINER_READ_FLAG_FORCE_TRACK) && p_packet->track) return VC_CONTAINER_ERROR_INVALID_ARGUMENT; track = p_ctx->tracks[0]; t_module = track->priv->module; CLEAR_BIT(t_module->flags, TRACK_NEW_PACKET); while (!BITS_AVAILABLE(p_ctx, &t_module->payload)) { uint32_t bytes_read; /* No data left from last RTP packet, get another one */ bytes_read = READ_BYTES(p_ctx, t_module->buffer, MAXIMUM_PACKET_SIZE); if (!bytes_read) return STREAM_STATUS(p_ctx); BITS_INIT(p_ctx, &t_module->payload, t_module->buffer, bytes_read); decode_rtp_packet_header(p_ctx, t_module); SET_BIT(t_module->flags, TRACK_NEW_PACKET); } if (p_packet) { uint32_t timestamp_top = t_module->timestamp >> 30; /* Determine whether timestamp has wrapped forwards or backwards around zero */ if ((timestamp_top == 0) && (t_module->last_timestamp_top == 3)) t_module->timestamp_wraps++; else if ((timestamp_top == 3) && (t_module->last_timestamp_top == 0)) t_module->timestamp_wraps--; t_module->last_timestamp_top = timestamp_top; p_packet->dts = p_packet->pts = ((int64_t)t_module->timestamp_wraps << 32) | t_module->timestamp; p_packet->track = 0; p_packet->flags = 0; } status = t_module->payload_handler(p_ctx, track, p_packet, flags); if (p_packet && status == VC_CONTAINER_SUCCESS) { /* Adjust timestamps from RTP clock rate to microseconds */ p_packet->pts = p_packet->pts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock; p_packet->dts = p_packet->dts * MICROSECONDS_PER_SECOND / t_module->timestamp_clock; } STREAM_STATUS(p_ctx) = status; return status; }
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); }
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 {