/*!
* COPYRIGHT (C) 2020 Emeric Grange - All Rights Reserved
*
* This file is part of MiniVideo.
*
* MiniVideo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MiniVideo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MiniVideo. If not, see .
*
* \file pes.c
* \author Emeric Grange
* \date 2012
*/
// minivideo headers
#include "pes.h"
#include "minivideo/bitstream_utils.h"
#include "minivideo/minitraces.h"
// C standard libraries
#include
#include
#include
#include
/* ************************************************************************** */
/*!
* \brief Jumpy protect your parsing - PES edition.
* \param bitstr: Our bitstream reader.
* \param header: A pointer to a PES header structure.
* \return SUCCESS or FAILURE if the jump could not be done.
*
* 'Jumpy' is in charge of checking your position into the stream after your
* parser finish parsing a box / list / chunk / element, never leaving you
* stranded in the middle of nowhere with no easy way to get back on track.
* It will check available informations to known if the current element has been
* fully parsed, and if not perform a jump (or even a rewind) to the next known
* element.
*/
int jumpy_pes(Bitstream_t *bitstr, PesHeader_t *header)
{
int retcode = SUCCESS;
// Done as a precaution, because the parsing of some boxes (like ESDS...)
// can leave us in the middle of a byte and that will never be caught by
// offset checks (cause they works on the assumption that we are byte aligned)
bitstream_force_alignment(bitstr);
// Check if we need a jump
int64_t current_pos = bitstream_get_absolute_byte_offset(bitstr);
if (current_pos != header->offset_end)
{
int64_t file_size = bitstream_get_full_size(bitstr);
// If the offset_end is past the last byte of the file, we do not need to jump
// The parser will pick that fact and finish up...
if (header->offset_end >= file_size)
{
bitstr->bitstream_offset = file_size;
return SUCCESS;
}
// Now, do we need to go forward or backward to reach our goal?
// Then, can we move in our current buffer or do we need to reload a new one?
if (current_pos < header->offset_end)
{
int64_t jump = header->offset_end - current_pos;
if (jump < (UINT_MAX/8))
retcode = skip_bits(bitstr, (unsigned int)(jump*8));
else
retcode = bitstream_goto_offset(bitstr, header->offset_end);
}
else
{
int64_t rewind = current_pos - header->offset_end;
if (rewind > 0)
{
if (rewind > (UINT_MAX/8))
retcode = rewind_bits(bitstr, (unsigned int)(rewind*8));
else
retcode = bitstream_goto_offset(bitstr, header->offset_end);
}
}
}
return retcode;
}
/* ************************************************************************** */
/*!
* \brief Parse PES packet header, common to all PES packet types.
* \param *bitstr: The bitstream to use.
* \param *header: A pointer to a PES header structure.
* \return 1 if succeed, 0 otherwise.
*
* From 'ISO/IEC 13818-1' specification:
* 2.4.3.6 PES packet.
* Table 2-17 – PES packet.
*/
int parse_pes_header(Bitstream_t *bitstr, PesHeader_t *header)
{
TRACE_2(MPS, "> parse_pes_header()");
header->offset_start = bitstream_get_absolute_byte_offset(bitstr);
header->start_code = read_bits(bitstr, 32);
header->stream_id = header->start_code & 0x000000FF;
header->payload_length = read_bits(bitstr, 16);
header->packet_length = header->payload_length + 6;
header->offset_end = header->offset_start + header->packet_length;
return SUCCESS;
}
/* ************************************************************************** */
/*!
* \brief Parse PES packet.
* \param *bitstr: The bitstream to use.
* \param *header: A pointer to a PES header structure.
* \param *packet: A pointer to a PES packet structure.
* \return 1 if succeed, 0 otherwise.
*
* From 'ISO/IEC 13818-1' specification:
* 2.4.3.6 PES packet.
* Table 2-17 – PES packet.
*
* Parse both MPEG-1 (ISO/IEC 11172-1) and MPEG-2 (ISO/IEC 13818-1) PES packets.
*/
int parse_pes(Bitstream_t *bitstr, PesHeader_t *header, PesPacket_t *packet)
{
TRACE_2(MPS, "> parse_pes()");
int retcode = SUCCESS;
TRACE_INFO(MPS, "parse_pes() 0x%X @ %lli",
header->start_code, bitstream_get_absolute_byte_offset(bitstr));
// "regular" PES packet?
if ((header->stream_id != SID_PROGRAM_STREAM_MAP) &&
(header->stream_id != SID_PADDING) &&
(header->stream_id != SID_PRIVATE_STREAM_2) &&
(header->stream_id != SID_ECM_STREAM) &&
(header->stream_id != SID_EMM_STREAM) &&
(header->stream_id != SID_PROGRAM_STREAM_DIRECTORY) &&
(header->stream_id != SID_DSMCC_STREAM) &&
(header->stream_id != SID_2221E))
{
unsigned checkversion = next_bits(bitstr, 2);
// Parse MPEG-2 PES header
if ((checkversion & 0x02) == 0x02)
{
packet->mpeg_version = 2;
if (read_bits(bitstr, 2) != 2)
{
TRACE_ERROR(MPS, "wrong 'marker_bits'");
return FAILURE;
}
packet->PES_scrambling_control = read_bits(bitstr, 2);
packet->PES_priority = read_bit(bitstr);
packet->data_alignment_indicator = read_bit(bitstr);
packet->copyright = read_bit(bitstr);
packet->original_or_copy = read_bit(bitstr);
packet->PTS_DTS_flag = read_bits(bitstr, 2);
packet->ESCR_flag = read_bit(bitstr);
packet->ES_rate_flag = read_bit(bitstr);
packet->DSM_trick_mode_flag = read_bit(bitstr);
packet->additional_copy_info_flag = read_bit(bitstr);
packet->PES_CRC_flag = read_bit(bitstr);
packet->PES_extension_flag = read_bit(bitstr);
packet->PES_header_data_length = read_bits(bitstr, 8);
if (packet->PTS_DTS_flag == 2)
{
if (read_bits(bitstr, 4) != 2)
{
TRACE_ERROR(MPS, "wrong 'marker_bit'");
return FAILURE;
}
packet->PTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15);
MARKER_BIT
}
else if (packet->PTS_DTS_flag == 3)
{
if (read_bits(bitstr, 4) != 3)
{
TRACE_ERROR(MPS, "wrong 'marker_bit'");
return FAILURE;
}
packet->PTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15);
MARKER_BIT
if (read_bits(bitstr, 4) != 1)
{
TRACE_ERROR(MPS, "wrong 'marker_bit'");
return FAILURE;
}
packet->DTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->DTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->DTS += read_bits(bitstr, 15);
MARKER_BIT
}
if (packet->ESCR_flag == 1)
{
packet->ESCR_base = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->ESCR_base += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->ESCR_base += read_bits(bitstr, 15);
MARKER_BIT
packet->ESCR_extension = read_bits(bitstr, 9);
MARKER_BIT
}
if (packet->ES_rate_flag == 1)
{
MARKER_BIT
packet->ES_rate = read_bits(bitstr, 22);
MARKER_BIT
}
if (packet->DSM_trick_mode_flag == 1)
{
packet->trick_mode_control = read_bits(bitstr, 3);
if (packet->trick_mode_control == TM_FAST_FORWARD)
{
packet->field_id = read_bits(bitstr, 2);
packet->intra_slice_refresh = read_bit(bitstr);
packet->frequency_truncation = read_bits(bitstr, 2);
}
else if (packet->trick_mode_control == TM_SLOW_MOTION)
{
packet->rep_cntrl = read_bits(bitstr, 5);
}
else if (packet->trick_mode_control == TM_FREEZE_FRAME)
{
packet->field_id = read_bits(bitstr, 2);
/*int reserved =*/ read_bits(bitstr, 3);
}
else if (packet->trick_mode_control == TM_FAST_REVERSE)
{
packet->field_id = read_bits(bitstr, 2);
packet->intra_slice_refresh = read_bit(bitstr);
packet->frequency_truncation = read_bits(bitstr, 2);
}
else if (packet->trick_mode_control == TM_SLOW_REVERSE)
{
packet->rep_cntrl = read_bits(bitstr, 5);
}
else
{
/*int reserved =*/ read_bits(bitstr, 5);
}
}
if (packet->additional_copy_info_flag == 1)
{
MARKER_BIT
packet->additional_copy_info = read_bits(bitstr, 7);
}
if (packet->PES_CRC_flag == 1)
{
packet->previous_PES_packet_CRC = read_bits(bitstr, 16);
}
if (packet->PES_extension_flag == 1)
{
packet->PES_private_data_flag = read_bit(bitstr);
packet->pack_header_field_flag = read_bit(bitstr);
packet->program_packet_sequence_counter_flag = read_bit(bitstr);
packet->PSTD_buffer_flag = read_bit(bitstr);
/*int reserved =*/ read_bits(bitstr, 3);
packet->PES_extension_flag_2 = read_bit(bitstr);
if (packet->PES_private_data_flag == 1)
{
for (int i = 0; i < 16; i++)
{
packet->PES_private_data[i] = read_bits(bitstr, 8);
}
}
if (packet->pack_header_field_flag == 1)
{
packet->pack_field_length = read_bits(bitstr, 8);
// TODO
//parse_pack_header(bitstr, wtf);
}
if (packet->program_packet_sequence_counter_flag == 1)
{
MARKER_BIT
packet->program_packet_sequence_counter = read_bits(bitstr, 7);
MARKER_BIT
packet->MPEG1_MPEG2_identifier = read_bit(bitstr);
packet->original_stuff_length = read_bits(bitstr, 6);
}
if (packet->PSTD_buffer_flag == 1)
{
if (read_bits(bitstr, 2) != 1)
{
TRACE_ERROR(MPS, "wrong 'marker_bit'");
return FAILURE;
}
packet->PSTD_buffer_scale = read_bit(bitstr);
packet->PSTD_buffer_size = read_bits(bitstr, 13);
}
if (packet->PES_extension_flag_2 == 1)
{
MARKER_BIT
packet->PES_extension_field_length = read_bits(bitstr, 7);
for (int i = 0; i < packet->PES_extension_field_length; i++)
{
/*int reserved =*/ read_bits(bitstr, 8);
}
}
}
}
else // Parse MPEG-1 PES header
{
packet->mpeg_version = 1;
packet->PES_header_data_length = 0; // We will emulate this field
// MPEG-1: up to 16 stuffing bytes here (optional)
while (next_bits(bitstr, 8) == 0xFF)
{
skip_bits(bitstr, 8);
packet->PES_header_data_length++;
}
// Optional
if (next_bits(bitstr, 2) == 1)
{
skip_bits(bitstr, 2);
packet->PES_header_data_length += 2;
packet->PSTD_buffer_scale = read_bit(bitstr);
packet->PSTD_buffer_size = read_bits(bitstr, 13);
}
if (next_bits(bitstr, 8) == 0x0F)
{
skip_bits(bitstr, 8);
packet->PES_header_data_length++;
}
else
{
if (next_bits(bitstr, 2) != 0)
{
TRACE_ERROR(MPS, "wrong 'marker_bit' PESv1");
return FAILURE;
}
packet->PTS_DTS_flag = read_bits(bitstr, 2);
if (packet->PTS_DTS_flag == 2)
{
packet->PES_header_data_length += 5;
packet->PTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15);
MARKER_BIT
}
else if (packet->PTS_DTS_flag == 3)
{
packet->PES_header_data_length += 10;
packet->PTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->PTS += read_bits(bitstr, 15);
MARKER_BIT
if (read_bits(bitstr, 4) != 1)
{
TRACE_ERROR(MPS, "wrong 'marker_bit' (PTS_DTS_flag==3)");
return FAILURE;
}
packet->DTS = read_bits(bitstr, 3) << 30;
MARKER_BIT
packet->DTS += read_bits(bitstr, 15) << 15;
MARKER_BIT
packet->DTS += read_bits(bitstr, 15);
MARKER_BIT
}
else
{
packet->PES_header_data_length++;
if (read_bits(bitstr, 4) == 0x0F)
{
TRACE_ERROR(MPS, "wrong 'marker_bit' (PTS_DTS_flag==0)");
return FAILURE;
}
}
}
}
// Skip packet data
//retcode = skip_pes_data(bitstr, packet);
/*
// TODO
int i = 0, N1 = 0, N2 = 0;
for (i = 0; i < N1; i++)
{
if (read_bits(bitstr, 8) != 0xFF)
{
TRACE_ERROR(MPS, BLD_GREEN "wrong 'stuffing_byte'" CLR_RESET);
return FAILURE;
}
}
for (i = 0; i < N2; i++)
{
uint8_t PES_packet_data_byte = read_bits(bitstr, 8);
}
*/
}
return retcode;
}
/* ************************************************************************** */
void print_pes(PesHeader_t *header, PesPacket_t *packet)
{
TRACE_INFO(MPS, BLD_GREEN "print_pes()" CLR_RESET);
// Header
TRACE_INFO(MPS, " packet_start_offset = %lli", header->offset_start);
TRACE_INFO(MPS, " packet_end_offset = %lli", header->offset_end);
TRACE_INFO(MPS, " packet_start_code = 0x%06X", header->start_code);
TRACE_INFO(MPS, " stream_id = 0x%02X", header->start_code);
TRACE_INFO(MPS, " PES_packet_length = %i", header->payload_length);
// "regular" PES packet?
if ((header->stream_id != SID_PROGRAM_STREAM_MAP) &&
(header->stream_id != SID_PADDING) &&
(header->stream_id != SID_PRIVATE_STREAM_2) &&
(header->stream_id != SID_ECM_STREAM) &&
(header->stream_id != SID_EMM_STREAM) &&
(header->stream_id != SID_PROGRAM_STREAM_DIRECTORY) &&
(header->stream_id != SID_DSMCC_STREAM) &&
(header->stream_id != SID_2221E))
{
TRACE_1(MPS, " PES_scrambling_control = %i", packet->PES_scrambling_control);
TRACE_1(MPS, " PES_priority = %i", packet->PES_priority);
TRACE_1(MPS, " data_alignment_indicator = %i", packet->data_alignment_indicator);
TRACE_1(MPS, " copyright = %i", packet->copyright);
TRACE_1(MPS, " original_or_copy = %i", packet->original_or_copy);
TRACE_1(MPS, " PTS_DTS_flag = %i", packet->PTS_DTS_flag);
TRACE_1(MPS, " ESCR_flag = %i", packet->ESCR_flag);
TRACE_1(MPS, " ES_rate_flag = %i", packet->ES_rate_flag);
TRACE_1(MPS, " DSM_trick_mode_flag = %i", packet->DSM_trick_mode_flag);
TRACE_1(MPS, " additional_copy_info_flag= %i", packet->additional_copy_info_flag);
TRACE_1(MPS, " PES_CRC_flag = %i", packet->PES_CRC_flag);
TRACE_1(MPS, " PES_extension_flag = %i", packet->PES_extension_flag);
TRACE_1(MPS, " PES_header_data_length = %i", packet->PES_header_data_length);
if (packet->PTS_DTS_flag == 2)
{
TRACE_1(MPS, " PTS = %i", packet->PTS);
}
else if (packet->PTS_DTS_flag == 3)
{
TRACE_1(MPS, " PTS = %i", packet->PTS);
TRACE_1(MPS, " DTS = %i", packet->DTS);
}
if (packet->ESCR_flag == 1)
{
TRACE_1(MPS, " ESCR_base = %i", packet->ESCR_base);
TRACE_1(MPS, " ESCR_extension = %i", packet->ESCR_extension);
}
if (packet->ES_rate_flag == 1)
{
TRACE_1(MPS, " ES_rate = %i", packet->ES_rate);
}
if (packet->DSM_trick_mode_flag == 1)
{
TRACE_1(MPS, " trick_mode_control= %i", packet->trick_mode_control);
if (packet->trick_mode_control == TM_FAST_FORWARD)
{
TRACE_1(MPS, " field_id = %i", packet->field_id);
TRACE_1(MPS, " intra_slice_refresh = %i", packet->intra_slice_refresh);
TRACE_1(MPS, " frequency_truncation = %i", packet->frequency_truncation);
}
else if (packet->trick_mode_control == TM_SLOW_MOTION)
{
TRACE_1(MPS, " rep_cntrl= %i", packet->rep_cntrl);
}
else if (packet->trick_mode_control == TM_FREEZE_FRAME)
{
TRACE_1(MPS, " field_id= %i", packet->field_id);
}
else if (packet->trick_mode_control == TM_FAST_REVERSE)
{
TRACE_1(MPS, " field_id = %i", packet->field_id);
TRACE_1(MPS, " intra_slice_refresh = %i", packet->intra_slice_refresh);
TRACE_1(MPS, " frequency_truncation = %i", packet->frequency_truncation);
}
else if (packet->trick_mode_control == TM_SLOW_REVERSE)
{
TRACE_1(MPS, " rep_cntrl= %i", packet->rep_cntrl);
}
}
if (packet->additional_copy_info_flag == 1)
{
TRACE_1(MPS, " additional_copy_info= %i", packet->additional_copy_info);
}
if (packet->PES_CRC_flag == 1)
{
TRACE_1(MPS, " previous_PES_packet_CRC= %i", packet->previous_PES_packet_CRC);
}
if (packet->PES_extension_flag == 1)
{
TRACE_1(MPS, " PES_private_data_flag = %i", packet->PES_private_data_flag);
TRACE_1(MPS, " pack_header_field_flag = %i", packet->pack_header_field_flag);
TRACE_1(MPS, " program_packet_sequence_counter_flag= %i", packet->program_packet_sequence_counter_flag);
TRACE_1(MPS, " PSTD_buffer_flag = %i", packet->PSTD_buffer_flag);
TRACE_1(MPS, " PES_extension_flag_2 = %i", packet->PES_extension_flag_2);
if (packet->PES_private_data_flag == 1)
{
int i = 0;
for (i = 0; i < 16; i++)
{
TRACE_1(MPS, " PES_private_data[%i]= %i", i, packet->PES_private_data[i]);
}
}
if (packet->pack_header_field_flag == 1)
{
TRACE_1(MPS, " pack_field_length= %i", packet->pack_field_length);
// TODO
//parse_pack_header(bitstr, wtf);
}
if (packet->program_packet_sequence_counter_flag == 1)
{
TRACE_1(MPS, " program_packet_sequence_counter = %i", packet->program_packet_sequence_counter);
TRACE_1(MPS, " MPEG1_MPEG2_identifier = %i", packet->MPEG1_MPEG2_identifier);
TRACE_1(MPS, " original_stuff_length = %i", packet->original_stuff_length);
}
if (packet->PSTD_buffer_flag == 1)
{
TRACE_1(MPS, " PSTD_buffer_scale= %i", packet->PSTD_buffer_scale);
TRACE_1(MPS, " PSTD_buffer_size = %i", packet->PSTD_buffer_size);
}
if (packet->PES_extension_flag_2 == 1)
{
TRACE_1(MPS, " PES_extension_field_length= %i", packet->PES_extension_field_length);
for (int i = 0; i < packet->PES_extension_field_length; i++)
{
TRACE_1(MPS, " reserved= xx");
}
}
}
}
}
/* ************************************************************************** */
/*!
* \brief parse_pes_padding
* \param bitstr: Our bitstream reader.
* \param header
* \param packet
* \return 1 if succeed, 0 otherwise.
*/
int parse_pes_padding(Bitstream_t *bitstr, PesHeader_t *header, PesPacket_t *packet)
{
TRACE_INFO(MPS, BLD_GREEN " parse_pes_padding()" CLR_RESET);
int retcode = SUCCESS;
if (header->payload_length != 0)
{
skip_bits(bitstr, header->payload_length * 8);
TRACE_INFO(MPS, " > skip_padding_packet() >> %i bytes", header->payload_length);
retcode = SUCCESS;
}
else
{
while (read_bits(bitstr, 8) == 0xFF)
{
// Manually skipping the padding bytes
}
}
return retcode;
}
/* ************************************************************************** */
/*!
* \brief Parse the 'body' of a PES packet containing audio data.
* \param bitstr: Our bitstream reader.
* \param header
* \param packet
* \param map
* \return
*/
//int parse_pes_a(Bitstream_t *bitstr, PesHeader_t *header, PesPacket_t *packet,
// MediaStream_t *map)
//{
// TRACE_2(MPS, "> parse_pes_a()");
// int retcode = SUCCESS;
//
// if (header->stream_id == SID_PRIVATE_STREAM_1)
// {
// // Look for a known "non-MPEG" start code
// uint32_t startcode = read_bits(bitstr, 32);
//
// if ((startcode & 0xFF000000) == 0x80000000)
// {
// map->stream_codec = CODEC_AC3;
//
// //pc_uint16 crc1 = (read & 0x0000FFFF);
// uint8_t read = read_bits(bitstr, 8);
// uint8_t fscod = (read & 0xC0) >> 6;
// uint8_t frmsizcod = (read & 0x3F);
//
// switch (fscod)
// {
// case 0:
// map->sampling_rate = 48000.0;
// break;
// case 1:
// map->sampling_rate = 44100.0;
// break;
// case 2:
// map->sampling_rate = 32000.0;
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported AC3 fscod %u", fscod);
// retcode = FAILURE;
// break;
// }
//
// switch (frmsizcod)
// {
// case 0:
// case 1:
// map->bitrate_avg = 32;
// break;
// case 2:
// case 3:
// map->bitrate_avg = 40;
// break;
// case 4:
// case 5:
// map->bitrate_avg = 48;
// break;
// case 6:
// case 7:
// map->bitrate_avg = 56;
// break;
// case 8:
// case 9:
// map->bitrate_avg = 64;
// break;
// case 10:
// case 11:
// map->bitrate_avg = 80;
// break;
// case 12:
// case 13:
// map->bitrate_avg = 96;
// break;
// case 14:
// case 15:
// map->bitrate_avg = 112;
// break;
// case 16:
// case 17:
// map->bitrate_avg = 128;
// break;
// case 18:
// case 19:
// map->bitrate_avg = 160;
// break;
// case 20:
// case 21:
// map->bitrate_avg = 192;
// break;
// case 22:
// case 23:
// map->bitrate_avg = 224;
// break;
// case 24:
// case 25:
// map->bitrate_avg = 256;
// break;
// case 26:
// case 27:
// map->bitrate_avg = 320;
// break;
// case 28:
// case 29:
// map->bitrate_avg = 384;
// break;
// case 30:
// case 31:
// map->bitrate_avg = 448;
// break;
// case 32:
// case 33:
// map->bitrate_avg = 512;
// break;
// case 34:
// case 35:
// map->bitrate_avg = 576;
// break;
// case 36:
// case 37:
// map->bitrate_avg = 640;
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported AC3 frmsizcod %u", frmsizcod);
// retcode = FAILURE;
// break;
// }
// }
// else if ((startcode == 0x7FFE8001) ||
// (startcode == 0x64582025))
// {
// map->stream_codec = CODEC_DTS;
//
// // 28 first bits are ignored
// uint32_t read = read_bits(bitstr, 16);
// read = read_bits(bitstr, 32);
//
// //uint32_t FSIZE = 0; // Might be necessary to skip the frame and go read the extension
// //uint32_t AMODE = (read & 0x000FC000) >> 18;
// uint32_t SFREQ = (read & 0x00003C00) >> 10;
// uint32_t RATE = (read & 0x000003E0) >> 5;
//
// switch (SFREQ)
// {
// case 1:
// map->sampling_rate = 8000;
// break;
// case 2:
// map->sampling_rate = 16000;
// break;
// case 3:
// map->sampling_rate = 32000;
// break;
// case 6:
// map->sampling_rate = 11025;
// break;
// case 7:
// map->sampling_rate = 22050;
// break;
// case 8:
// map->sampling_rate = 44100;
// break;
// case 11:
// map->sampling_rate = 12000;
// break;
// case 12:
// map->sampling_rate = 24000;
// break;
// case 13:
// map->sampling_rate = 48000;
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported DTS SFREQ %u", SFREQ);
// retcode = FAILURE;
// break;
// }
//
// switch (RATE)
// {
// case 0:
// map->bitrate_avg = 32000;
// break;
// case 1:
// map->bitrate_avg = 56000;
// break;
// case 2:
// map->bitrate_avg = 64000;
// break;
// case 3:
// map->bitrate_avg = 96000;
// break;
// case 4:
// map->bitrate_avg = 112000;
// break;
// case 5:
// map->bitrate_avg = 128000;
// break;
// case 6:
// map->bitrate_avg = 192000;
// break;
// case 7:
// map->bitrate_avg = 224000;
// break;
// case 8:
// map->bitrate_avg = 256000;
// break;
// case 9:
// map->bitrate_avg = 320000;
// break;
// case 10:
// map->bitrate_avg = 384000;
// break;
// case 11:
// map->bitrate_avg = 448000;
// break;
// case 12:
// map->bitrate_avg = 512000;
// break;
// case 13:
// map->bitrate_avg = 576000;
// break;
// case 14:
// map->bitrate_avg = 640000;
// break;
// case 15:
// map->bitrate_avg = 768000;
// break;
// case 16:
// map->bitrate_avg = 960000;
// break;
// case 17:
// map->bitrate_avg = 1024000;
// break;
// case 18:
// map->bitrate_avg = 1152000;
// break;
// case 19:
// map->bitrate_avg = 1280000;
// break;
// case 20:
// map->bitrate_avg = 1344000;
// break;
// case 21:
// map->bitrate_avg = 1408000;
// break;
// case 22:
// map->bitrate_avg = 1411000;
// break;
// case 23:
// map->bitrate_avg = 1472000;
// break;
// case 24:
// map->bitrate_avg = 1536000;
// break;
// case 29:
// map->bitrate_avg = 2048000; // Speficifation says "open"
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported DTS RATE %u", RATE);
// retcode = FAILURE;
// break;
// }
// }
// else // audio codec in private stream could also be : LPCM, AAC, ... ?
// {
// TRACE_WARNING(MPS, "Unknown audio codec (0x%08X) inside audio private stream", startcode);
// retcode = FAILURE;
// }
// }
// else
// {
// // Look for a known MP3 start code
// uint16_t read = read_bits(bitstr, 16);
//
// if ((read & 0xFFF0) == 0xFFF0)
// {
// uint16_t audio_version_id = (read & 0x000C) >> 2;
// uint16_t layer_index = (read & 0x0003);
//
// read = read_bits(bitstr, 8);
// uint16_t bitrate_index = (read & 0x0078) >> 3;
// uint16_t samplingrate_index = (read & 0x0006) >> 1;
//
// uint32_t _mpeg_version = 0;
// uint32_t _mpeg_layer = 0;
//
// switch (audio_version_id)
// {
// case 0x00:
// _mpeg_version = 3; // MPEG-2.5
// break;
//
// case 0x01:
// case 0x02:
// _mpeg_version = 2; // MPEG-2
// break;
//
// case 0x03:
// _mpeg_version = 1; // MPEG-1
// break;
// }
//
// switch (layer_index)
// {
// case 0x03:
// _mpeg_layer = 1; // Layer 1
// map->stream_codec = CODEC_MPEG_L1;
// break;
//
// case 0x02:
// _mpeg_layer = 2; // Layer 2
// map->stream_codec = CODEC_MPEG_L2;
// break;
//
// default:
// case 0x01:
// case 0x00: // reserved
// _mpeg_layer = 3; // Layer 3
// map->stream_codec = CODEC_MPEG_L3;
// break;
// }
//
// //map->bitrate = bitrate_index_table[_mpeg_version - 1][_mpeg_layer - 1][bitrate_index];
// //map->sampling_rate = samplingrate_index_table[_mpeg_version - 1][samplingrate_index];
// //_mpeg_sampleperframe = sampleperframe_table[_mpeg_version - 1][_mpeg_layer - 1];
// }
// else
// {
// TRACE_WARNING(MPS, "Unknown ES type (0x%04X) inside PES audio packet (id: 0x%02X)",
// read, header->stream_id);
// retcode = FAILURE;
// }
// }
//
// return retcode;
//}
//
///* ************************************************************************** */
//
///*!
// * \brief Parse the 'body' of a PES packet containing video data.
// * \param bitstr: Our bitstream reader.
// * \param header
// * \param packet
// * \param map
// * \return
// */
//int parse_pes_v(Bitstream_t *bitstr, PesHeader_t *header, PesPacket_t *packet,
// MediaStream_t *map)
//{
// TRACE_2(MPS, "> parse_pes_v()");
// int retcode = SUCCESS;
//
// // Avoid trying to get infos from a splitted video sample
// if (packet->PTS)
// {
// TRACE_2(MPS, "Trying get_video_infos() @ ");
//
// TRACE_INFO(MPS, "parse_pes_v() 0x%X @ %lli",
// header->start_code, bitstream_get_absolute_byte_offset(bitstr));
//
// // Look for a sequence header start code
// uint32_t start_code = read_bits(bitstr, 32);
//
// // MPEG-1/2
// if (start_code == 0x000001B3)
// {
// uint32_t sizes = read_bits(bitstr, 32);
// uint32_t aspect_ratio_index = (sizes & 0x000000F0) >> 4;
// uint32_t framerate_index = (sizes & 0x0000000F);
//
// map->color_matrix = COLOR_SPC_BT709;
// map->width = (sizes & 0xFFF00000) >> 20;
// map->height = (sizes & 0x000FFF00) >> 8;
//
// uint32_t _mpeg_version = 2;
//
// if (_mpeg_version == 1)
// {
// map->stream_codec = CODEC_MPEG1;
//
// switch (aspect_ratio_index)
// {
// case 1:
// map->display_aspect_ratio = 1.0;
// break;
// case 8:
// case 12:
// map->display_aspect_ratio = (4.0 / 3.0);
// break;
// case 3:
// case 6:
// map->display_aspect_ratio = (16.0 / 9.0);
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported MPEG-1 aspect_ratio_index %u", aspect_ratio_index);
// retcode = FAILURE;
// break;
// }
// }
// else // if (_mpeg_version == 2)
// {
// map->stream_codec = CODEC_MPEG2;
//
// switch (aspect_ratio_index)
// {
// case 1:
// map->video_aspect_ratio = 1.0;
// break;
// case 2:
// map->video_aspect_ratio = (4.0 / 3.0);
// break;
// case 3:
// map->video_aspect_ratio = (16.0 / 9.0);
// break;
// case 4:
// map->video_aspect_ratio = (2.21 / 1.0);
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported MPEG-2 aspect_ratio_index %u", aspect_ratio_index);
// retcode = FAILURE;
// break;
// }
// }
//
// switch (framerate_index)
// {
// case 1:
// map->framerate = 23.976;
// map->framerate_num = 24000;
// map->framerate_base = 1001;
// break;
// case 2:
// map->framerate = 24.0;
// map->framerate_num = 24;
// map->framerate_base = 1;
// break;
// case 3:
// map->framerate = 25.0;
// map->framerate_num = 25;
// map->framerate_base = 1;
// break;
// case 4:
// map->framerate = 29.970;
// map->framerate_num = 30000;
// map->framerate_base = 1001;
// break;
// case 5:
// map->framerate = 30.0;
// map->framerate_num = 30;
// map->framerate_base = 1;
// break;
// case 6:
// map->framerate = 50.0;
// map->framerate_num = 50;
// map->framerate_base = 1;
// break;
// case 7:
// map->framerate = 59.940;
// map->framerate_num = 60000;
// map->framerate_base = 1001;
// break;
// case 8:
// map->framerate = 60.0;
// map->framerate_num = 60;
// map->framerate_base = 1;
// break;
// default:
// TRACE_WARNING(MPS, "Unsupported MPEG-1/2 framerate_index %u", framerate_index);
// retcode = FAILURE;
// break;
// }
// }
// else
// {
// TRACE_WARNING(MPS, "Unknown ES type (0x%08X) inside PES video packet (id: 0x%02X)",
// start_code, header->stream_id);
// retcode = FAILURE;
// }
// }
//
// return retcode;
//}
/* ************************************************************************** */