|
|
|
@ -349,11 +349,6 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SrsTsContext::set_sync_byte(int8_t sb)
|
|
|
|
|
{
|
|
|
|
|
sync_byte = sb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsContext::encode_pat_pmt(ISrsStreamWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
@ -812,24 +807,24 @@ SrsTsPacket* SrsTsPacket::create_pes_first(SrsTsContext* context,
|
|
|
|
|
// LCOV_EXCL_STOP
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pes->packet_start_code_prefix = 0x01;
|
|
|
|
|
pes->stream_id = (uint8_t)sid;
|
|
|
|
|
pes->PES_packet_length = (size > 0xFFFF)? 0:size;
|
|
|
|
|
pes->PES_scrambling_control = 0;
|
|
|
|
|
pes->PES_priority = 0;
|
|
|
|
|
pes->data_alignment_indicator = 0;
|
|
|
|
|
pes->copyright = 0;
|
|
|
|
|
pes->original_or_copy = 0;
|
|
|
|
|
pes->PTS_DTS_flags = (dts == pts)? 0x02:0x03;
|
|
|
|
|
pes->ESCR_flag = 0;
|
|
|
|
|
pes->ES_rate_flag = 0;
|
|
|
|
|
pes->DSM_trick_mode_flag = 0;
|
|
|
|
|
pes->additional_copy_info_flag = 0;
|
|
|
|
|
pes->PES_CRC_flag = 0;
|
|
|
|
|
pes->PES_extension_flag = 0;
|
|
|
|
|
pes->PES_header_data_length = 0; // calc in size.
|
|
|
|
|
pes->pts = pts;
|
|
|
|
|
pes->dts = dts;
|
|
|
|
|
pes->pes.packet_start_code_prefix = 0x01;
|
|
|
|
|
pes->pes.stream_id = (uint8_t)sid;
|
|
|
|
|
pes->pes.PES_packet_length = (size > 0xFFFF)? 0:size;
|
|
|
|
|
pes->pes.PES_scrambling_control = 0;
|
|
|
|
|
pes->pes.PES_priority = 0;
|
|
|
|
|
pes->pes.data_alignment_indicator = 0;
|
|
|
|
|
pes->pes.copyright = 0;
|
|
|
|
|
pes->pes.original_or_copy = 0;
|
|
|
|
|
pes->pes.PTS_DTS_flags = (dts == pts)? 0x02:0x03;
|
|
|
|
|
pes->pes.ESCR_flag = 0;
|
|
|
|
|
pes->pes.ES_rate_flag = 0;
|
|
|
|
|
pes->pes.DSM_trick_mode_flag = 0;
|
|
|
|
|
pes->pes.additional_copy_info_flag = 0;
|
|
|
|
|
pes->pes.PES_CRC_flag = 0;
|
|
|
|
|
pes->pes.PES_extension_flag = 0;
|
|
|
|
|
pes->pes.PES_header_data_length = 0; // calc in size.
|
|
|
|
|
pes->pes.pts = pts;
|
|
|
|
|
pes->pes.dts = dts;
|
|
|
|
|
return pkt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1249,7 +1244,7 @@ SrsTsPayload::~SrsTsPayload()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SrsTsPayloadPES::SrsTsPayloadPES(SrsTsPacket* p) : SrsTsPayload(p)
|
|
|
|
|
SrsMpegPES::SrsMpegPES()
|
|
|
|
|
{
|
|
|
|
|
nb_stuffings = 0;
|
|
|
|
|
nb_bytes = 0;
|
|
|
|
@ -1291,97 +1286,19 @@ SrsTsPayloadPES::SrsTsPayloadPES(SrsTsPacket* p) : SrsTsPayload(p)
|
|
|
|
|
original_stuff_length = 0;
|
|
|
|
|
P_STD_buffer_scale = 0;
|
|
|
|
|
P_STD_buffer_size = 0;
|
|
|
|
|
|
|
|
|
|
has_payload_ = false;
|
|
|
|
|
nb_payload_ = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SrsTsPayloadPES::~SrsTsPayloadPES()
|
|
|
|
|
SrsMpegPES::~SrsMpegPES()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
srs_error_t SrsMpegPES::decode(SrsBuffer* stream)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
|
|
// find the channel from chunk.
|
|
|
|
|
SrsTsChannel* channel = packet->context->get(packet->pid);
|
|
|
|
|
if (!channel) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES no channel for pid=%#x", packet->pid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// init msg.
|
|
|
|
|
SrsTsMessage* msg = channel->msg;
|
|
|
|
|
if (!msg) {
|
|
|
|
|
msg = new SrsTsMessage(channel, packet);
|
|
|
|
|
channel->msg = msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we must cache the fresh state of msg,
|
|
|
|
|
// for the PES_packet_length is 0, the first payload_unit_start_indicator always 1,
|
|
|
|
|
// so should check for the fresh and not completed it.
|
|
|
|
|
bool is_fresh_msg = msg->fresh();
|
|
|
|
|
|
|
|
|
|
// check when fresh, the payload_unit_start_indicator
|
|
|
|
|
// should be 1 for the fresh msg.
|
|
|
|
|
if (is_fresh_msg && !packet->payload_unit_start_indicator) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: PES fresh packet length=%d, us=%d, cc=%d",
|
|
|
|
|
msg->PES_packet_length, packet->payload_unit_start_indicator, packet->continuity_counter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check when not fresh and PES_packet_length>0,
|
|
|
|
|
// the payload_unit_start_indicator should never be 1 when not completed.
|
|
|
|
|
if (!is_fresh_msg && msg->PES_packet_length > 0 && !msg->completed(packet->payload_unit_start_indicator) && packet->payload_unit_start_indicator) {
|
|
|
|
|
srs_warn("ts: ignore PES packet length=%d, payload=%d, us=%d, cc=%d",
|
|
|
|
|
msg->PES_packet_length, msg->payload->length(), packet->payload_unit_start_indicator, packet->continuity_counter);
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
srs_freep(msg);
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check the continuity counter
|
|
|
|
|
if (!is_fresh_msg) {
|
|
|
|
|
// late-incoming or duplicated continuity, drop message.
|
|
|
|
|
// @remark check overflow, the counter plus 1 should greater when invalid.
|
|
|
|
|
if (msg->continuity_counter >= packet->continuity_counter && ((msg->continuity_counter + 1) & 0x0f) > packet->continuity_counter) {
|
|
|
|
|
srs_warn("ts: drop PES %dB for duplicated cc=%#x", msg->continuity_counter);
|
|
|
|
|
stream->skip(stream->size() - stream->pos());
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when got partially message, the continous count must be continuous, or drop it.
|
|
|
|
|
if (((msg->continuity_counter + 1) & 0x0f) != packet->continuity_counter) {
|
|
|
|
|
srs_warn("ts: ignore continuity must be continous, msg=%#x, packet=%#x", msg->continuity_counter, packet->continuity_counter);
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
srs_freep(msg);
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
msg->continuity_counter = packet->continuity_counter;
|
|
|
|
|
|
|
|
|
|
// for the PES_packet_length(0), reap when completed.
|
|
|
|
|
if (!is_fresh_msg && msg->completed(packet->payload_unit_start_indicator)) {
|
|
|
|
|
// reap previous PES packet.
|
|
|
|
|
*ppmsg = msg;
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// contious packet, append bytes for unit start is 0
|
|
|
|
|
if (!packet->payload_unit_start_indicator) {
|
|
|
|
|
if ((err = msg->dump(stream, &nb_bytes)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "ts: pes dump");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when unit start, parse the fresh msg.
|
|
|
|
|
if (packet->payload_unit_start_indicator) {
|
|
|
|
|
// 6B fixed header.
|
|
|
|
|
if (!stream->require(6)) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE");
|
|
|
|
@ -1403,8 +1320,6 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
// @remark the sid indicates the elementary stream format.
|
|
|
|
|
// the SrsTsPESStreamIdAudio and SrsTsPESStreamIdVideo is start by 0b110 or 0b1110
|
|
|
|
|
SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id;
|
|
|
|
|
msg->sid = sid;
|
|
|
|
|
|
|
|
|
|
if (sid != SrsTsPESStreamIdProgramStreamMap
|
|
|
|
|
&& sid != SrsTsPESStreamIdPaddingStream
|
|
|
|
|
&& sid != SrsTsPESStreamIdPrivateStream2
|
|
|
|
@ -1462,10 +1377,6 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
return srs_error_wrap(err, "dts/pts");
|
|
|
|
|
}
|
|
|
|
|
dts = pts;
|
|
|
|
|
|
|
|
|
|
// update the dts and pts of message.
|
|
|
|
|
msg->dts = dts;
|
|
|
|
|
msg->pts = pts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 10B
|
|
|
|
@ -1481,10 +1392,6 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
if (dts - pts > 90000 || pts - dts > 90000) {
|
|
|
|
|
srs_warn("ts: sync dts=%" PRId64 ", pts=%" PRId64, dts, pts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update the dts and pts of message.
|
|
|
|
|
msg->dts = dts;
|
|
|
|
|
msg->pts = pts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore coverage bellow, for we don't use them in HLS.
|
|
|
|
@ -1627,21 +1534,24 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
// indicated in the PES_packet_length minus the number of bytes
|
|
|
|
|
// between the last byte of the PES_packet_length field and the
|
|
|
|
|
// first PES_packet_data_byte.
|
|
|
|
|
/**
|
|
|
|
|
* when actual packet length > 0xffff(65535),
|
|
|
|
|
* which exceed the max uint16_t packet length,
|
|
|
|
|
* use 0 packet length, the next unit start indicates the end of packet.
|
|
|
|
|
*/
|
|
|
|
|
//
|
|
|
|
|
// If the actual size > uin16_t, which exceed the PES_packet_length, then PES_packet_length is 0, and we
|
|
|
|
|
// should dump all left bytes in stream to message util next unit start packet.
|
|
|
|
|
// Otherwise, the PES_packet_length should greater than 0, which is a specified length, then we also dump
|
|
|
|
|
// the left bytes in stream, in such case, the nb_payload_ is the actual size of payload.
|
|
|
|
|
if (PES_packet_length > 0) {
|
|
|
|
|
int nb_packet = PES_packet_length - (stream->pos() - pos_packet);
|
|
|
|
|
msg->PES_packet_length = srs_max(0, nb_packet);
|
|
|
|
|
if (nb_packet < 0) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: Invalid PES_packet_length=%d, pos_packet=%d, pos=%d", PES_packet_length, pos_packet, stream->pos());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// xB
|
|
|
|
|
if ((err = msg->dump(stream, &nb_bytes)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "dump pes");
|
|
|
|
|
nb_payload_ = nb_packet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now, it has payload. The size is specified by PES_packet_length, which might be:
|
|
|
|
|
// 0, Dump all bytes in stream util next unit start packet.
|
|
|
|
|
// nb_payload_, Dump specified bytes in stream.
|
|
|
|
|
has_payload_ = true;
|
|
|
|
|
|
|
|
|
|
// Ignore coverage bellow, for we don't use them in HLS.
|
|
|
|
|
// LCOV_EXCL_START
|
|
|
|
|
} else if (sid == SrsTsPESStreamIdProgramStreamMap
|
|
|
|
@ -1656,10 +1566,9 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
// PES_packet_data_byte
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// xB
|
|
|
|
|
if ((err = msg->dump(stream, &nb_bytes)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "dump packet");
|
|
|
|
|
}
|
|
|
|
|
// The pos_packet equals to stream pos, so the PES_packet_length is actually the payload length.
|
|
|
|
|
nb_payload_ = PES_packet_length;
|
|
|
|
|
has_payload_ = true;
|
|
|
|
|
} else if (sid == SrsTsPESStreamIdPaddingStream) {
|
|
|
|
|
// for (i = 0; i < PES_packet_length; i++) {
|
|
|
|
|
// padding_byte
|
|
|
|
@ -1674,26 +1583,11 @@ srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
stream->skip(nb_drop);
|
|
|
|
|
srs_warn("ts: drop the pes packet %dB for stream_id=%#x", nb_drop, stream_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when fresh and the PES_packet_length is 0,
|
|
|
|
|
// the payload_unit_start_indicator always be 1,
|
|
|
|
|
// the message should never EOF for the first packet.
|
|
|
|
|
if (is_fresh_msg && msg->PES_packet_length == 0) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check msg, reap when completed.
|
|
|
|
|
if (msg->completed(packet->payload_unit_start_indicator)) {
|
|
|
|
|
*ppmsg = msg;
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
srs_info("ts: reap msg for completed.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SrsTsPayloadPES::size()
|
|
|
|
|
int SrsMpegPES::size()
|
|
|
|
|
{
|
|
|
|
|
int sz = 0;
|
|
|
|
|
|
|
|
|
@ -1753,7 +1647,7 @@ int SrsTsPayloadPES::size()
|
|
|
|
|
return sz;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream)
|
|
|
|
|
srs_error_t SrsMpegPES::encode(SrsBuffer* stream)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
|
@ -1909,7 +1803,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv)
|
|
|
|
|
srs_error_t SrsMpegPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
|
@ -1960,7 +1854,7 @@ srs_error_t SrsTsPayloadPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* p
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v)
|
|
|
|
|
srs_error_t SrsMpegPES::encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
|
@ -1987,6 +1881,147 @@ srs_error_t SrsTsPayloadPES::encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SrsTsPayloadPES::SrsTsPayloadPES(SrsTsPacket* p) : SrsTsPayload(p)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SrsTsPayloadPES::~SrsTsPayloadPES()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::decode(SrsBuffer* stream, SrsTsMessage** ppmsg)
|
|
|
|
|
{
|
|
|
|
|
srs_error_t err = srs_success;
|
|
|
|
|
|
|
|
|
|
// find the channel from chunk.
|
|
|
|
|
SrsTsChannel* channel = packet->context->get(packet->pid);
|
|
|
|
|
if (!channel) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES no channel for pid=%#x", packet->pid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// init msg.
|
|
|
|
|
SrsTsMessage* msg = channel->msg;
|
|
|
|
|
if (!msg) {
|
|
|
|
|
msg = new SrsTsMessage(channel, packet);
|
|
|
|
|
channel->msg = msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// we must cache the fresh state of msg,
|
|
|
|
|
// for the PES_packet_length is 0, the first payload_unit_start_indicator always 1,
|
|
|
|
|
// so should check for the fresh and not completed it.
|
|
|
|
|
bool is_fresh_msg = msg->fresh();
|
|
|
|
|
|
|
|
|
|
// check when fresh, the payload_unit_start_indicator
|
|
|
|
|
// should be 1 for the fresh msg.
|
|
|
|
|
if (is_fresh_msg && !packet->payload_unit_start_indicator) {
|
|
|
|
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: PES fresh packet length=%d, us=%d, cc=%d",
|
|
|
|
|
msg->PES_packet_length, packet->payload_unit_start_indicator, packet->continuity_counter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check when not fresh and PES_packet_length>0,
|
|
|
|
|
// the payload_unit_start_indicator should never be 1 when not completed.
|
|
|
|
|
if (!is_fresh_msg && msg->PES_packet_length > 0 && !msg->completed(packet->payload_unit_start_indicator) && packet->payload_unit_start_indicator) {
|
|
|
|
|
srs_warn("ts: ignore PES packet length=%d, payload=%d, us=%d, cc=%d",
|
|
|
|
|
msg->PES_packet_length, msg->payload->length(), packet->payload_unit_start_indicator, packet->continuity_counter);
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
srs_freep(msg);
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check the continuity counter
|
|
|
|
|
if (!is_fresh_msg) {
|
|
|
|
|
// late-incoming or duplicated continuity, drop message.
|
|
|
|
|
// @remark check overflow, the counter plus 1 should greater when invalid.
|
|
|
|
|
if (msg->continuity_counter >= packet->continuity_counter && ((msg->continuity_counter + 1) & 0x0f) > packet->continuity_counter) {
|
|
|
|
|
srs_warn("ts: drop PES %dB for duplicated cc=%#x", msg->continuity_counter);
|
|
|
|
|
stream->skip(stream->size() - stream->pos());
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when got partially message, the continous count must be continuous, or drop it.
|
|
|
|
|
if (((msg->continuity_counter + 1) & 0x0f) != packet->continuity_counter) {
|
|
|
|
|
srs_warn("ts: ignore continuity must be continous, msg=%#x, packet=%#x", msg->continuity_counter, packet->continuity_counter);
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
srs_freep(msg);
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
msg->continuity_counter = packet->continuity_counter;
|
|
|
|
|
|
|
|
|
|
// for the PES_packet_length(0), reap when completed.
|
|
|
|
|
if (!is_fresh_msg && msg->completed(packet->payload_unit_start_indicator)) {
|
|
|
|
|
// reap previous PES packet.
|
|
|
|
|
*ppmsg = msg;
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
|
|
|
|
|
// reparse current msg.
|
|
|
|
|
stream->skip(stream->pos() * -1);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// contious packet, append bytes for unit start is 0
|
|
|
|
|
if (!packet->payload_unit_start_indicator) {
|
|
|
|
|
if ((err = msg->dump(stream, &pes.nb_bytes)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "ts: pes dump");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when unit start, parse the fresh msg.
|
|
|
|
|
if (packet->payload_unit_start_indicator) {
|
|
|
|
|
if ((err = pes.decode(stream)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "header");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update message when decode the first PES packet.
|
|
|
|
|
msg->sid = (SrsTsPESStreamId)pes.stream_id;
|
|
|
|
|
if (pes.PTS_DTS_flags == 0x02 || pes.PTS_DTS_flags == 0x03) {
|
|
|
|
|
msg->dts = pes.dts;
|
|
|
|
|
msg->pts = pes.pts;
|
|
|
|
|
}
|
|
|
|
|
if (pes.has_payload_) {
|
|
|
|
|
// The size of message, might be 0 or a positive value.
|
|
|
|
|
msg->PES_packet_length = pes.nb_payload_;
|
|
|
|
|
|
|
|
|
|
// xB
|
|
|
|
|
if ((err = msg->dump(stream, &pes.nb_bytes)) != srs_success) {
|
|
|
|
|
return srs_error_wrap(err, "dump pes");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// when fresh and the PES_packet_length is 0,
|
|
|
|
|
// the payload_unit_start_indicator always be 1,
|
|
|
|
|
// the message should never EOF for the first packet.
|
|
|
|
|
if (is_fresh_msg && msg->PES_packet_length == 0) {
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check msg, reap when completed.
|
|
|
|
|
if (msg->completed(packet->payload_unit_start_indicator)) {
|
|
|
|
|
*ppmsg = msg;
|
|
|
|
|
channel->msg = NULL;
|
|
|
|
|
srs_info("ts: reap msg for completed.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int SrsTsPayloadPES::size()
|
|
|
|
|
{
|
|
|
|
|
return pes.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream)
|
|
|
|
|
{
|
|
|
|
|
return pes.encode(stream);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
|
|
|
|
{
|
|
|
|
|
pointer_field = 0;
|
|
|
|
|