mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 11:51:57 +00:00
implements the pat/pmt write ts header.
This commit is contained in:
parent
e88c1e32ee
commit
1ed3e283ab
2 changed files with 802 additions and 114 deletions
|
@ -517,6 +517,8 @@ ISrsTsHandler::~ISrsTsHandler()
|
|||
|
||||
SrsTsContext::SrsTsContext()
|
||||
{
|
||||
vcodec = SrsCodecVideoReserved;
|
||||
acodec = SrsCodecAudioReserved1;
|
||||
}
|
||||
|
||||
SrsTsContext::~SrsTsContext()
|
||||
|
@ -529,6 +531,30 @@ SrsTsContext::~SrsTsContext()
|
|||
pids.clear();
|
||||
}
|
||||
|
||||
SrsTsChannel* SrsTsContext::get(int pid)
|
||||
{
|
||||
if (pids.find(pid) == pids.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return pids[pid];
|
||||
}
|
||||
|
||||
void SrsTsContext::set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream)
|
||||
{
|
||||
SrsTsChannel* channel = NULL;
|
||||
|
||||
if (pids.find(pid) == pids.end()) {
|
||||
channel = new SrsTsChannel();
|
||||
pids[pid] = channel;
|
||||
} else {
|
||||
channel = pids[pid];
|
||||
}
|
||||
|
||||
channel->pid = pid;
|
||||
channel->apply = apply_pid;
|
||||
channel->stream = stream;
|
||||
}
|
||||
|
||||
int SrsTsContext::decode(SrsStream* stream, ISrsTsHandler* handler)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
@ -559,28 +585,122 @@ int SrsTsContext::decode(SrsStream* stream, ISrsTsHandler* handler)
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsTsChannel* SrsTsContext::get(int pid)
|
||||
int SrsTsContext::encode(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* payload, SrsCodecVideo vc, SrsCodecAudio ac)
|
||||
{
|
||||
if (pids.find(pid) == pids.end()) {
|
||||
return NULL;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// when any codec changed, write PAT/PMT table.
|
||||
if (vcodec != vc || acodec != ac) {
|
||||
vcodec = vc;
|
||||
acodec = ac;
|
||||
if ((ret = encode_pat_pmt(writer, vc, ac)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return pids[pid];
|
||||
|
||||
// encode the media frame to PES packets over TS.
|
||||
return encode_pes(writer, frame, payload);
|
||||
}
|
||||
|
||||
void SrsTsContext::set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream)
|
||||
int SrsTsContext::encode_pat_pmt(SrsFileWriter* writer, SrsCodecVideo vc, SrsCodecAudio ac)
|
||||
{
|
||||
SrsTsChannel* channel = NULL;
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (pids.find(pid) == pids.end()) {
|
||||
channel = new SrsTsChannel();
|
||||
pids[pid] = channel;
|
||||
} else {
|
||||
channel = pids[pid];
|
||||
SrsTsStream vs = SrsTsStreamReserved;
|
||||
SrsTsStream as = SrsTsStreamReserved;
|
||||
switch (vc) {
|
||||
case SrsCodecVideoAVC: vs = SrsTsStreamVideoH264; break;
|
||||
case SrsCodecVideoReserved:
|
||||
case SrsCodecVideoReserved1:
|
||||
case SrsCodecVideoReserved2:
|
||||
case SrsCodecVideoSorensonH263:
|
||||
case SrsCodecVideoScreenVideo:
|
||||
case SrsCodecVideoOn2VP6:
|
||||
case SrsCodecVideoOn2VP6WithAlphaChannel:
|
||||
case SrsCodecVideoScreenVideoVersion2:
|
||||
break;
|
||||
}
|
||||
switch (ac) {
|
||||
case SrsCodecAudioAAC: as = SrsTsStreamAudioAAC; break;
|
||||
case SrsCodecAudioMP3: as = SrsTsStreamAudioMp3; break;
|
||||
case SrsCodecAudioReserved1:
|
||||
case SrsCodecAudioLinearPCMPlatformEndian:
|
||||
case SrsCodecAudioADPCM:
|
||||
case SrsCodecAudioLinearPCMLittleEndian:
|
||||
case SrsCodecAudioNellymoser16kHzMono:
|
||||
case SrsCodecAudioNellymoser8kHzMono:
|
||||
case SrsCodecAudioNellymoser:
|
||||
case SrsCodecAudioReservedG711AlawLogarithmicPCM:
|
||||
case SrsCodecAudioReservedG711MuLawLogarithmicPCM:
|
||||
case SrsCodecAudioReserved:
|
||||
case SrsCodecAudioSpeex:
|
||||
case SrsCodecAudioReservedMP3_8kHz:
|
||||
case SrsCodecAudioReservedDeviceSpecificSound:
|
||||
break;
|
||||
}
|
||||
|
||||
channel->pid = pid;
|
||||
channel->apply = apply_pid;
|
||||
channel->stream = stream;
|
||||
int16_t pmt_number = 1;
|
||||
int16_t pmt_pid = 0x100;
|
||||
if (true) {
|
||||
SrsTsPacket* pkt = SrsTsPacket::create_pat(this, pmt_number, pmt_pid);
|
||||
SrsAutoFree(SrsTsPacket, pkt);
|
||||
|
||||
char* buf = new char[SRS_TS_PACKET_SIZE];
|
||||
SrsAutoFree(char, buf);
|
||||
|
||||
// set the left bytes with 0xFF.
|
||||
int nb_buf = pkt->size();
|
||||
srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
|
||||
memset(buf + nb_buf, 0xFF, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
|
||||
SrsStream stream;
|
||||
if ((ret = stream.initialize(buf, nb_buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if ((ret = pkt->encode(&stream)) != ERROR_SUCCESS) {
|
||||
srs_error("ts encode ts packet failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = writer->write(buf, SRS_TS_PACKET_SIZE, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("ts write ts packet failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
int16_t video_pid = 0x101;
|
||||
int16_t audio_pid = 0x102;
|
||||
if (true) {
|
||||
SrsTsPacket* pkt = SrsTsPacket::create_pmt(this, pmt_number, pmt_pid, video_pid, vs, audio_pid, as);
|
||||
SrsAutoFree(SrsTsPacket, pkt);
|
||||
|
||||
char* buf = new char[SRS_TS_PACKET_SIZE];
|
||||
SrsAutoFree(char, buf);
|
||||
|
||||
// set the left bytes with 0xFF.
|
||||
int nb_buf = pkt->size();
|
||||
srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
|
||||
memset(buf + nb_buf, 0xFF, SRS_TS_PACKET_SIZE - nb_buf);
|
||||
|
||||
SrsStream stream;
|
||||
if ((ret = stream.initialize(buf, nb_buf)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if ((ret = pkt->encode(&stream)) != ERROR_SUCCESS) {
|
||||
srs_error("ts encode ts packet failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ret = writer->write(buf, SRS_TS_PACKET_SIZE, NULL)) != ERROR_SUCCESS) {
|
||||
srs_error("ts write ts packet failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* payload)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPacket::SrsTsPacket(SrsTsContext* c)
|
||||
|
@ -688,6 +808,126 @@ int SrsTsPacket::decode(SrsStream* stream, SrsTsMessage** ppmsg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPacket::size()
|
||||
{
|
||||
int sz = 4;
|
||||
|
||||
sz += adaptation_field? adaptation_field->size() : 0;
|
||||
sz += payload? payload->size() : 0;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsPacket::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// 4B ts packet header.
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_HEADER;
|
||||
srs_error("ts: mux header failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream->write_1bytes(sync_byte);
|
||||
|
||||
int16_t pidv = pid & 0x1FFF;
|
||||
pidv |= (transport_priority << 13) & 0x2000;
|
||||
pidv |= (transport_error_indicator << 15) & 0x8000;
|
||||
pidv |= (payload_unit_start_indicator << 14) & 0x4000;
|
||||
stream->write_2bytes(pidv);
|
||||
|
||||
int8_t ccv = continuity_counter & 0x0F;
|
||||
ccv |= (transport_scrambling_control << 6) & 0xC0;
|
||||
ccv |= (adaption_field_control << 4) & 0x30;
|
||||
stream->write_1bytes(ccv);
|
||||
|
||||
srs_info("ts: header sync=%#x error=%d unit_start=%d priotiry=%d pid=%d scrambling=%d adaption=%d counter=%d",
|
||||
sync_byte, transport_error_indicator, payload_unit_start_indicator, transport_priority, pid,
|
||||
transport_scrambling_control, adaption_field_control, continuity_counter);
|
||||
|
||||
// optional: adaptation field
|
||||
if (adaptation_field) {
|
||||
if ((ret = adaptation_field->encode(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("ts: mux af faield. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("ts: mux af ok.");
|
||||
}
|
||||
|
||||
// optional: payload.
|
||||
if (payload) {
|
||||
if ((ret = payload->encode(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("ts: mux payload failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("ts: mux payload ok.");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPacket* SrsTsPacket::create_pat(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid)
|
||||
{
|
||||
SrsTsPacket* pkt = new SrsTsPacket(context);
|
||||
pkt->sync_byte = 0x47;
|
||||
pkt->transport_error_indicator = 0;
|
||||
pkt->payload_unit_start_indicator = 1;
|
||||
pkt->transport_priority = 0;
|
||||
pkt->pid = SrsTsPidPAT;
|
||||
pkt->transport_scrambling_control = SrsTsScrambledDisabled;
|
||||
pkt->adaption_field_control = SrsTsAdaptationFieldTypePayloadOnly;
|
||||
pkt->continuity_counter = 0;
|
||||
pkt->adaptation_field = NULL;
|
||||
SrsTsPayloadPAT* pat = new SrsTsPayloadPAT(pkt);
|
||||
pkt->payload = pat;
|
||||
|
||||
pat->pointer_field = 0;
|
||||
pat->table_id = SrsTsPsiIdPas;
|
||||
pat->section_syntax_indicator = 1;
|
||||
pat->section_length = 0; // calc in size.
|
||||
pat->transport_stream_id = 1;
|
||||
pat->version_number = 0;
|
||||
pat->current_next_indicator = 1;
|
||||
pat->section_number = 0;
|
||||
pat->last_section_number = 0;
|
||||
pat->programs.push_back(new SrsTsPayloadPATProgram(pmt_number, pmt_pid));
|
||||
pat->CRC_32 = 0; // calc in encode.
|
||||
return pkt;
|
||||
}
|
||||
|
||||
SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as)
|
||||
{
|
||||
SrsTsPacket* pkt = new SrsTsPacket(context);
|
||||
pkt->sync_byte = 0x47;
|
||||
pkt->transport_error_indicator = 0;
|
||||
pkt->payload_unit_start_indicator = 1;
|
||||
pkt->transport_priority = 0;
|
||||
pkt->pid = (SrsTsPid)pmt_pid;
|
||||
pkt->transport_scrambling_control = SrsTsScrambledDisabled;
|
||||
pkt->adaption_field_control = SrsTsAdaptationFieldTypePayloadOnly;
|
||||
pkt->continuity_counter = 0;
|
||||
pkt->adaptation_field = NULL;
|
||||
SrsTsPayloadPMT* pmt = new SrsTsPayloadPMT(pkt);
|
||||
pkt->payload = pmt;
|
||||
|
||||
pmt->pointer_field = 0;
|
||||
pmt->table_id = SrsTsPsiIdPms;
|
||||
pmt->section_syntax_indicator = 1;
|
||||
pmt->section_length = 0; // calc in size.
|
||||
pmt->program_number = pmt_number;
|
||||
pmt->version_number = 0;
|
||||
pmt->current_next_indicator = 1;
|
||||
pmt->section_number = 0;
|
||||
pmt->last_section_number = 0;
|
||||
pmt->PCR_PID = vpid;
|
||||
pmt->program_info_length = 0;
|
||||
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid));
|
||||
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
|
||||
pmt->CRC_32 = 0; // calc in encode.
|
||||
return pkt;
|
||||
}
|
||||
|
||||
SrsTsAdaptationField::SrsTsAdaptationField(SrsTsPacket* pkt)
|
||||
{
|
||||
packet = pkt;
|
||||
|
@ -929,6 +1169,27 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsAdaptationField::size()
|
||||
{
|
||||
int sz = 2;
|
||||
|
||||
sz += PCR_flag? 6 : 0;
|
||||
sz += OPCR_flag? 6 : 0;
|
||||
sz += splicing_point_flag? 1 : 0;
|
||||
sz += transport_private_data_flag? 1 + transport_private_data_length : 0;
|
||||
sz += adaptation_field_extension_flag? 2 + adaptation_field_extension_length : 0;
|
||||
sz += nb_af_ext_reserved;
|
||||
sz += nb_af_reserved;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsAdaptationField::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
|
||||
{
|
||||
packet = p;
|
||||
|
@ -1356,6 +1617,65 @@ int SrsTsPayloadPES::decode(SrsStream* stream, SrsTsMessage** ppmsg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPES::size()
|
||||
{
|
||||
int sz = 6;
|
||||
|
||||
SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id;
|
||||
|
||||
if (sid != SrsTsPESStreamIdProgramStreamMap
|
||||
&& sid != SrsTsPESStreamIdPaddingStream
|
||||
&& sid != SrsTsPESStreamIdPrivateStream2
|
||||
&& sid != SrsTsPESStreamIdEcmStream
|
||||
&& sid != SrsTsPESStreamIdEmmStream
|
||||
&& sid != SrsTsPESStreamIdProgramStreamDirectory
|
||||
&& sid != SrsTsPESStreamIdDsmccStream
|
||||
&& sid != SrsTsPESStreamIdH2221TypeE
|
||||
) {
|
||||
sz += 3;
|
||||
|
||||
sz += (PTS_DTS_flags == 0x2)? 5:0;
|
||||
sz += (PTS_DTS_flags == 0x3)? 10:0;
|
||||
sz += ESCR_flag? 6:0;
|
||||
sz += ES_rate_flag? 3:0;
|
||||
sz += DSM_trick_mode_flag? 1:0;
|
||||
sz += additional_copy_info_flag? 1:0;
|
||||
sz += PES_CRC_flag? 2:0;
|
||||
sz += PES_extension_flag? 1:0;
|
||||
|
||||
if (PES_extension_flag) {
|
||||
sz += PES_private_data_flag? 16:0;
|
||||
sz += pack_header_field_flag? 1 + pack_field_length:0; // 1+x bytes.
|
||||
sz += program_packet_sequence_counter_flag? 2:0;
|
||||
sz += P_STD_buffer_flag? 2:0;
|
||||
sz += PES_extension_flag_2? 1 + PES_extension_field_length:0; // 1+x bytes.
|
||||
}
|
||||
|
||||
sz += nb_stuffings;
|
||||
|
||||
// packet bytes
|
||||
} else if (sid == SrsTsPESStreamIdProgramStreamMap
|
||||
|| sid == SrsTsPESStreamIdPrivateStream2
|
||||
|| sid == SrsTsPESStreamIdEcmStream
|
||||
|| sid == SrsTsPESStreamIdEmmStream
|
||||
|| sid == SrsTsPESStreamIdProgramStreamDirectory
|
||||
|| sid == SrsTsPESStreamIdDsmccStream
|
||||
|| sid == SrsTsPESStreamIdH2221TypeE
|
||||
) {
|
||||
// packet bytes
|
||||
} else {
|
||||
// nb_drop
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPES::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPES::decode_33bits_dts_pts(SrsStream* stream, int64_t* pv)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
@ -1420,6 +1740,8 @@ int SrsTsPayloadPES::decode_33bits_dts_pts(SrsStream* stream, int64_t* pv)
|
|||
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
||||
{
|
||||
pointer_field = 0;
|
||||
const0_value = 0;
|
||||
const1_value = 3;
|
||||
CRC_32 = 0;
|
||||
}
|
||||
|
||||
|
@ -1462,11 +1784,12 @@ int SrsTsPayloadPSI::decode(SrsStream* stream, SrsTsMessage** /*ppmsg*/)
|
|||
table_id = (SrsTsPsiId)stream->read_1bytes();
|
||||
|
||||
// 2B
|
||||
section_length = stream->read_2bytes();
|
||||
int16_t slv = stream->read_2bytes();
|
||||
|
||||
section_syntax_indicator = (section_length >> 15) & 0x01;
|
||||
const0_value = (section_length >> 14) & 0x01;
|
||||
section_length &= 0x0FFF;
|
||||
section_syntax_indicator = (slv >> 15) & 0x01;
|
||||
const0_value = (slv >> 14) & 0x01;
|
||||
const1_value = (slv >> 12) & 0x03;
|
||||
section_length = slv & 0x0FFF;
|
||||
|
||||
// no section, ignore.
|
||||
if (section_length == 0) {
|
||||
|
@ -1521,18 +1844,139 @@ int SrsTsPayloadPSI::decode(SrsStream* stream, SrsTsMessage** /*ppmsg*/)
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram()
|
||||
int SrsTsPayloadPSI::size()
|
||||
{
|
||||
number = 0;
|
||||
pid = 0;
|
||||
int sz = 0;
|
||||
|
||||
// section size is the sl plus the crc32
|
||||
section_length = psi_size() + 4;
|
||||
|
||||
sz += packet->payload_unit_start_indicator? 1:0;
|
||||
sz += 3;
|
||||
sz += section_length;
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPSI::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (packet->payload_unit_start_indicator) {
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||
srs_error("ts: mux PSI failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
stream->write_1bytes(pointer_field);
|
||||
}
|
||||
|
||||
// to calc the crc32
|
||||
char* ppat = stream->data() + stream->pos();
|
||||
int pat_pos = stream->pos();
|
||||
|
||||
// atleast 3B for all psi.
|
||||
if (!stream->require(3)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||
srs_error("ts: mux PSI failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
// 1B
|
||||
stream->write_1bytes(table_id);
|
||||
|
||||
// 2B
|
||||
int16_t slv = section_length & 0x0FFF;
|
||||
slv |= (section_syntax_indicator << 15) & 0x8000;
|
||||
slv |= (const0_value << 14) & 0x4000;
|
||||
slv |= (const1_value << 12) & 0x3000;
|
||||
stream->write_2bytes(slv);
|
||||
|
||||
// no section, ignore.
|
||||
if (section_length == 0) {
|
||||
srs_warn("ts: mux PAT ignore empty section");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!stream->require(section_length)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||
srs_error("ts: mux PAT section failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// call the virtual method of actual PSI.
|
||||
if ((ret = psi_encode(stream)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 4B
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PSI;
|
||||
srs_error("ts: mux PSI crc32 failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
CRC_32 = srs_crc32(ppat, stream->pos() - pat_pos);
|
||||
stream->write_4bytes(CRC_32);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram(int16_t n, int16_t p)
|
||||
{
|
||||
number = n;
|
||||
pid = p;
|
||||
const1_value = 0x07;
|
||||
}
|
||||
|
||||
SrsTsPayloadPATProgram::~SrsTsPayloadPATProgram()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsTsPayloadPATProgram::decode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// atleast 4B for PAT program specified
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PAT;
|
||||
srs_error("ts: demux PAT failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tmpv = stream->read_4bytes();
|
||||
number = (int16_t)((tmpv >> 16) & 0xFFFF);
|
||||
const1_value = (int16_t)((tmpv >> 13) & 0x07);
|
||||
pid = (int16_t)(tmpv & 0x1FFF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPATProgram::size()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPATProgram::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// atleast 4B for PAT program specified
|
||||
if (!stream->require(4)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PAT;
|
||||
srs_error("ts: mux PAT failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tmpv = pid & 0x1FFF;
|
||||
tmpv |= (number << 16) & 0xFFFF0000;
|
||||
tmpv |= (const1_value << 13) & 0xE000;
|
||||
stream->write_4bytes(tmpv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
|
||||
{
|
||||
const1_value = 3;
|
||||
}
|
||||
|
||||
SrsTsPayloadPAT::~SrsTsPayloadPAT()
|
||||
|
@ -1562,10 +2006,11 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
|
|||
transport_stream_id = stream->read_2bytes();
|
||||
|
||||
// 1B
|
||||
current_next_indicator = stream->read_1bytes();
|
||||
int8_t cniv = stream->read_1bytes();
|
||||
|
||||
version_number = (current_next_indicator >> 1) & 0x1F;
|
||||
current_next_indicator &= 0x01;
|
||||
const1_value = (cniv >> 6) & 0x03;
|
||||
version_number = (cniv >> 1) & 0x1F;
|
||||
current_next_indicator = cniv & 0x01;
|
||||
|
||||
// TODO: FIXME: check the indicator.
|
||||
|
||||
|
@ -1579,9 +2024,9 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
|
|||
for (int i = 0; i < program_bytes; i += 4) {
|
||||
SrsTsPayloadPATProgram* program = new SrsTsPayloadPATProgram();
|
||||
|
||||
int tmpv = stream->read_4bytes();
|
||||
program->number = (int16_t)((tmpv >> 16) & 0xFFFF);
|
||||
program->pid = (int16_t)(tmpv & 0x1FFF);
|
||||
if ((ret = program->decode(stream)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// update the apply pid table.
|
||||
packet->context->set(program->pid, SrsTsPidApplyPMT);
|
||||
|
@ -1595,8 +2040,59 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPMTESInfo::SrsTsPayloadPMTESInfo()
|
||||
int SrsTsPayloadPAT::psi_size()
|
||||
{
|
||||
int sz = 5;
|
||||
for (int i = 0; i < (int)programs.size(); i ++) {
|
||||
SrsTsPayloadPATProgram* program = programs.at(i);
|
||||
sz += program->size();
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPAT::psi_encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// atleast 5B for PAT specified
|
||||
if (!stream->require(5)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PAT;
|
||||
srs_error("ts: mux PAT failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 2B
|
||||
stream->write_2bytes(transport_stream_id);
|
||||
|
||||
// 1B
|
||||
int8_t cniv = current_next_indicator & 0x01;
|
||||
cniv |= (version_number << 1) & 0x3E;
|
||||
cniv |= (const1_value << 6) & 0xC0;
|
||||
stream->write_1bytes(cniv);
|
||||
|
||||
// 1B
|
||||
stream->write_1bytes(section_number);
|
||||
// 1B
|
||||
stream->write_1bytes(last_section_number);
|
||||
|
||||
// multiple 4B program data.
|
||||
for (int i = 0; i < (int)programs.size(); i ++) {
|
||||
SrsTsPayloadPATProgram* program = programs.at(i);
|
||||
if ((ret = program->encode(stream)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPMTESInfo::SrsTsPayloadPMTESInfo(SrsTsStream st, int16_t epid)
|
||||
{
|
||||
stream_type = st;
|
||||
elementary_PID = epid;
|
||||
|
||||
const1_value0 = 7;
|
||||
const1_value1 = 0x0f;
|
||||
ES_info_length = 0;
|
||||
ES_info = NULL;
|
||||
}
|
||||
|
@ -1606,8 +2102,84 @@ SrsTsPayloadPMTESInfo::~SrsTsPayloadPMTESInfo()
|
|||
srs_freep(ES_info);
|
||||
}
|
||||
|
||||
int SrsTsPayloadPMTESInfo::decode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// 5B
|
||||
if (!stream->require(5)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
srs_error("ts: demux PMT es info failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream_type = (SrsTsStream)stream->read_1bytes();
|
||||
|
||||
int16_t epv = stream->read_2bytes();
|
||||
const1_value0 = (epv >> 13) & 0x07;
|
||||
elementary_PID = epv & 0x1FFF;
|
||||
|
||||
int16_t eilv = stream->read_2bytes();
|
||||
const1_value1 = (epv >> 12) & 0x0f;
|
||||
ES_info_length = eilv & 0x0FFF;
|
||||
|
||||
if (ES_info_length > 0) {
|
||||
if (!stream->require(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(ES_info);
|
||||
ES_info = new char[ES_info_length];
|
||||
stream->read_bytes(ES_info, ES_info_length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPMTESInfo::size()
|
||||
{
|
||||
return 5 + ES_info_length;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPMTESInfo::encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// 5B
|
||||
if (!stream->require(5)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
srs_error("ts: mux PMT es info failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream->write_1bytes(stream_type);
|
||||
|
||||
int16_t epv = elementary_PID & 0x1FFF;
|
||||
epv |= (const1_value0 << 13) & 0xE000;
|
||||
stream->write_2bytes(epv);
|
||||
|
||||
int16_t eilv = ES_info_length & 0x0FFF;
|
||||
eilv |= (const1_value1 << 12) & 0xF000;
|
||||
stream->write_2bytes(eilv);
|
||||
|
||||
if (ES_info_length > 0) {
|
||||
if (!stream->require(ES_info_length)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
srs_error("ts: mux PMT es info data failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
stream->write_bytes(ES_info, ES_info_length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTsPayloadPMT::SrsTsPayloadPMT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
|
||||
{
|
||||
const1_value0 = 3;
|
||||
const1_value1 = 7;
|
||||
const1_value2 = 0x0f;
|
||||
program_info_length = 0;
|
||||
program_info_desc = NULL;
|
||||
}
|
||||
|
@ -1639,10 +2211,11 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
|
|||
program_number = stream->read_2bytes();
|
||||
|
||||
// 1B
|
||||
current_next_indicator = stream->read_1bytes();
|
||||
int8_t cniv = stream->read_1bytes();
|
||||
|
||||
version_number = (current_next_indicator >> 1) & 0x1F;
|
||||
current_next_indicator &= 0x01;
|
||||
const1_value0 = (cniv >> 6) & 0x03;
|
||||
version_number = (cniv >> 1) & 0x1F;
|
||||
current_next_indicator = cniv & 0x01;
|
||||
|
||||
// 1B
|
||||
section_number = stream->read_1bytes();
|
||||
|
@ -1651,15 +2224,15 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
|
|||
last_section_number = stream->read_1bytes();
|
||||
|
||||
// 2B
|
||||
PCR_PID = stream->read_2bytes();
|
||||
|
||||
PCR_PID &= 0x1FFF;
|
||||
int16_t ppv = stream->read_2bytes();
|
||||
const1_value1 = (ppv >> 13) & 0x07;
|
||||
PCR_PID = ppv & 0x1FFF;
|
||||
|
||||
// 2B
|
||||
program_info_length = stream->read_2bytes();
|
||||
int16_t pilv = stream->read_2bytes();
|
||||
const1_value2 = (pilv >> 12) & 0x0F;
|
||||
program_info_length = pilv & 0xFFF;
|
||||
|
||||
program_info_length &= 0xFFF;
|
||||
|
||||
if (program_info_length > 0) {
|
||||
if (!stream->require(program_info_length)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
|
@ -1678,31 +2251,10 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
|
|||
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);
|
||||
if ((ret = info->decode(stream)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->stream_type = (SrsTsStream)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
|
||||
switch (info->stream_type) {
|
||||
case SrsTsStreamVideoH264:
|
||||
|
@ -1727,14 +2279,82 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPMT::psi_size()
|
||||
{
|
||||
int sz = 9;
|
||||
sz += program_info_length;
|
||||
for (int i = 0; i < (int)infos.size(); i ++) {
|
||||
SrsTsPayloadPMTESInfo* info = infos.at(i);
|
||||
sz += info->size();
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
int SrsTsPayloadPMT::psi_encode(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// atleast 9B for PMT specified
|
||||
if (!stream->require(9)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
srs_error("ts: mux PMT failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 2B
|
||||
stream->write_2bytes(program_number);
|
||||
|
||||
// 1B
|
||||
int8_t cniv = current_next_indicator & 0x01;
|
||||
cniv |= (const1_value0 << 6) & 0xC0;
|
||||
cniv |= (version_number << 1) & 0xFE;
|
||||
stream->write_1bytes(cniv);
|
||||
|
||||
// 1B
|
||||
stream->write_1bytes(section_number);
|
||||
|
||||
// 1B
|
||||
stream->write_1bytes(last_section_number);
|
||||
|
||||
// 2B
|
||||
int16_t ppv = PCR_PID & 0x1FFF;
|
||||
ppv |= (const1_value1 << 13) & 0xE000;
|
||||
stream->write_2bytes(ppv);
|
||||
|
||||
// 2B
|
||||
int16_t pilv = program_info_length & 0xFFF;
|
||||
pilv |= (const1_value2 << 12) & 0xF000;
|
||||
stream->write_2bytes(pilv);
|
||||
|
||||
if (program_info_length > 0) {
|
||||
if (!stream->require(program_info_length)) {
|
||||
ret = ERROR_STREAM_CASTER_TS_PMT;
|
||||
srs_error("ts: mux PMT program info failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream->write_bytes(program_info_desc, program_info_length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)infos.size(); i ++) {
|
||||
SrsTsPayloadPMTESInfo* info = infos.at(i);
|
||||
if ((ret = info->encode(stream)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
|
||||
{
|
||||
writer = w;
|
||||
context = NULL;
|
||||
|
||||
// reserved is not written.
|
||||
previous = SrsCodecAudioReserved1;
|
||||
// current default to aac.
|
||||
current = SrsCodecAudioAAC;
|
||||
// default to aac.
|
||||
acodec = SrsCodecAudioAAC;
|
||||
// default to avc(h.264)
|
||||
vcodec = SrsCodecVideoAVC;
|
||||
}
|
||||
|
||||
SrsTSMuxer::~SrsTSMuxer()
|
||||
|
@ -1749,6 +2369,10 @@ int SrsTSMuxer::open(string _path)
|
|||
path = _path;
|
||||
|
||||
close();
|
||||
|
||||
// use context to write ts file.
|
||||
srs_freep(context);
|
||||
context = new SrsTsContext();
|
||||
|
||||
if ((ret = writer->open(path)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
|
@ -1759,31 +2383,19 @@ int SrsTSMuxer::open(string _path)
|
|||
|
||||
int SrsTSMuxer::update_acodec(SrsCodecAudio ac)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
if (current == ac) {
|
||||
return ret;
|
||||
}
|
||||
current = ac;
|
||||
|
||||
return ret;
|
||||
acodec = ac;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// when acodec changed, write header.
|
||||
if (current != previous) {
|
||||
previous = current;
|
||||
if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) {
|
||||
if ((ret = context->encode(writer, af, ab, vcodec, acodec)) != ERROR_SUCCESS) {
|
||||
srs_error("hls encode audio failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("hls encode audio ok");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1792,23 +2404,18 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb)
|
|||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// when acodec changed, write header.
|
||||
if (current != previous) {
|
||||
previous = current;
|
||||
if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) {
|
||||
if ((ret = context->encode(writer, vf, vb, vcodec, acodec)) != ERROR_SUCCESS) {
|
||||
srs_error("hls encode video failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("hls encode video ok");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsTSMuxer::close()
|
||||
{
|
||||
srs_freep(context);
|
||||
writer->close();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
int64_t dts;
|
||||
int pid;
|
||||
int sid;
|
||||
int cc;
|
||||
int cc; // continuity_counter
|
||||
bool write_pcr;
|
||||
|
||||
SrsMpegtsFrame();
|
||||
|
@ -327,18 +327,18 @@ public:
|
|||
*/
|
||||
class SrsTsContext
|
||||
{
|
||||
// codec
|
||||
private:
|
||||
std::map<int, SrsTsChannel*> pids;
|
||||
// encoder
|
||||
private:
|
||||
// when any codec changed, write the PAT/PMT.
|
||||
SrsCodecVideo vcodec;
|
||||
SrsCodecAudio acodec;
|
||||
public:
|
||||
SrsTsContext();
|
||||
virtual ~SrsTsContext();
|
||||
public:
|
||||
/**
|
||||
* the stream contains only one ts packet.
|
||||
* @param handler the ts message handler to process the msg.
|
||||
* @remark we will consume all bytes in stream.
|
||||
*/
|
||||
virtual int decode(SrsStream* stream, ISrsTsHandler* handler);
|
||||
// codec
|
||||
public:
|
||||
/**
|
||||
* get the pid apply, the parsed pid.
|
||||
|
@ -349,6 +349,27 @@ public:
|
|||
* set the pid apply, the parsed pid.
|
||||
*/
|
||||
virtual void set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream = SrsTsStreamReserved);
|
||||
// decode methods
|
||||
public:
|
||||
/**
|
||||
* the stream contains only one ts packet.
|
||||
* @param handler the ts message handler to process the msg.
|
||||
* @remark we will consume all bytes in stream.
|
||||
*/
|
||||
virtual int decode(SrsStream* stream, ISrsTsHandler* handler);
|
||||
// encode methods
|
||||
public:
|
||||
/**
|
||||
* write the PES packet, the video/audio stream.
|
||||
* @param frame the video/audio frame info.
|
||||
* @param payload the video/audio payload bytes.
|
||||
* @param vc the video codec, write the PAT/PMT table when changed.
|
||||
* @param ac the audio codec, write the PAT/PMT table when changed.
|
||||
*/
|
||||
virtual int encode(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* payload, SrsCodecVideo vc, SrsCodecAudio ac);
|
||||
private:
|
||||
virtual int encode_pat_pmt(SrsFileWriter* writer, SrsCodecVideo vcodec, SrsCodecAudio acodec);
|
||||
virtual int encode_pes(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* payload);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -454,6 +475,12 @@ public:
|
|||
virtual ~SrsTsPacket();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
public:
|
||||
static SrsTsPacket* create_pat(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid);
|
||||
static SrsTsPacket* create_pmt(SrsTsContext* context, int16_t pmt_number, int16_t pmt_pid, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -755,6 +782,9 @@ public:
|
|||
virtual ~SrsTsAdaptationField();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -800,6 +830,9 @@ public:
|
|||
virtual ~SrsTsPayload();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg) = 0;
|
||||
public:
|
||||
virtual int size() = 0;
|
||||
virtual int encode(SrsStream* stream) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1141,6 +1174,9 @@ public:
|
|||
virtual ~SrsTsPayloadPES();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
private:
|
||||
virtual int decode_33bits_dts_pts(SrsStream* stream, int64_t* pv);
|
||||
};
|
||||
|
@ -1179,13 +1215,18 @@ public:
|
|||
* const value, must be '0'
|
||||
*/
|
||||
int8_t const0_value; //1bit
|
||||
// 2bits reserved.
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value; //2bits
|
||||
/**
|
||||
* 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
|
||||
public:
|
||||
// the specified psi info, for example, PAT fields.
|
||||
public:
|
||||
// 4B
|
||||
/**
|
||||
|
@ -1199,7 +1240,12 @@ public:
|
|||
virtual ~SrsTsPayloadPSI();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
protected:
|
||||
virtual int psi_size() = 0;
|
||||
virtual int psi_encode(SrsStream* stream) = 0;
|
||||
virtual int psi_decode(SrsStream* stream) = 0;
|
||||
};
|
||||
|
||||
|
@ -1217,7 +1263,10 @@ public:
|
|||
* Association Table.
|
||||
*/
|
||||
int16_t number; // 16bits
|
||||
// reserved 3bits
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value; //3bits
|
||||
/**
|
||||
* program_map_PID/network_PID 13bits
|
||||
* network_PID - The network_PID is a 13-bit field, which is used only in conjunction with the value of the
|
||||
|
@ -1225,10 +1274,15 @@ public:
|
|||
* 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;
|
||||
int16_t pid; //13bits
|
||||
public:
|
||||
SrsTsPayloadPATProgram();
|
||||
SrsTsPayloadPATProgram(int16_t n = 0, int16_t p = 0);
|
||||
virtual ~SrsTsPayloadPATProgram();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1249,7 +1303,10 @@ public:
|
|||
u_int16_t transport_stream_id; //16bits
|
||||
|
||||
// 1B
|
||||
// 2bits reerverd.
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value; //2bits
|
||||
/**
|
||||
* 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
|
||||
|
@ -1285,8 +1342,11 @@ public:
|
|||
public:
|
||||
SrsTsPayloadPAT(SrsTsPacket* p);
|
||||
virtual ~SrsTsPayloadPAT();
|
||||
public:
|
||||
protected:
|
||||
virtual int psi_decode(SrsStream* stream);
|
||||
protected:
|
||||
virtual int psi_size();
|
||||
virtual int psi_encode(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1303,15 +1363,21 @@ public:
|
|||
SrsTsStream stream_type; //8bits
|
||||
|
||||
// 2B
|
||||
// 3bits reserved
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value0; //3bits
|
||||
/**
|
||||
* 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
|
||||
// (2+x)B
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value1; //4bits
|
||||
/**
|
||||
* 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.
|
||||
|
@ -1319,8 +1385,13 @@ public:
|
|||
int16_t ES_info_length; //12bits
|
||||
char* ES_info; //[ES_info_length] bytes.
|
||||
public:
|
||||
SrsTsPayloadPMTESInfo();
|
||||
SrsTsPayloadPMTESInfo(SrsTsStream st = SrsTsStreamReserved, int16_t epid = 0);
|
||||
virtual ~SrsTsPayloadPMTESInfo();
|
||||
public:
|
||||
virtual int decode(SrsStream* stream);
|
||||
public:
|
||||
virtual int size();
|
||||
virtual int encode(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1349,7 +1420,10 @@ public:
|
|||
u_int16_t program_number; //16bits
|
||||
|
||||
// 1B
|
||||
// 2bits reerverd.
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value0; //2bits
|
||||
/**
|
||||
* 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
|
||||
|
@ -1378,17 +1452,20 @@ public:
|
|||
u_int8_t last_section_number; //8bits
|
||||
|
||||
// 2B
|
||||
// 2bits reserved.
|
||||
/**
|
||||
* reverved value, must be '1'
|
||||
*/
|
||||
int8_t const1_value1; //3bits
|
||||
/**
|
||||
* 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
|
||||
int16_t PCR_PID; //13bits
|
||||
|
||||
// 2B
|
||||
// 4bits reserved.
|
||||
int8_t const1_value2; //4bits
|
||||
/**
|
||||
* 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.
|
||||
|
@ -1401,8 +1478,11 @@ public:
|
|||
public:
|
||||
SrsTsPayloadPMT(SrsTsPacket* p);
|
||||
virtual ~SrsTsPayloadPMT();
|
||||
public:
|
||||
protected:
|
||||
virtual int psi_decode(SrsStream* stream);
|
||||
protected:
|
||||
virtual int psi_size();
|
||||
virtual int psi_encode(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1412,9 +1492,10 @@ public:
|
|||
class SrsTSMuxer
|
||||
{
|
||||
private:
|
||||
SrsCodecAudio previous;
|
||||
SrsCodecAudio current;
|
||||
SrsCodecVideo vcodec;
|
||||
SrsCodecAudio acodec;
|
||||
private:
|
||||
SrsTsContext* context;
|
||||
SrsFileWriter* writer;
|
||||
std::string path;
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue