mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #250, decode the PMT and PAT
This commit is contained in:
parent
7692e50fc2
commit
cc87992fe0
3 changed files with 457 additions and 129 deletions
|
@ -223,6 +223,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define ERROR_STREAM_CASTER_TS_SYNC_BYTE 4013
|
#define ERROR_STREAM_CASTER_TS_SYNC_BYTE 4013
|
||||||
#define ERROR_STREAM_CASTER_TS_AF 4014
|
#define ERROR_STREAM_CASTER_TS_AF 4014
|
||||||
#define ERROR_STREAM_CASTER_TS_CRC32 4015
|
#define ERROR_STREAM_CASTER_TS_CRC32 4015
|
||||||
|
#define ERROR_STREAM_CASTER_TS_PSI 4016
|
||||||
|
#define ERROR_STREAM_CASTER_TS_PAT 4017
|
||||||
|
#define ERROR_STREAM_CASTER_TS_PMT 4018
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* whether the error code is an system control error.
|
* whether the error code is an system control error.
|
||||||
|
|
|
@ -417,7 +417,7 @@ int SrsTsContext::decode(SrsStream* stream)
|
||||||
// parse util EOF of stream.
|
// parse util EOF of stream.
|
||||||
// for example, parse multiple times for the PES_packet_length(0) packet.
|
// for example, parse multiple times for the PES_packet_length(0) packet.
|
||||||
while (!stream->empty()) {
|
while (!stream->empty()) {
|
||||||
SrsTsPacket* packet = new SrsTsPacket();
|
SrsTsPacket* packet = new SrsTsPacket(this);
|
||||||
SrsAutoFree(SrsTsPacket, packet);
|
SrsAutoFree(SrsTsPacket, packet);
|
||||||
|
|
||||||
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
|
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
|
||||||
|
@ -429,8 +429,23 @@ int SrsTsContext::decode(SrsStream* stream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsTsPacket::SrsTsPacket()
|
SrsTsPidApply SrsTsContext::get(int pid)
|
||||||
{
|
{
|
||||||
|
if (pids.find(pid) == pids.end()) {
|
||||||
|
return SrsTsPidApplyReserved;
|
||||||
|
}
|
||||||
|
return pids[pid];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsTsContext::set(int pid, SrsTsPidApply apply_pid)
|
||||||
|
{
|
||||||
|
pids[pid] = apply_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPacket::SrsTsPacket(SrsTsContext* c)
|
||||||
|
{
|
||||||
|
context = c;
|
||||||
|
|
||||||
sync_byte = 0;
|
sync_byte = 0;
|
||||||
transport_error_indicator = 0;
|
transport_error_indicator = 0;
|
||||||
payload_unit_start_indicator = 0;
|
payload_unit_start_indicator = 0;
|
||||||
|
@ -507,10 +522,17 @@ int SrsTsPacket::decode(SrsStream* stream)
|
||||||
// 2.4.4.3 Program association Table
|
// 2.4.4.3 Program association Table
|
||||||
srs_freep(payload);
|
srs_freep(payload);
|
||||||
payload = new SrsTsPayloadPAT(this);
|
payload = new SrsTsPayloadPAT(this);
|
||||||
|
} else {
|
||||||
|
SrsTsPidApply apply_pid = context->get(pid);
|
||||||
|
if (apply_pid == SrsTsPidApplyPMT) {
|
||||||
|
// 2.4.4.8 Program Map Table
|
||||||
|
srs_freep(payload);
|
||||||
|
payload = new SrsTsPayloadPMT(this);
|
||||||
} else {
|
} else {
|
||||||
// left bytes as reserved.
|
// left bytes as reserved.
|
||||||
stream->skip(nb_payload);
|
stream->skip(nb_payload);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) {
|
if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) {
|
||||||
srs_error("ts: demux payload failed. ret=%d", ret);
|
srs_error("ts: demux payload failed. ret=%d", ret);
|
||||||
|
@ -676,6 +698,7 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
|
||||||
}
|
}
|
||||||
transport_private_data_length = (u_int8_t)stream->read_1bytes();
|
transport_private_data_length = (u_int8_t)stream->read_1bytes();
|
||||||
|
|
||||||
|
if (transport_private_data_length> 0) {
|
||||||
if (!stream->require(transport_private_data_length)) {
|
if (!stream->require(transport_private_data_length)) {
|
||||||
ret = ERROR_STREAM_CASTER_TS_AF;
|
ret = ERROR_STREAM_CASTER_TS_AF;
|
||||||
srs_error("ts: demux af transport_private_data_flag failed. ret=%d", ret);
|
srs_error("ts: demux af transport_private_data_flag failed. ret=%d", ret);
|
||||||
|
@ -685,6 +708,7 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
|
||||||
transport_private_data = new char[transport_private_data_length];
|
transport_private_data = new char[transport_private_data_length];
|
||||||
stream->read_bytes(transport_private_data, transport_private_data_length);
|
stream->read_bytes(transport_private_data, transport_private_data_length);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (adaptation_field_extension_flag) {
|
if (adaptation_field_extension_flag) {
|
||||||
int pos_af_ext = stream->pos();
|
int pos_af_ext = stream->pos();
|
||||||
|
@ -760,16 +784,6 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram()
|
|
||||||
{
|
|
||||||
number = 0;
|
|
||||||
pid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
|
SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
|
||||||
{
|
{
|
||||||
packet = p;
|
packet = p;
|
||||||
|
@ -782,6 +796,7 @@ SrsTsPayload::~SrsTsPayload()
|
||||||
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
||||||
{
|
{
|
||||||
pointer_field = 0;
|
pointer_field = 0;
|
||||||
|
CRC_32 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsTsPayloadPSI::~SrsTsPayloadPSI()
|
SrsTsPayloadPSI::~SrsTsPayloadPSI()
|
||||||
|
@ -802,43 +817,21 @@ int SrsTsPayloadPSI::decode(SrsStream* stream)
|
||||||
*/
|
*/
|
||||||
if (packet->payload_unit_start_indicator) {
|
if (packet->payload_unit_start_indicator) {
|
||||||
if (!stream->require(1)) {
|
if (!stream->require(1)) {
|
||||||
ret = ERROR_STREAM_CASTER_TS_AF;
|
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||||
srs_error("ts: demux PSI failed. ret=%d", ret);
|
srs_error("ts: demux PSI failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
pointer_field = stream->read_1bytes();
|
pointer_field = stream->read_1bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
|
|
||||||
{
|
|
||||||
nb_programs = 0;
|
|
||||||
programs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrsTsPayloadPAT::~SrsTsPayloadPAT()
|
|
||||||
{
|
|
||||||
srs_freep(programs);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SrsTsPayloadPAT::decode(SrsStream* stream)
|
|
||||||
{
|
|
||||||
int ret = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
if ((ret = SrsTsPayloadPSI::decode(stream)) != ERROR_SUCCESS) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// to calc the crc32
|
// to calc the crc32
|
||||||
char* ppat = stream->data() + stream->pos();
|
char* ppat = stream->data() + stream->pos();
|
||||||
int pat_pos = stream->pos();
|
int pat_pos = stream->pos();
|
||||||
|
|
||||||
// atleast 8B without programs and crc32
|
// atleast 3B for all psi.
|
||||||
if (!stream->require(8)) {
|
if (!stream->require(3)) {
|
||||||
ret = ERROR_STREAM_CASTER_TS_AF;
|
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||||
srs_error("ts: demux PAT failed. ret=%d", ret);
|
srs_error("ts: demux PSI failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
// 1B
|
// 1B
|
||||||
|
@ -851,11 +844,82 @@ int SrsTsPayloadPAT::decode(SrsStream* stream)
|
||||||
const0_value = (section_length >> 14) & 0x01;
|
const0_value = (section_length >> 14) & 0x01;
|
||||||
section_length &= 0x0FFF;
|
section_length &= 0x0FFF;
|
||||||
|
|
||||||
|
// no section, ignore.
|
||||||
|
if (section_length == 0) {
|
||||||
|
srs_warn("ts: demux PAT ignore empty section");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (!stream->require(section_length)) {
|
if (!stream->require(section_length)) {
|
||||||
ret = ERROR_STREAM_CASTER_TS_AF;
|
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||||
srs_error("ts: demux PAT section failed. ret=%d", ret);
|
srs_error("ts: demux PAT section failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the virtual method of actual PSI.
|
||||||
|
if ((ret = psi_decode(stream)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4B
|
||||||
|
if (!stream->require(4)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||||
|
srs_error("ts: demux PSI crc32 failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
CRC_32 = stream->read_4bytes();
|
||||||
|
|
||||||
|
// verify crc32.
|
||||||
|
int32_t crc32 = srs_crc32(ppat, stream->pos() - pat_pos - 4);
|
||||||
|
if (crc32 != CRC_32) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_CRC32;
|
||||||
|
srs_error("ts: verify PSI crc32 failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// consume left stuffings
|
||||||
|
if (!stream->empty()) {
|
||||||
|
stream->skip(stream->size() - stream->pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram()
|
||||||
|
{
|
||||||
|
number = 0;
|
||||||
|
pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPAT::~SrsTsPayloadPAT()
|
||||||
|
{
|
||||||
|
std::vector<SrsTsPayloadPATProgram*>::iterator it;
|
||||||
|
for (it = programs.begin(); it != programs.end(); ++it) {
|
||||||
|
SrsTsPayloadPATProgram* program = *it;
|
||||||
|
srs_freep(program);
|
||||||
|
}
|
||||||
|
programs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// atleast 5B for PAT specified
|
||||||
|
if (!stream->require(5)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PAT;
|
||||||
|
srs_error("ts: demux PAT failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int pos = stream->pos();
|
int pos = stream->pos();
|
||||||
|
|
||||||
// 2B
|
// 2B
|
||||||
|
@ -876,35 +940,136 @@ int SrsTsPayloadPAT::decode(SrsStream* stream)
|
||||||
|
|
||||||
// multiple 4B program data.
|
// multiple 4B program data.
|
||||||
int program_bytes = section_length - 4 - (stream->pos() - pos);
|
int program_bytes = section_length - 4 - (stream->pos() - pos);
|
||||||
nb_programs = program_bytes / 4;
|
for (int i = 0; i < program_bytes; i += 4) {
|
||||||
if (nb_programs > 0) {
|
SrsTsPayloadPATProgram* program = new SrsTsPayloadPATProgram();
|
||||||
srs_freep(programs);
|
|
||||||
programs = new SrsTsPayloadPATProgram[nb_programs];
|
|
||||||
|
|
||||||
for (int i = 0; i < nb_programs; i++) {
|
|
||||||
SrsTsPayloadPATProgram* program = programs + i;
|
|
||||||
|
|
||||||
int tmpv = stream->read_4bytes();
|
int tmpv = stream->read_4bytes();
|
||||||
program->number = (int16_t)((tmpv >> 16) & 0xFFFF);
|
program->number = (int16_t)((tmpv >> 16) & 0xFFFF);
|
||||||
program->pid = (int16_t)(tmpv & 0x1FFF);
|
program->pid = (int16_t)(tmpv & 0x1FFF);
|
||||||
|
|
||||||
|
// update the apply pid table.
|
||||||
|
packet->context->set(program->pid, SrsTsPidApplyPMT);
|
||||||
|
|
||||||
|
programs.push_back(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the apply pid table.
|
||||||
|
packet->context->set(packet->pid, SrsTsPidApplyPAT);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPMTESInfo::SrsTsPayloadPMTESInfo()
|
||||||
|
{
|
||||||
|
ES_info_length = 0;
|
||||||
|
ES_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPMTESInfo::~SrsTsPayloadPMTESInfo()
|
||||||
|
{
|
||||||
|
srs_freep(ES_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPMT::SrsTsPayloadPMT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
|
||||||
|
{
|
||||||
|
program_info_length = 0;
|
||||||
|
program_info_desc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPMT::~SrsTsPayloadPMT()
|
||||||
|
{
|
||||||
|
srs_freep(program_info_desc);
|
||||||
|
|
||||||
|
std::vector<SrsTsPayloadPMTESInfo*>::iterator it;
|
||||||
|
for (it = infos.begin(); it != infos.end(); ++it) {
|
||||||
|
SrsTsPayloadPMTESInfo* info = *it;
|
||||||
|
srs_freep(info);
|
||||||
|
}
|
||||||
|
infos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// atleast 9B for PMT specified
|
||||||
|
if (!stream->require(9)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||||
|
srs_error("ts: demux PMT failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
program_number = stream->read_2bytes();
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
current_next_indicator = stream->read_1bytes();
|
||||||
|
|
||||||
|
version_number = (current_next_indicator >> 1) & 0x1F;
|
||||||
|
current_next_indicator &= 0x01;
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
section_number = stream->read_1bytes();
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
last_section_number = stream->read_1bytes();
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
PCR_PID = stream->read_2bytes();
|
||||||
|
|
||||||
|
PCR_PID &= 0x1FFF;
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
program_info_length = stream->read_2bytes();
|
||||||
|
|
||||||
|
program_info_length &= 0xFFF;
|
||||||
|
|
||||||
|
if (program_info_length > 0) {
|
||||||
|
if (!stream->require(program_info_length)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||||
|
srs_error("ts: demux PMT program info failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_freep(program_info_desc);
|
||||||
|
program_info_desc = new char[program_info_length];
|
||||||
|
stream->read_bytes(program_info_desc, program_info_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// [section_length] - 4(CRC) - 9B - [program_info_length]
|
||||||
|
int ES_EOF_pos = stream->pos() + section_length - 4 - 9 - program_info_length;
|
||||||
|
while (stream->pos() < ES_EOF_pos) {
|
||||||
|
SrsTsPayloadPMTESInfo* info = new SrsTsPayloadPMTESInfo();
|
||||||
|
infos.push_back(info);
|
||||||
|
|
||||||
|
// 5B
|
||||||
|
if (!stream->require(5)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||||
|
srs_error("ts: demux PMT es info failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->stream_type = stream->read_1bytes();
|
||||||
|
info->elementary_PID = stream->read_2bytes();
|
||||||
|
info->ES_info_length = stream->read_2bytes();
|
||||||
|
|
||||||
|
info->elementary_PID &= 0x1FFF;
|
||||||
|
info->ES_info_length &= 0x0FFF;
|
||||||
|
|
||||||
|
if (info->ES_info_length > 0) {
|
||||||
|
if (!stream->require(info->ES_info_length)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||||
|
srs_error("ts: demux PMT es info data failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_freep(info->ES_info);
|
||||||
|
info->ES_info = new char[info->ES_info_length];
|
||||||
|
stream->read_bytes(info->ES_info, info->ES_info_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4B
|
// update the apply pid table.
|
||||||
if (!stream->require(4)) {
|
packet->context->set(packet->pid, SrsTsPidApplyPMT);
|
||||||
ret = ERROR_STREAM_CASTER_TS_AF;
|
|
||||||
srs_error("ts: demux PAT crc32 failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
CRC_32 = stream->read_4bytes();
|
|
||||||
|
|
||||||
// verify crc32.
|
|
||||||
int32_t crc32 = srs_crc32(ppat, stream->pos() - pat_pos - 4);
|
|
||||||
if (crc32 != CRC_32) {
|
|
||||||
ret = ERROR_STREAM_CASTER_TS_CRC32;
|
|
||||||
srs_error("ts: verify PAT crc32 failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_core.hpp>
|
#include <srs_core.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <srs_kernel_codec.hpp>
|
#include <srs_kernel_codec.hpp>
|
||||||
|
|
||||||
|
@ -64,6 +66,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* the pid of ts packet,
|
* the pid of ts packet,
|
||||||
* Table 2-3 ¨C PID table, hls-mpeg-ts-iso13818-1.pdf, page 37
|
* Table 2-3 ¨C PID table, hls-mpeg-ts-iso13818-1.pdf, page 37
|
||||||
|
* NOTE ¨C The transport packets with PID values 0x0000, 0x0001, and 0x0010-0x1FFE are allowed to carry a PCR.
|
||||||
*/
|
*/
|
||||||
enum SrsTsPid
|
enum SrsTsPid
|
||||||
{
|
{
|
||||||
|
@ -73,6 +76,12 @@ enum SrsTsPid
|
||||||
SrsTsPidCAT = 0x01,
|
SrsTsPidCAT = 0x01,
|
||||||
// Transport Stream Description Table
|
// Transport Stream Description Table
|
||||||
SrsTsPidTSDT = 0x02,
|
SrsTsPidTSDT = 0x02,
|
||||||
|
// Reserved
|
||||||
|
SrsTsPidReservedStart = 0x03,
|
||||||
|
SrsTsPidReservedEnd = 0x0f,
|
||||||
|
// May be assigned as network_PID, Program_map_PID, elementary_PID, or for other purposes
|
||||||
|
SrsTsPidAppStart = 0x10,
|
||||||
|
SrsTsPidAppEnd = 0x1ffe,
|
||||||
// null packets (see Table 2-3)
|
// null packets (see Table 2-3)
|
||||||
SrsTsPidNULL = 0x01FFF,
|
SrsTsPidNULL = 0x01FFF,
|
||||||
};
|
};
|
||||||
|
@ -109,11 +118,28 @@ enum SrsTsAdaptationFieldType
|
||||||
SrsTsAdaptationFieldTypeBoth = 0x03,
|
SrsTsAdaptationFieldTypeBoth = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the actually parsed ts pid,
|
||||||
|
* @see SrsTsPid, some pid, for example, PMT/Video/Audio is specified by PAT or other tables.
|
||||||
|
*/
|
||||||
|
enum SrsTsPidApply
|
||||||
|
{
|
||||||
|
SrsTsPidApplyReserved = 0, // TSPidTypeReserved, nothing parsed, used reserved.
|
||||||
|
|
||||||
|
SrsTsPidApplyPAT, // Program associtate table
|
||||||
|
SrsTsPidApplyPMT, // Program map table.
|
||||||
|
|
||||||
|
SrsTsPidApplyVideo, // for video
|
||||||
|
SrsTsPidApplyAudio, // vor audio
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the context of ts, to decode the ts stream.
|
* the context of ts, to decode the ts stream.
|
||||||
*/
|
*/
|
||||||
class SrsTsContext
|
class SrsTsContext
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
std::map<int, SrsTsPidApply> pids;
|
||||||
public:
|
public:
|
||||||
SrsTsContext();
|
SrsTsContext();
|
||||||
virtual ~SrsTsContext();
|
virtual ~SrsTsContext();
|
||||||
|
@ -123,6 +149,16 @@ public:
|
||||||
* @remark we will consume all bytes in stream.
|
* @remark we will consume all bytes in stream.
|
||||||
*/
|
*/
|
||||||
virtual int decode(SrsStream* stream);
|
virtual int decode(SrsStream* stream);
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* get the pid apply, the parsed pid.
|
||||||
|
* @return the apply pid; SrsTsPidApplyReserved for invalid.
|
||||||
|
*/
|
||||||
|
virtual SrsTsPidApply get(int pid);
|
||||||
|
/**
|
||||||
|
* set the pid apply, the parsed pid.
|
||||||
|
*/
|
||||||
|
virtual void set(int pid, SrsTsPidApply apply_pid);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,7 +240,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* The continuity_counter is a 4-bit field incrementing with each Transport Stream packet with the
|
* The continuity_counter is a 4-bit field incrementing with each Transport Stream packet with the
|
||||||
* same PID. The continuity_counter wraps around to 0 after its maximum value. The continuity_counter shall not be
|
* same PID. The continuity_counter wraps around to 0 after its maximum value. The continuity_counter shall not be
|
||||||
*incremented when the adaptation_field_control of the packet equals '00' or '10'.
|
* incremented when the adaptation_field_control of the packet equals '00'(reseverd) or '10'(adaptation field only).
|
||||||
*
|
*
|
||||||
* In Transport Streams, duplicate packets may be sent as two, and only two, consecutive Transport Stream packets of the
|
* In Transport Streams, duplicate packets may be sent as two, and only two, consecutive Transport Stream packets of the
|
||||||
* same PID. The duplicate packets shall have the same continuity_counter value as the original packet and the
|
* same PID. The duplicate packets shall have the same continuity_counter value as the original packet and the
|
||||||
|
@ -222,7 +258,9 @@ private:
|
||||||
SrsTsAdaptationField* adaptation_field;
|
SrsTsAdaptationField* adaptation_field;
|
||||||
SrsTsPayload* payload;
|
SrsTsPayload* payload;
|
||||||
public:
|
public:
|
||||||
SrsTsPacket();
|
SrsTsContext* context;
|
||||||
|
public:
|
||||||
|
SrsTsPacket(SrsTsContext* c);
|
||||||
virtual ~SrsTsPacket();
|
virtual ~SrsTsPacket();
|
||||||
public:
|
public:
|
||||||
virtual int decode(SrsStream* stream);
|
virtual int decode(SrsStream* stream);
|
||||||
|
@ -560,34 +598,6 @@ enum SrsTsPsiId
|
||||||
SrsTsPsiIdForbidden = 0xFF,
|
SrsTsPsiIdForbidden = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* the program of PAT of PSI ts packet.
|
|
||||||
*/
|
|
||||||
class SrsTsPayloadPATProgram
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
// 4B
|
|
||||||
/**
|
|
||||||
* Program_number is a 16-bit field. It specifies the program to which the program_map_PID is
|
|
||||||
* applicable. When set to 0x0000, then the following PID reference shall be the network PID. For all other cases the value
|
|
||||||
* of this field is user defined. This field shall not take any single value more than once within one version of the Program
|
|
||||||
* Association Table.
|
|
||||||
*/
|
|
||||||
int16_t number; // 16bits
|
|
||||||
// reserved 3bits
|
|
||||||
/**
|
|
||||||
* program_map_PID/network_PID 13bits
|
|
||||||
* network_PID ¨C The network_PID is a 13-bit field, which is used only in conjunction with the value of the
|
|
||||||
* program_number set to 0x0000, specifies the PID of the Transport Stream packets which shall contain the Network
|
|
||||||
* Information Table. The value of the network_PID field is defined by the user, but shall only take values as specified in
|
|
||||||
* Table 2-3. The presence of the network_PID is optional.
|
|
||||||
*/
|
|
||||||
int16_t pid;
|
|
||||||
public:
|
|
||||||
SrsTsPayloadPATProgram();
|
|
||||||
virtual ~SrsTsPayloadPATProgram();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the payload of ts packet, can be PES or PSI payload.
|
* the payload of ts packet, can be PES or PSI payload.
|
||||||
*/
|
*/
|
||||||
|
@ -620,22 +630,6 @@ public:
|
||||||
* payload of that packet.
|
* payload of that packet.
|
||||||
*/
|
*/
|
||||||
int8_t pointer_field;
|
int8_t pointer_field;
|
||||||
public:
|
|
||||||
SrsTsPayloadPSI(SrsTsPacket* p);
|
|
||||||
virtual ~SrsTsPayloadPSI();
|
|
||||||
public:
|
|
||||||
virtual int decode(SrsStream* stream);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the PAT payload of PSI ts packet.
|
|
||||||
* 2.4.4.3 Program association Table, hls-mpeg-ts-iso13818-1.pdf, page 61
|
|
||||||
* The Program Association Table provides the correspondence between a program_number and the PID value of the
|
|
||||||
* Transport Stream packets which carry the program definition. The program_number is the numeric label associated with
|
|
||||||
* a program.
|
|
||||||
*/
|
|
||||||
class SrsTsPayloadPAT : public SrsTsPayloadPSI
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// 1B
|
// 1B
|
||||||
/**
|
/**
|
||||||
|
@ -659,7 +653,61 @@ public:
|
||||||
* field shall not exceed 1021 (0x3FD).
|
* field shall not exceed 1021 (0x3FD).
|
||||||
*/
|
*/
|
||||||
u_int16_t section_length; //12bits
|
u_int16_t section_length; //12bits
|
||||||
|
public:
|
||||||
|
// 4B
|
||||||
|
/**
|
||||||
|
* This is a 32-bit field that contains the CRC value that gives a zero output of the registers in the decoder
|
||||||
|
* defined in Annex A after processing the entire section.
|
||||||
|
* @remark crc32(bytes without pointer field, before crc32 field)
|
||||||
|
*/
|
||||||
|
int32_t CRC_32; //32bits
|
||||||
|
public:
|
||||||
|
SrsTsPayloadPSI(SrsTsPacket* p);
|
||||||
|
virtual ~SrsTsPayloadPSI();
|
||||||
|
public:
|
||||||
|
virtual int decode(SrsStream* stream);
|
||||||
|
protected:
|
||||||
|
virtual int psi_decode(SrsStream* stream) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the program of PAT of PSI ts packet.
|
||||||
|
*/
|
||||||
|
class SrsTsPayloadPATProgram
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 4B
|
||||||
|
/**
|
||||||
|
* Program_number is a 16-bit field. It specifies the program to which the program_map_PID is
|
||||||
|
* applicable. When set to 0x0000, then the following PID reference shall be the network PID. For all other cases the value
|
||||||
|
* of this field is user defined. This field shall not take any single value more than once within one version of the Program
|
||||||
|
* Association Table.
|
||||||
|
*/
|
||||||
|
int16_t number; // 16bits
|
||||||
|
// reserved 3bits
|
||||||
|
/**
|
||||||
|
* program_map_PID/network_PID 13bits
|
||||||
|
* network_PID ¨C The network_PID is a 13-bit field, which is used only in conjunction with the value of the
|
||||||
|
* program_number set to 0x0000, specifies the PID of the Transport Stream packets which shall contain the Network
|
||||||
|
* Information Table. The value of the network_PID field is defined by the user, but shall only take values as specified in
|
||||||
|
* Table 2-3. The presence of the network_PID is optional.
|
||||||
|
*/
|
||||||
|
int16_t pid;
|
||||||
|
public:
|
||||||
|
SrsTsPayloadPATProgram();
|
||||||
|
virtual ~SrsTsPayloadPATProgram();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the PAT payload of PSI ts packet.
|
||||||
|
* 2.4.4.3 Program association Table, hls-mpeg-ts-iso13818-1.pdf, page 61
|
||||||
|
* The Program Association Table provides the correspondence between a program_number and the PID value of the
|
||||||
|
* Transport Stream packets which carry the program definition. The program_number is the numeric label associated with
|
||||||
|
* a program.
|
||||||
|
*/
|
||||||
|
class SrsTsPayloadPAT : public SrsTsPayloadPSI
|
||||||
|
{
|
||||||
|
public:
|
||||||
// 2B
|
// 2B
|
||||||
/**
|
/**
|
||||||
* This is a 16-bit field which serves as a label to identify this Transport Stream from any other
|
* This is a 16-bit field which serves as a label to identify this Transport Stream from any other
|
||||||
|
@ -700,16 +748,128 @@ public:
|
||||||
u_int8_t last_section_number; //8bits
|
u_int8_t last_section_number; //8bits
|
||||||
|
|
||||||
// multiple 4B program data.
|
// multiple 4B program data.
|
||||||
int nb_programs;
|
std::vector<SrsTsPayloadPATProgram*> programs;
|
||||||
SrsTsPayloadPATProgram* programs;
|
|
||||||
|
|
||||||
// 4B
|
|
||||||
int32_t CRC_32; //32bits
|
|
||||||
public:
|
public:
|
||||||
SrsTsPayloadPAT(SrsTsPacket* p);
|
SrsTsPayloadPAT(SrsTsPacket* p);
|
||||||
virtual ~SrsTsPayloadPAT();
|
virtual ~SrsTsPayloadPAT();
|
||||||
public:
|
public:
|
||||||
virtual int decode(SrsStream* stream);
|
virtual int psi_decode(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the esinfo for PMT program.
|
||||||
|
*/
|
||||||
|
class SrsTsPayloadPMTESInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* This is an 8-bit field specifying the type of program element carried within the packets with the PID
|
||||||
|
* whose value is specified by the elementary_PID. The values of stream_type are specified in Table 2-29.
|
||||||
|
*/
|
||||||
|
u_int8_t stream_type; //8bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
// 3bits reserved
|
||||||
|
/**
|
||||||
|
* This is a 13-bit field specifying the PID of the Transport Stream packets which carry the associated
|
||||||
|
* program element.
|
||||||
|
*/
|
||||||
|
int16_t elementary_PID; //13bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
// 4bits reserved
|
||||||
|
/**
|
||||||
|
* This is a 12-bit field, the first two bits of which shall be '00'. The remaining 10 bits specify the number
|
||||||
|
* of bytes of the descriptors of the associated program element immediately following the ES_info_length field.
|
||||||
|
*/
|
||||||
|
int16_t ES_info_length; //12bits
|
||||||
|
char* ES_info; //[ES_info_length] bytes.
|
||||||
|
public:
|
||||||
|
SrsTsPayloadPMTESInfo();
|
||||||
|
virtual ~SrsTsPayloadPMTESInfo();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the PMT payload of PSI ts packet.
|
||||||
|
* 2.4.4.8 Program Map Table, hls-mpeg-ts-iso13818-1.pdf, page 64
|
||||||
|
* The Program Map Table provides the mappings between program numbers and the program elements that comprise
|
||||||
|
* them. A single instance of such a mapping is referred to as a "program definition". The program map table is the
|
||||||
|
* complete collection of all program definitions for a Transport Stream. This table shall be transmitted in packets, the PID
|
||||||
|
* values of which are selected by the encoder. More than one PID value may be used, if desired. The table is contained in
|
||||||
|
* one or more sections with the following syntax. It may be segmented to occupy multiple sections. In each section, the
|
||||||
|
* section number field shall be set to zero. Sections are identified by the program_number field.
|
||||||
|
*/
|
||||||
|
class SrsTsPayloadPMT : public SrsTsPayloadPSI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 2B
|
||||||
|
/**
|
||||||
|
* program_number is a 16-bit field. It specifies the program to which the program_map_PID is
|
||||||
|
* applicable. One program definition shall be carried within only one TS_program_map_section. This implies that a
|
||||||
|
* program definition is never longer than 1016 (0x3F8). See Informative Annex C for ways to deal with the cases when
|
||||||
|
* that length is not sufficient. The program_number may be used as a designation for a broadcast channel, for example. By
|
||||||
|
* describing the different program elements belonging to a program, data from different sources (e.g. sequential events)
|
||||||
|
* can be concatenated together to form a continuous set of streams using a program_number. For examples of applications
|
||||||
|
* refer to Annex C.
|
||||||
|
*/
|
||||||
|
u_int16_t program_number; //16bits
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
// 2bits reerverd.
|
||||||
|
/**
|
||||||
|
* This 5-bit field is the version number of the TS_program_map_section. The version number shall be
|
||||||
|
* incremented by 1 modulo 32 when a change in the information carried within the section occurs. Version number refers
|
||||||
|
* to the definition of a single program, and therefore to a single section. When the current_next_indicator is set to '1', then
|
||||||
|
* the version_number shall be that of the currently applicable TS_program_map_section. When the current_next_indicator
|
||||||
|
* is set to '0', then the version_number shall be that of the next applicable TS_program_map_section.
|
||||||
|
*/
|
||||||
|
int8_t version_number; //5bits
|
||||||
|
/**
|
||||||
|
* A 1-bit field, which when set to '1' indicates that the TS_program_map_section sent is
|
||||||
|
* currently applicable. When the bit is set to '0', it indicates that the TS_program_map_section sent is not yet applicable
|
||||||
|
* and shall be the next TS_program_map_section to become valid.
|
||||||
|
*/
|
||||||
|
int8_t current_next_indicator; //1bit
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* The value of this 8-bit field shall be 0x00.
|
||||||
|
*/
|
||||||
|
u_int8_t section_number; //8bits
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* The value of this 8-bit field shall be 0x00.
|
||||||
|
*/
|
||||||
|
u_int8_t last_section_number; //8bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
// 2bits reserved.
|
||||||
|
/**
|
||||||
|
* This is a 13-bit field indicating the PID of the Transport Stream packets which shall contain the PCR fields
|
||||||
|
* valid for the program specified by program_number. If no PCR is associated with a program definition for private
|
||||||
|
* streams, then this field shall take the value of 0x1FFF. Refer to the semantic definition of PCR in 2.4.3.5 and Table 2-3
|
||||||
|
* for restrictions on the choice of PCR_PID value.
|
||||||
|
*/
|
||||||
|
int16_t PCR_PID; //16bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
// 4bits reserved.
|
||||||
|
/**
|
||||||
|
* This is a 12-bit field, the first two bits of which shall be '00'. The remaining 10 bits specify the
|
||||||
|
* number of bytes of the descriptors immediately following the program_info_length field.
|
||||||
|
*/
|
||||||
|
u_int16_t program_info_length; //12bits
|
||||||
|
char* program_info_desc; //[program_info_length]bytes
|
||||||
|
|
||||||
|
// array of TSPMTESInfo.
|
||||||
|
std::vector<SrsTsPayloadPMTESInfo*> infos;
|
||||||
|
public:
|
||||||
|
SrsTsPayloadPMT(SrsTsPacket* p);
|
||||||
|
virtual ~SrsTsPayloadPMT();
|
||||||
|
public:
|
||||||
|
virtual int psi_decode(SrsStream* stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue