mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
for #250, decode the PAT of PSI ts packet.
This commit is contained in:
parent
51aecb8fde
commit
52b62918d9
5 changed files with 394 additions and 9 deletions
|
@ -486,6 +486,8 @@ Supported operating systems and hardware:
|
||||||
).
|
).
|
||||||
1. Support HLS(h.264+mp3) streaming, read
|
1. Support HLS(h.264+mp3) streaming, read
|
||||||
[#301](https://github.com/winlinvip/simple-rtmp-server/issues/301).
|
[#301](https://github.com/winlinvip/simple-rtmp-server/issues/301).
|
||||||
|
1. [dev] Support push MPEG-TS over UDP to SRS, read
|
||||||
|
[#250](https://github.com/winlinvip/simple-rtmp-server/issues/250).
|
||||||
1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
|
1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
|
||||||
1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
|
1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
|
||||||
1. [no-plan] Support multiple processes, for both origin and edge
|
1. [no-plan] Support multiple processes, for both origin and edge
|
||||||
|
|
|
@ -35,19 +35,20 @@ using namespace std;
|
||||||
#include <srs_kernel_ts.hpp>
|
#include <srs_kernel_ts.hpp>
|
||||||
#include <srs_kernel_stream.hpp>
|
#include <srs_kernel_stream.hpp>
|
||||||
#include <srs_kernel_ts.hpp>
|
#include <srs_kernel_ts.hpp>
|
||||||
#include <srs_core_autofree.hpp>
|
|
||||||
|
|
||||||
#ifdef SRS_AUTO_STREAM_CASTER
|
#ifdef SRS_AUTO_STREAM_CASTER
|
||||||
|
|
||||||
SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
|
SrsMpegtsOverUdp::SrsMpegtsOverUdp(SrsConfDirective* c)
|
||||||
{
|
{
|
||||||
stream = new SrsStream();
|
stream = new SrsStream();
|
||||||
|
context = new SrsTsContext();
|
||||||
output = _srs_config->get_stream_caster_output(c);
|
output = _srs_config->get_stream_caster_output(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
|
SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
|
||||||
{
|
{
|
||||||
srs_freep(stream);
|
srs_freep(stream);
|
||||||
|
srs_freep(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
|
int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
|
||||||
|
@ -85,10 +86,7 @@ int SrsMpegtsOverUdp::on_ts_packet(SrsStream* stream)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsTsPacket* packet = new SrsTsPacket();
|
if ((ret = context->decode(stream)) != ERROR_SUCCESS) {
|
||||||
SrsAutoFree(SrsTsPacket, packet);
|
|
||||||
|
|
||||||
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
|
|
||||||
srs_error("mpegts: decode ts packet failed. ret=%d", ret);
|
srs_error("mpegts: decode ts packet failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ class sockaddr_in;
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class SrsStream;
|
class SrsStream;
|
||||||
|
class SrsTsContext;
|
||||||
class SrsConfDirective;
|
class SrsConfDirective;
|
||||||
|
|
||||||
#ifdef SRS_AUTO_STREAM_CASTER
|
#ifdef SRS_AUTO_STREAM_CASTER
|
||||||
|
@ -45,6 +46,7 @@ class SrsMpegtsOverUdp
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsStream* stream;
|
SrsStream* stream;
|
||||||
|
SrsTsContext* context;
|
||||||
std::string output;
|
std::string output;
|
||||||
public:
|
public:
|
||||||
SrsMpegtsOverUdp(SrsConfDirective* c);
|
SrsMpegtsOverUdp(SrsConfDirective* c);
|
||||||
|
|
|
@ -39,6 +39,7 @@ using namespace std;
|
||||||
#include <srs_kernel_buffer.hpp>
|
#include <srs_kernel_buffer.hpp>
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_kernel_stream.hpp>
|
#include <srs_kernel_stream.hpp>
|
||||||
|
#include <srs_core_autofree.hpp>
|
||||||
|
|
||||||
// in ms, for HLS aac sync time.
|
// in ms, for HLS aac sync time.
|
||||||
#define SRS_CONF_DEFAULT_AAC_SYNC 100
|
#define SRS_CONF_DEFAULT_AAC_SYNC 100
|
||||||
|
@ -401,6 +402,33 @@ SrsMpegtsFrame::SrsMpegtsFrame()
|
||||||
key = false;
|
key = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsTsContext::SrsTsContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsContext::~SrsTsContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsTsContext::decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// parse util EOF of stream.
|
||||||
|
// for example, parse multiple times for the PES_packet_length(0) packet.
|
||||||
|
while (!stream->empty()) {
|
||||||
|
SrsTsPacket* packet = new SrsTsPacket();
|
||||||
|
SrsAutoFree(SrsTsPacket, packet);
|
||||||
|
|
||||||
|
if ((ret = packet->decode(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("mpegts: decode ts packet failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SrsTsPacket::SrsTsPacket()
|
SrsTsPacket::SrsTsPacket()
|
||||||
{
|
{
|
||||||
sync_byte = 0;
|
sync_byte = 0;
|
||||||
|
@ -412,11 +440,13 @@ SrsTsPacket::SrsTsPacket()
|
||||||
adaption_field_control = SrsTsAdaptationFieldTypeReserved;
|
adaption_field_control = SrsTsAdaptationFieldTypeReserved;
|
||||||
continuity_counter = 0;
|
continuity_counter = 0;
|
||||||
adaptation_field = NULL;
|
adaptation_field = NULL;
|
||||||
|
payload = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsTsPacket::~SrsTsPacket()
|
SrsTsPacket::~SrsTsPacket()
|
||||||
{
|
{
|
||||||
srs_freep(adaptation_field);
|
srs_freep(adaptation_field);
|
||||||
|
srs_freep(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsTsPacket::decode(SrsStream* stream)
|
int SrsTsPacket::decode(SrsStream* stream)
|
||||||
|
@ -471,6 +501,23 @@ int SrsTsPacket::decode(SrsStream* stream)
|
||||||
// calc the user defined data size for payload.
|
// calc the user defined data size for payload.
|
||||||
int nb_payload = SRS_TS_PACKET_SIZE - (stream->pos() - pos);
|
int nb_payload = SRS_TS_PACKET_SIZE - (stream->pos() - pos);
|
||||||
|
|
||||||
|
// optional: payload.
|
||||||
|
if (adaption_field_control == SrsTsAdaptationFieldTypePayloadOnly || adaption_field_control == SrsTsAdaptationFieldTypeBoth) {
|
||||||
|
if (pid == SrsTsPidPAT) {
|
||||||
|
// 2.4.4.3 Program association Table
|
||||||
|
srs_freep(payload);
|
||||||
|
payload = new SrsTsPayloadPAT(this);
|
||||||
|
} else {
|
||||||
|
// left bytes as reserved.
|
||||||
|
stream->skip(nb_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload && (ret = payload->decode(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("ts: demux payload failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,6 +760,145 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram()
|
||||||
|
{
|
||||||
|
number = 0;
|
||||||
|
pid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
|
||||||
|
{
|
||||||
|
packet = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayload::~SrsTsPayload()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
||||||
|
{
|
||||||
|
pointer_field = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsTsPayloadPSI::~SrsTsPayloadPSI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsTsPayloadPSI::decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the payload of the Transport Stream packet contains PSI data, the payload_unit_start_indicator has the following
|
||||||
|
* significance: if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value
|
||||||
|
* shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. If the
|
||||||
|
* Transport Stream packet does not carry the first byte of a PSI section, the payload_unit_start_indicator value shall be '0',
|
||||||
|
* indicating that there is no pointer_field in the payload. Refer to 2.4.4.1 and 2.4.4.2. This also applies to private streams of
|
||||||
|
* stream_type 5 (refer to Table 2-29).
|
||||||
|
*/
|
||||||
|
if (packet->payload_unit_start_indicator) {
|
||||||
|
if (!stream->require(1)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_AF;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
// 1B
|
||||||
|
table_id = (SrsTsPsiId)stream->read_1bytes();
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
section_length = stream->read_2bytes();
|
||||||
|
|
||||||
|
section_syntax_indicator = (section_length >> 15) & 0x01;
|
||||||
|
const0_value = (section_length >> 14) & 0x01;
|
||||||
|
section_length &= 0x0FFF;
|
||||||
|
|
||||||
|
if (!stream->require(section_length)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_AF;
|
||||||
|
srs_error("ts: demux PAT section failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int pos = stream->pos();
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
transport_stream_id = stream->read_2bytes();
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
current_next_indicator = stream->read_1bytes();
|
||||||
|
|
||||||
|
version_number = (current_next_indicator >> 1) & 0x1F;
|
||||||
|
current_next_indicator &= 0x01;
|
||||||
|
|
||||||
|
// TODO: FIXME: check the indicator.
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
section_number = stream->read_1bytes();
|
||||||
|
// 1B
|
||||||
|
last_section_number = stream->read_1bytes();
|
||||||
|
|
||||||
|
// 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 < 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4B
|
||||||
|
if (!stream->require(4)) {
|
||||||
|
ret = ERROR_STREAM_CASTER_TS_AF;
|
||||||
|
srs_error("ts: demux PAT crc32 failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
CRC_32 = stream->read_4bytes();
|
||||||
|
|
||||||
|
// TODO: FIXME: verfy crc32.
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
|
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
|
||||||
{
|
{
|
||||||
writer = w;
|
writer = w;
|
||||||
|
|
|
@ -42,6 +42,7 @@ class SrsAvcAacCodec;
|
||||||
class SrsCodecSample;
|
class SrsCodecSample;
|
||||||
class SrsSimpleBuffer;
|
class SrsSimpleBuffer;
|
||||||
class SrsTsAdaptationField;
|
class SrsTsAdaptationField;
|
||||||
|
class SrsTsPayload;
|
||||||
|
|
||||||
// Transport Stream packets are 188 bytes in length.
|
// Transport Stream packets are 188 bytes in length.
|
||||||
#define SRS_TS_PACKET_SIZE 188
|
#define SRS_TS_PACKET_SIZE 188
|
||||||
|
@ -108,6 +109,22 @@ enum SrsTsAdaptationFieldType
|
||||||
SrsTsAdaptationFieldTypeBoth = 0x03,
|
SrsTsAdaptationFieldTypeBoth = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the context of ts, to decode the ts stream.
|
||||||
|
*/
|
||||||
|
class SrsTsContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsTsContext();
|
||||||
|
virtual ~SrsTsContext();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* the stream contains only one ts packet.
|
||||||
|
* @remark we will consume all bytes in stream.
|
||||||
|
*/
|
||||||
|
virtual int decode(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the packet in ts stream,
|
* the packet in ts stream,
|
||||||
* 2.4.3.2 Transport Stream packet layer, hls-mpeg-ts-iso13818-1.pdf, page 36
|
* 2.4.3.2 Transport Stream packet layer, hls-mpeg-ts-iso13818-1.pdf, page 36
|
||||||
|
@ -203,14 +220,11 @@ public:
|
||||||
u_int8_t continuity_counter; //4bits
|
u_int8_t continuity_counter; //4bits
|
||||||
private:
|
private:
|
||||||
SrsTsAdaptationField* adaptation_field;
|
SrsTsAdaptationField* adaptation_field;
|
||||||
|
SrsTsPayload* payload;
|
||||||
public:
|
public:
|
||||||
SrsTsPacket();
|
SrsTsPacket();
|
||||||
virtual ~SrsTsPacket();
|
virtual ~SrsTsPacket();
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* the stream contains only one ts packet.
|
|
||||||
* @remark we will consume all bytes in stream.
|
|
||||||
*/
|
|
||||||
virtual int decode(SrsStream* stream);
|
virtual int decode(SrsStream* stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -515,6 +529,189 @@ public:
|
||||||
virtual int decode(SrsStream* stream);
|
virtual int decode(SrsStream* stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2.4.4.4 Table_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 62
|
||||||
|
* The table_id field identifies the contents of a Transport Stream PSI section as shown in Table 2-26.
|
||||||
|
*/
|
||||||
|
enum SrsTsPsiId
|
||||||
|
{
|
||||||
|
// program_association_section
|
||||||
|
SrsTsPsiIdPas = 0x00,
|
||||||
|
// conditional_access_section (CA_section)
|
||||||
|
SrsTsPsiIdCas = 0x01,
|
||||||
|
// TS_program_map_section
|
||||||
|
SrsTsPsiIdPms = 0x02,
|
||||||
|
// TS_description_section
|
||||||
|
SrsTsPsiIdDs = 0x03,
|
||||||
|
// ISO_IEC_14496_scene_description_section
|
||||||
|
SrsTsPsiIdSds = 0x04,
|
||||||
|
// ISO_IEC_14496_object_descriptor_section
|
||||||
|
SrsTsPsiIdOds = 0x05,
|
||||||
|
// ITU-T Rec. H.222.0 | ISO/IEC 13818-1 reserved
|
||||||
|
SrsTsPsiIdIso138181Start = 0x06,
|
||||||
|
SrsTsPsiIdIso138181End = 0x37,
|
||||||
|
// Defined in ISO/IEC 13818-6
|
||||||
|
SrsTsPsiIdIso138186Start = 0x38,
|
||||||
|
SrsTsPsiIdIso138186End = 0x3F,
|
||||||
|
// User private
|
||||||
|
SrsTsPsiIdUserStart = 0x40,
|
||||||
|
SrsTsPsiIdUserEnd = 0xFE,
|
||||||
|
// forbidden
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
class SrsTsPayload
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SrsTsPacket* packet;
|
||||||
|
public:
|
||||||
|
SrsTsPayload(SrsTsPacket* p);
|
||||||
|
virtual ~SrsTsPayload();
|
||||||
|
public:
|
||||||
|
virtual int decode(SrsStream* stream) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the PSI payload of ts packet.
|
||||||
|
* 2.4.4 Program specific information, hls-mpeg-ts-iso13818-1.pdf, page 59
|
||||||
|
*/
|
||||||
|
class SrsTsPayloadPSI : public SrsTsPayload
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* This is an 8-bit field whose value shall be the number of bytes, immediately following the pointer_field
|
||||||
|
* until the first byte of the first section that is present in the payload of the Transport Stream packet (so a value of 0x00 in
|
||||||
|
* the pointer_field indicates that the section starts immediately after the pointer_field). When at least one section begins in
|
||||||
|
* a given Transport Stream packet, then the payload_unit_start_indicator (refer to 2.4.3.2) shall be set to 1 and the first
|
||||||
|
* byte of the payload of that Transport Stream packet shall contain the pointer. When no section begins in a given
|
||||||
|
* Transport Stream packet, then the payload_unit_start_indicator shall be set to 0 and no pointer shall be sent in the
|
||||||
|
* 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
|
||||||
|
/**
|
||||||
|
* This is an 8-bit field, which shall be set to 0x00 as shown in Table 2-26.
|
||||||
|
*/
|
||||||
|
SrsTsPsiId table_id; //8bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
/**
|
||||||
|
* The section_syntax_indicator is a 1-bit field which shall be set to '1'.
|
||||||
|
*/
|
||||||
|
int8_t section_syntax_indicator; //1bit
|
||||||
|
/**
|
||||||
|
* const value, must be '0'
|
||||||
|
*/
|
||||||
|
int8_t const0_value; //1bit
|
||||||
|
// 2bits 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 section, starting immediately following the section_length field, and including the CRC. The value in this
|
||||||
|
* field shall not exceed 1021 (0x3FD).
|
||||||
|
*/
|
||||||
|
u_int16_t section_length; //12bits
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
/**
|
||||||
|
* This is a 16-bit field which serves as a label to identify this Transport Stream from any other
|
||||||
|
* multiplex within a network. Its value is defined by the user.
|
||||||
|
*/
|
||||||
|
u_int16_t transport_stream_id; //16bits
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
// 2bits reerverd.
|
||||||
|
/**
|
||||||
|
* This 5-bit field is the version number of the whole Program Association Table. The version number
|
||||||
|
* shall be incremented by 1 modulo 32 whenever the definition of the Program Association Table changes. When the
|
||||||
|
* current_next_indicator is set to '1', then the version_number shall be that of the currently applicable Program Association
|
||||||
|
* Table. When the current_next_indicator is set to '0', then the version_number shall be that of the next applicable Program
|
||||||
|
* Association Table.
|
||||||
|
*/
|
||||||
|
int8_t version_number; //5bits
|
||||||
|
/**
|
||||||
|
* A 1-bit indicator, which when set to '1' indicates that the Program Association Table sent is
|
||||||
|
* currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable and shall be the next
|
||||||
|
* table to become valid.
|
||||||
|
*/
|
||||||
|
int8_t current_next_indicator; //1bit
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* This 8-bit field gives the number of this section. The section_number of the first section in the
|
||||||
|
* Program Association Table shall be 0x00. It shall be incremented by 1 with each additional section in the Program
|
||||||
|
* Association Table.
|
||||||
|
*/
|
||||||
|
u_int8_t section_number; //8bits
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
/**
|
||||||
|
* This 8-bit field specifies the number of the last section (that is, the section with the highest
|
||||||
|
* section_number) of the complete Program Association Table.
|
||||||
|
*/
|
||||||
|
u_int8_t last_section_number; //8bits
|
||||||
|
|
||||||
|
// multiple 4B program data.
|
||||||
|
int nb_programs;
|
||||||
|
SrsTsPayloadPATProgram* programs;
|
||||||
|
|
||||||
|
// 4B
|
||||||
|
int32_t CRC_32; //32bits
|
||||||
|
public:
|
||||||
|
SrsTsPayloadPAT(SrsTsPacket* p);
|
||||||
|
virtual ~SrsTsPayloadPAT();
|
||||||
|
public:
|
||||||
|
virtual int decode(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write data from frame(header info) and buffer(data) to ts file.
|
* write data from frame(header info) and buffer(data) to ts file.
|
||||||
* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter
|
* it's a simple object wrapper for utility from nginx-rtmp: SrsMpegtsWriter
|
||||||
|
|
Loading…
Reference in a new issue