diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index b153ad484..0be810ad7 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -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_AF 4014 #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. diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index da6970dfc..bd490451e 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -417,7 +417,7 @@ int SrsTsContext::decode(SrsStream* stream) // parse util EOF of stream. // for example, parse multiple times for the PES_packet_length(0) packet. while (!stream->empty()) { - SrsTsPacket* packet = new SrsTsPacket(); + SrsTsPacket* packet = new SrsTsPacket(this); SrsAutoFree(SrsTsPacket, packet); if ((ret = packet->decode(stream)) != ERROR_SUCCESS) { @@ -429,8 +429,23 @@ int SrsTsContext::decode(SrsStream* stream) 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; transport_error_indicator = 0; payload_unit_start_indicator = 0; @@ -508,8 +523,15 @@ int SrsTsPacket::decode(SrsStream* stream) srs_freep(payload); payload = new SrsTsPayloadPAT(this); } else { - // left bytes as reserved. - stream->skip(nb_payload); + 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 { + // left bytes as reserved. + stream->skip(nb_payload); + } } if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) { @@ -676,14 +698,16 @@ int SrsTsAdaptationField::decode(SrsStream* stream) } transport_private_data_length = (u_int8_t)stream->read_1bytes(); - if (!stream->require(transport_private_data_length)) { - ret = ERROR_STREAM_CASTER_TS_AF; - srs_error("ts: demux af transport_private_data_flag failed. ret=%d", ret); - return ret; + if (transport_private_data_length> 0) { + if (!stream->require(transport_private_data_length)) { + ret = ERROR_STREAM_CASTER_TS_AF; + srs_error("ts: demux af transport_private_data_flag failed. ret=%d", ret); + return ret; + } + srs_freep(transport_private_data); + transport_private_data = new char[transport_private_data_length]; + stream->read_bytes(transport_private_data, transport_private_data_length); } - srs_freep(transport_private_data); - transport_private_data = new char[transport_private_data_length]; - stream->read_bytes(transport_private_data, transport_private_data_length); } if (adaptation_field_extension_flag) { @@ -760,16 +784,6 @@ int SrsTsAdaptationField::decode(SrsStream* stream) return ret; } -SrsTsPayloadPATProgram::SrsTsPayloadPATProgram() -{ - number = 0; - pid = 0; -} - -SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram() -{ -} - SrsTsPayload::SrsTsPayload(SrsTsPacket* p) { packet = p; @@ -782,6 +796,7 @@ SrsTsPayload::~SrsTsPayload() SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p) { pointer_field = 0; + CRC_32 = 0; } SrsTsPayloadPSI::~SrsTsPayloadPSI() @@ -802,43 +817,21 @@ int SrsTsPayloadPSI::decode(SrsStream* stream) */ if (packet->payload_unit_start_indicator) { 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); return ret; } 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 char* ppat = stream->data() + stream->pos(); int pat_pos = stream->pos(); - // atleast 8B without programs and crc32 - if (!stream->require(8)) { - ret = ERROR_STREAM_CASTER_TS_AF; - srs_error("ts: demux PAT failed. ret=%d", ret); + // atleast 3B for all psi. + if (!stream->require(3)) { + ret = ERROR_STREAM_CASTER_TS_PSI; + srs_error("ts: demux PSI failed. ret=%d", ret); return ret; } // 1B @@ -851,11 +844,82 @@ int SrsTsPayloadPAT::decode(SrsStream* stream) const0_value = (section_length >> 14) & 0x01; 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)) { - ret = ERROR_STREAM_CASTER_TS_AF; + ret = ERROR_STREAM_CASTER_TS_PSI; srs_error("ts: demux PAT section failed. ret=%d", 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::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(); // 2B @@ -876,36 +940,137 @@ int SrsTsPayloadPAT::decode(SrsStream* stream) // multiple 4B program data. int program_bytes = section_length - 4 - (stream->pos() - pos); - nb_programs = program_bytes / 4; - if (nb_programs > 0) { - srs_freep(programs); - programs = new SrsTsPayloadPATProgram[nb_programs]; + for (int i = 0; i < program_bytes; i += 4) { + SrsTsPayloadPATProgram* program = new SrsTsPayloadPATProgram(); - for (int i = 0; i < nb_programs; i++) { - SrsTsPayloadPATProgram* program = programs + i; + int tmpv = stream->read_4bytes(); + program->number = (int16_t)((tmpv >> 16) & 0xFFFF); + program->pid = (int16_t)(tmpv & 0x1FFF); - int tmpv = stream->read_4bytes(); - program->number = (int16_t)((tmpv >> 16) & 0xFFFF); - program->pid = (int16_t)(tmpv & 0x1FFF); - } + // update the apply pid table. + packet->context->set(program->pid, SrsTsPidApplyPMT); + + programs.push_back(program); } - - // 4B - if (!stream->require(4)) { - ret = ERROR_STREAM_CASTER_TS_AF; - srs_error("ts: demux PAT crc32 failed. ret=%d", ret); - return ret; + + // 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::iterator it; + for (it = infos.begin(); it != infos.end(); ++it) { + SrsTsPayloadPMTESInfo* info = *it; + srs_freep(info); } - CRC_32 = stream->read_4bytes(); + infos.clear(); +} - // 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); +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); + } + } + + // update the apply pid table. + packet->context->set(packet->pid, SrsTsPidApplyPMT); + return ret; } diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp index 35cde69e4..fd2f90d26 100644 --- a/trunk/src/kernel/srs_kernel_ts.hpp +++ b/trunk/src/kernel/srs_kernel_ts.hpp @@ -30,6 +30,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include +#include #include @@ -64,15 +66,22 @@ public: /** * the pid of ts packet, * 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 { // Program Association Table(see Table 2-25). - SrsTsPidPAT = 0x00, + SrsTsPidPAT = 0x00, // Conditional Access Table (see Table 2-27). - SrsTsPidCAT = 0x01, + SrsTsPidCAT = 0x01, // 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) SrsTsPidNULL = 0x01FFF, }; @@ -109,11 +118,28 @@ enum SrsTsAdaptationFieldType 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. */ class SrsTsContext { +private: + std::map pids; public: SrsTsContext(); virtual ~SrsTsContext(); @@ -123,6 +149,16 @@ public: * @remark we will consume all bytes in 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 * 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 * 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; SrsTsPayload* payload; public: - SrsTsPacket(); + SrsTsContext* context; +public: + SrsTsPacket(SrsTsContext* c); virtual ~SrsTsPacket(); public: virtual int decode(SrsStream* stream); @@ -560,34 +598,6 @@ enum SrsTsPsiId 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. */ @@ -620,22 +630,6 @@ public: * payload of that packet. */ 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: // 1B /** @@ -659,7 +653,61 @@ public: * field shall not exceed 1021 (0x3FD). */ 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 /** * 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 // multiple 4B program data. - int nb_programs; - SrsTsPayloadPATProgram* programs; - - // 4B - int32_t CRC_32; //32bits + std::vector programs; public: SrsTsPayloadPAT(SrsTsPacket* p); virtual ~SrsTsPayloadPAT(); 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 infos; +public: + SrsTsPayloadPMT(SrsTsPacket* p); + virtual ~SrsTsPayloadPMT(); +public: + virtual int psi_decode(SrsStream* stream); }; /**