implements the pat/pmt write ts header.

pull/133/head
winlin 10 years ago
parent e88c1e32ee
commit 1ed3e283ab

@ -517,6 +517,8 @@ ISrsTsHandler::~ISrsTsHandler()
SrsTsContext::SrsTsContext() SrsTsContext::SrsTsContext()
{ {
vcodec = SrsCodecVideoReserved;
acodec = SrsCodecAudioReserved1;
} }
SrsTsContext::~SrsTsContext() SrsTsContext::~SrsTsContext()
@ -529,6 +531,30 @@ SrsTsContext::~SrsTsContext()
pids.clear(); 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 SrsTsContext::decode(SrsStream* stream, ISrsTsHandler* handler)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
@ -559,28 +585,122 @@ int SrsTsContext::decode(SrsStream* stream, ISrsTsHandler* handler)
return ret; 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()) { int ret = ERROR_SUCCESS;
return NULL;
// 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()) { SrsTsStream vs = SrsTsStreamReserved;
channel = new SrsTsChannel(); SrsTsStream as = SrsTsStreamReserved;
pids[pid] = channel; switch (vc) {
} else { case SrsCodecVideoAVC: vs = SrsTsStreamVideoH264; break;
channel = pids[pid]; 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;
}
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);
channel->pid = pid; char* buf = new char[SRS_TS_PACKET_SIZE];
channel->apply = apply_pid; SrsAutoFree(char, buf);
channel->stream = stream;
// 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) SrsTsPacket::SrsTsPacket(SrsTsContext* c)
@ -688,6 +808,126 @@ int SrsTsPacket::decode(SrsStream* stream, SrsTsMessage** ppmsg)
return ret; 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) SrsTsAdaptationField::SrsTsAdaptationField(SrsTsPacket* pkt)
{ {
packet = pkt; packet = pkt;
@ -929,6 +1169,27 @@ int SrsTsAdaptationField::decode(SrsStream* stream)
return ret; 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) SrsTsPayload::SrsTsPayload(SrsTsPacket* p)
{ {
packet = p; packet = p;
@ -1356,6 +1617,65 @@ int SrsTsPayloadPES::decode(SrsStream* stream, SrsTsMessage** ppmsg)
return ret; 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 SrsTsPayloadPES::decode_33bits_dts_pts(SrsStream* stream, int64_t* pv)
{ {
int ret = ERROR_SUCCESS; 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) SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
{ {
pointer_field = 0; pointer_field = 0;
const0_value = 0;
const1_value = 3;
CRC_32 = 0; CRC_32 = 0;
} }
@ -1462,11 +1784,12 @@ int SrsTsPayloadPSI::decode(SrsStream* stream, SrsTsMessage** /*ppmsg*/)
table_id = (SrsTsPsiId)stream->read_1bytes(); table_id = (SrsTsPsiId)stream->read_1bytes();
// 2B // 2B
section_length = stream->read_2bytes(); int16_t slv = stream->read_2bytes();
section_syntax_indicator = (section_length >> 15) & 0x01; section_syntax_indicator = (slv >> 15) & 0x01;
const0_value = (section_length >> 14) & 0x01; const0_value = (slv >> 14) & 0x01;
section_length &= 0x0FFF; const1_value = (slv >> 12) & 0x03;
section_length = slv & 0x0FFF;
// no section, ignore. // no section, ignore.
if (section_length == 0) { if (section_length == 0) {
@ -1521,18 +1844,139 @@ int SrsTsPayloadPSI::decode(SrsStream* stream, SrsTsMessage** /*ppmsg*/)
return ret; return ret;
} }
SrsTsPayloadPATProgram::SrsTsPayloadPATProgram() int SrsTsPayloadPSI::size()
{ {
number = 0; int sz = 0;
pid = 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() 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) SrsTsPayloadPAT::SrsTsPayloadPAT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
{ {
const1_value = 3;
} }
SrsTsPayloadPAT::~SrsTsPayloadPAT() SrsTsPayloadPAT::~SrsTsPayloadPAT()
@ -1562,10 +2006,11 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
transport_stream_id = stream->read_2bytes(); transport_stream_id = stream->read_2bytes();
// 1B // 1B
current_next_indicator = stream->read_1bytes(); int8_t cniv = stream->read_1bytes();
version_number = (current_next_indicator >> 1) & 0x1F; const1_value = (cniv >> 6) & 0x03;
current_next_indicator &= 0x01; version_number = (cniv >> 1) & 0x1F;
current_next_indicator = cniv & 0x01;
// TODO: FIXME: check the indicator. // TODO: FIXME: check the indicator.
@ -1579,9 +2024,9 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
for (int i = 0; i < program_bytes; i += 4) { for (int i = 0; i < program_bytes; i += 4) {
SrsTsPayloadPATProgram* program = new SrsTsPayloadPATProgram(); SrsTsPayloadPATProgram* program = new SrsTsPayloadPATProgram();
int tmpv = stream->read_4bytes(); if ((ret = program->decode(stream)) != ERROR_SUCCESS) {
program->number = (int16_t)((tmpv >> 16) & 0xFFFF); return ret;
program->pid = (int16_t)(tmpv & 0x1FFF); }
// update the apply pid table. // update the apply pid table.
packet->context->set(program->pid, SrsTsPidApplyPMT); packet->context->set(program->pid, SrsTsPidApplyPMT);
@ -1595,8 +2040,59 @@ int SrsTsPayloadPAT::psi_decode(SrsStream* stream)
return ret; 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_length = 0;
ES_info = NULL; ES_info = NULL;
} }
@ -1606,8 +2102,84 @@ SrsTsPayloadPMTESInfo::~SrsTsPayloadPMTESInfo()
srs_freep(ES_info); 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) SrsTsPayloadPMT::SrsTsPayloadPMT(SrsTsPacket* p) : SrsTsPayloadPSI(p)
{ {
const1_value0 = 3;
const1_value1 = 7;
const1_value2 = 0x0f;
program_info_length = 0; program_info_length = 0;
program_info_desc = NULL; program_info_desc = NULL;
} }
@ -1639,10 +2211,11 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
program_number = stream->read_2bytes(); program_number = stream->read_2bytes();
// 1B // 1B
current_next_indicator = stream->read_1bytes(); int8_t cniv = stream->read_1bytes();
version_number = (current_next_indicator >> 1) & 0x1F; const1_value0 = (cniv >> 6) & 0x03;
current_next_indicator &= 0x01; version_number = (cniv >> 1) & 0x1F;
current_next_indicator = cniv & 0x01;
// 1B // 1B
section_number = stream->read_1bytes(); section_number = stream->read_1bytes();
@ -1651,14 +2224,14 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
last_section_number = stream->read_1bytes(); last_section_number = stream->read_1bytes();
// 2B // 2B
PCR_PID = stream->read_2bytes(); int16_t ppv = stream->read_2bytes();
const1_value1 = (ppv >> 13) & 0x07;
PCR_PID &= 0x1FFF; PCR_PID = ppv & 0x1FFF;
// 2B // 2B
program_info_length = stream->read_2bytes(); int16_t pilv = stream->read_2bytes();
const1_value2 = (pilv >> 12) & 0x0F;
program_info_length &= 0xFFF; program_info_length = pilv & 0xFFF;
if (program_info_length > 0) { if (program_info_length > 0) {
if (!stream->require(program_info_length)) { if (!stream->require(program_info_length)) {
@ -1678,31 +2251,10 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
SrsTsPayloadPMTESInfo* info = new SrsTsPayloadPMTESInfo(); SrsTsPayloadPMTESInfo* info = new SrsTsPayloadPMTESInfo();
infos.push_back(info); infos.push_back(info);
// 5B if ((ret = info->decode(stream)) != ERROR_SUCCESS) {
if (!stream->require(5)) {
ret = ERROR_STREAM_CASTER_TS_PMT;
srs_error("ts: demux PMT es info failed. ret=%d", ret);
return ret; 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 // update the apply pid table
switch (info->stream_type) { switch (info->stream_type) {
case SrsTsStreamVideoH264: case SrsTsStreamVideoH264:
@ -1727,14 +2279,82 @@ int SrsTsPayloadPMT::psi_decode(SrsStream* stream)
return ret; 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) SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w)
{ {
writer = w; writer = w;
context = NULL;
// reserved is not written. // default to aac.
previous = SrsCodecAudioReserved1; acodec = SrsCodecAudioAAC;
// current default to aac. // default to avc(h.264)
current = SrsCodecAudioAAC; vcodec = SrsCodecVideoAVC;
} }
SrsTSMuxer::~SrsTSMuxer() SrsTSMuxer::~SrsTSMuxer()
@ -1750,6 +2370,10 @@ int SrsTSMuxer::open(string _path)
close(); close();
// use context to write ts file.
srs_freep(context);
context = new SrsTsContext();
if ((ret = writer->open(path)) != ERROR_SUCCESS) { if ((ret = writer->open(path)) != ERROR_SUCCESS) {
return ret; return ret;
} }
@ -1759,31 +2383,19 @@ int SrsTSMuxer::open(string _path)
int SrsTSMuxer::update_acodec(SrsCodecAudio ac) int SrsTSMuxer::update_acodec(SrsCodecAudio ac)
{ {
int ret = ERROR_SUCCESS; acodec = ac;
return ERROR_SUCCESS;
if (current == ac) {
return ret;
}
current = ac;
return ret;
} }
int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab) int SrsTSMuxer::write_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when acodec changed, write header. if ((ret = context->encode(writer, af, ab, vcodec, acodec)) != ERROR_SUCCESS) {
if (current != previous) { srs_error("hls encode audio failed. ret=%d", ret);
previous = current;
if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) {
return ret;
}
}
if ((ret = SrsMpegtsWriter::write_frame(writer, af, ab)) != ERROR_SUCCESS) {
return ret; return ret;
} }
srs_info("hls encode audio ok");
return ret; return ret;
} }
@ -1792,23 +2404,18 @@ int SrsTSMuxer::write_video(SrsMpegtsFrame* vf, SrsSimpleBuffer* vb)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// when acodec changed, write header. if ((ret = context->encode(writer, vf, vb, vcodec, acodec)) != ERROR_SUCCESS) {
if (current != previous) { srs_error("hls encode video failed. ret=%d", ret);
previous = current;
if ((ret = SrsMpegtsWriter::write_header(writer, previous)) != ERROR_SUCCESS) {
return ret;
}
}
if ((ret = SrsMpegtsWriter::write_frame(writer, vf, vb)) != ERROR_SUCCESS) {
return ret; return ret;
} }
srs_info("hls encode video ok");
return ret; return ret;
} }
void SrsTSMuxer::close() void SrsTSMuxer::close()
{ {
srs_freep(context);
writer->close(); writer->close();
} }

@ -59,7 +59,7 @@ public:
int64_t dts; int64_t dts;
int pid; int pid;
int sid; int sid;
int cc; int cc; // continuity_counter
bool write_pcr; bool write_pcr;
SrsMpegtsFrame(); SrsMpegtsFrame();
@ -327,18 +327,18 @@ public:
*/ */
class SrsTsContext class SrsTsContext
{ {
// codec
private: private:
std::map<int, SrsTsChannel*> pids; std::map<int, SrsTsChannel*> pids;
// encoder
private:
// when any codec changed, write the PAT/PMT.
SrsCodecVideo vcodec;
SrsCodecAudio acodec;
public: public:
SrsTsContext(); SrsTsContext();
virtual ~SrsTsContext(); virtual ~SrsTsContext();
public: // codec
/**
* 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);
public: public:
/** /**
* get the pid apply, the parsed pid. * get the pid apply, the parsed pid.
@ -349,6 +349,27 @@ public:
* set the pid apply, the parsed pid. * set the pid apply, the parsed pid.
*/ */
virtual void set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream = SrsTsStreamReserved); 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(); virtual ~SrsTsPacket();
public: public:
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg); 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(); virtual ~SrsTsAdaptationField();
public: public:
virtual int decode(SrsStream* stream); virtual int decode(SrsStream* stream);
public:
virtual int size();
virtual int encode(SrsStream* stream);
}; };
/** /**
@ -800,6 +830,9 @@ public:
virtual ~SrsTsPayload(); virtual ~SrsTsPayload();
public: public:
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg) = 0; 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(); virtual ~SrsTsPayloadPES();
public: public:
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg); virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg);
public:
virtual int size();
virtual int encode(SrsStream* stream);
private: private:
virtual int decode_33bits_dts_pts(SrsStream* stream, int64_t* pv); virtual int decode_33bits_dts_pts(SrsStream* stream, int64_t* pv);
}; };
@ -1179,13 +1215,18 @@ public:
* const value, must be '0' * const value, must be '0'
*/ */
int8_t const0_value; //1bit 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 * 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 * 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). * field shall not exceed 1021 (0x3FD).
*/ */
u_int16_t section_length; //12bits u_int16_t section_length; //12bits
public:
// the specified psi info, for example, PAT fields.
public: public:
// 4B // 4B
/** /**
@ -1199,7 +1240,12 @@ public:
virtual ~SrsTsPayloadPSI(); virtual ~SrsTsPayloadPSI();
public: public:
virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg); virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg);
public:
virtual int size();
virtual int encode(SrsStream* stream);
protected: protected:
virtual int psi_size() = 0;
virtual int psi_encode(SrsStream* stream) = 0;
virtual int psi_decode(SrsStream* stream) = 0; virtual int psi_decode(SrsStream* stream) = 0;
}; };
@ -1217,7 +1263,10 @@ public:
* Association Table. * Association Table.
*/ */
int16_t number; // 16bits int16_t number; // 16bits
// reserved 3bits /**
* reverved value, must be '1'
*/
int8_t const1_value; //3bits
/** /**
* program_map_PID/network_PID 13bits * 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 * 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 * 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. * Table 2-3. The presence of the network_PID is optional.
*/ */
int16_t pid; int16_t pid; //13bits
public: public:
SrsTsPayloadPATProgram(); SrsTsPayloadPATProgram(int16_t n = 0, int16_t p = 0);
virtual ~SrsTsPayloadPATProgram(); 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 u_int16_t transport_stream_id; //16bits
// 1B // 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 * 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 * shall be incremented by 1 modulo 32 whenever the definition of the Program Association Table changes. When the
@ -1285,8 +1342,11 @@ public:
public: public:
SrsTsPayloadPAT(SrsTsPacket* p); SrsTsPayloadPAT(SrsTsPacket* p);
virtual ~SrsTsPayloadPAT(); virtual ~SrsTsPayloadPAT();
public: protected:
virtual int psi_decode(SrsStream* stream); 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 SrsTsStream stream_type; //8bits
// 2B // 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 * This is a 13-bit field specifying the PID of the Transport Stream packets which carry the associated
* program element. * program element.
*/ */
int16_t elementary_PID; //13bits int16_t elementary_PID; //13bits
// 2B // (2+x)B
// 4bits reserved /**
* 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 * 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. * 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 int16_t ES_info_length; //12bits
char* ES_info; //[ES_info_length] bytes. char* ES_info; //[ES_info_length] bytes.
public: public:
SrsTsPayloadPMTESInfo(); SrsTsPayloadPMTESInfo(SrsTsStream st = SrsTsStreamReserved, int16_t epid = 0);
virtual ~SrsTsPayloadPMTESInfo(); 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 u_int16_t program_number; //16bits
// 1B // 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 * 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 * 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 u_int8_t last_section_number; //8bits
// 2B // 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 * 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 * 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 * 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. * for restrictions on the choice of PCR_PID value.
*/ */
int16_t PCR_PID; //16bits int16_t PCR_PID; //13bits
// 2B // 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 * 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. * number of bytes of the descriptors immediately following the program_info_length field.
@ -1401,8 +1478,11 @@ public:
public: public:
SrsTsPayloadPMT(SrsTsPacket* p); SrsTsPayloadPMT(SrsTsPacket* p);
virtual ~SrsTsPayloadPMT(); virtual ~SrsTsPayloadPMT();
public: protected:
virtual int psi_decode(SrsStream* stream); virtual int psi_decode(SrsStream* stream);
protected:
virtual int psi_size();
virtual int psi_encode(SrsStream* stream);
}; };
/** /**
@ -1412,9 +1492,10 @@ public:
class SrsTSMuxer class SrsTSMuxer
{ {
private: private:
SrsCodecAudio previous; SrsCodecVideo vcodec;
SrsCodecAudio current; SrsCodecAudio acodec;
private: private:
SrsTsContext* context;
SrsFileWriter* writer; SrsFileWriter* writer;
std::string path; std::string path;
public: public:

Loading…
Cancel
Save