static inline void bs_skip_u(bs_t* b, int n) { int i; for ( i = 0; i < n; i++ ) { bs_skip_u1( b ); } }
int pes_read_header(pes_header_t *ph, bs_t *b) { int PES_packet_start = bs_pos(b); // we *really* care about bytes 0..19, as we can cheat and manipulate PTS/DTS this way if (bs_bytes_left(b) < 20) return 0; // bytes 0..2 uint32_t pes_packet_start_code = bs_read_u24(b); if (pes_packet_start_code != PES_PACKET_START_CODE_PREFIX) { int actually_read = bs_pos(b) - PES_packet_start; b->p -= actually_read; // undo the read LOG_WARN_ARGS("PES packet starts with 0x%06X instead of expected start code 0x%06X, skipping it", pes_packet_start_code, PES_PACKET_START_CODE_PREFIX); return 0; // bail out! something is fishy! } // bytes 3..5 ph->stream_id = bs_read_u8(b); ph->PES_packet_length = bs_read_u16(b); if (HAS_PES_HEADER(ph->stream_id)) { // byte 6 bs_skip_u(b, 2); ph->PES_scrambling_control = bs_read_u(b, 2); ph->PES_priority = bs_read_u1(b); ph->data_alignment_indicator = bs_read_u1(b); ph->copyright = bs_read_u1(b); ph->original_or_copy = bs_read_u1(b); // byte 7 ph->PTS_DTS_flags = bs_read_u(b, 2); ph->ESCR_flag = bs_read_u1(b); ph->ES_rate_flag = bs_read_u1(b); ph->DSM_trick_mode_flag = bs_read_u1(b); ph->additional_copy_info_flag = bs_read_u1(b); ph->PES_CRC_flag = bs_read_u1(b); ph->PES_extension_flag = bs_read_u1(b); // byte 8 ph->PES_header_data_length = bs_read_u8(b); int PES_packet_optional_start = bs_pos(b); // byte 9..14 if (ph->PTS_DTS_flags & PES_PTS_FLAG) { bs_skip_u(b, 4); ph->PTS = bs_read_90khz_timestamp(b); } // byte 15..19 if (ph->PTS_DTS_flags & PES_DTS_FLAG) { bs_skip_u(b, 4); ph->DTS = bs_read_90khz_timestamp(b); } if (ph->ESCR_flag) { bs_skip_u(b, 2); ph->ESCR_base = bs_read_90khz_timestamp(b); ph->ESCR_extension = bs_read_u(b, 9); bs_skip_u1(b); } if (ph->ES_rate_flag) { bs_skip_u1(b); ph->ES_rate = bs_read_u(b, 22); bs_skip_u1(b); } if (ph->DSM_trick_mode_flag) { ph->trick_mode_control = bs_read_u(b, 3); switch (ph->trick_mode_control) { case PES_DSM_TRICK_MODE_CTL_FAST_FORWARD: case PES_DSM_TRICK_MODE_CTL_FAST_REVERSE: ph->field_id = bs_read_u(b, 2); ph->intra_slice_refresh = bs_read_u1(b); ph->frequency_truncation = bs_read_u(b, 2); break; case PES_DSM_TRICK_MODE_CTL_SLOW_MOTION: case PES_DSM_TRICK_MODE_CTL_SLOW_REVERSE: ph->rep_cntrl = bs_read_u(b, 5); break; case PES_DSM_TRICK_MODE_CTL_FREEZE_FRAME: ph->field_id = bs_read_u(b, 2); bs_skip_u(b, 3); break; default: bs_skip_u(b, 5); break; } } if (ph->additional_copy_info_flag) { bs_skip_u1(b); ph->additional_copy_info = bs_read_u(b, 7); } if (ph->PES_CRC_flag) { ph->previous_PES_packet_CRC = bs_read_u16(b); } if (ph->PES_extension_flag) { ph->PES_private_data_flag = bs_read_u1(b); ph->pack_header_field_flag = bs_read_u1(b); ph->program_packet_sequence_counter_flag = bs_read_u1(b); ph->PSTD_buffer_flag = bs_read_u1(b); bs_skip_u(b, 3); ph->PES_extension_flag_2 = bs_read_u1(b); if (ph->PES_private_data_flag) bs_read_bytes(b, ph->PES_private_data, 16); if (ph->pack_header_field_flag) { // whoever discovers the need for pack_header() is welcome to implement it. // I haven't. ph->pack_field_length = bs_read_u8(b); bs_skip_bytes(b, ph->pack_field_length); } if (ph->program_packet_sequence_counter_flag) { bs_skip_u1(b); ph->program_packet_sequence_counter = bs_read_u(b, 7); bs_skip_u1(b); ph->MPEG1_MPEG2_identifier = bs_read_u1(b); ph->original_stuff_length = bs_read_u(b, 6); } if (ph->PSTD_buffer_flag) { bs_skip_u(b, 2); ph->PSTD_buffer_scale = bs_read_u1(b); ph->PSTD_buffer_size = bs_read_u(b, 13); } if (ph->PES_extension_flag_2) { int PES_extension_field_start = bs_pos(b); bs_skip_u1(b); ph->PES_extension_field_length = bs_read_u(b, 7); ph->stream_id_extension_flag = bs_read_u1(b); if (!ph->stream_id_extension_flag) { ph->stream_id_extension = bs_read_u(b, 7); } else { bs_skip_u(b, 6); ph->tref_extension_flag = bs_read_u1(b); if (ph->tref_extension_flag) { bs_skip_u(b, 4); ph->TREF = bs_read_90khz_timestamp(b); } } int PES_extension_bytes_left = bs_pos(b) - PES_extension_field_start; if (PES_extension_bytes_left > 0) bs_skip_bytes(b, PES_extension_bytes_left); } } int PES_optional_bytes_read = bs_pos(b) - PES_packet_optional_start; int stuffing_bytes_len = ph->PES_header_data_length - PES_optional_bytes_read; // if any if (stuffing_bytes_len > 0) bs_skip_bytes(b, stuffing_bytes_len); } return (bs_pos(b) - PES_packet_start); }