mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
UTest: Fix utest warnings.
This commit is contained in:
parent
cfbbe3044f
commit
9c81a0e1bd
8 changed files with 603 additions and 560 deletions
|
@ -7246,20 +7246,11 @@ string SrsConfig::get_https_api_listen()
|
||||||
{
|
{
|
||||||
SRS_OVERWRITE_BY_ENV_STRING("srs.http_api.https.listen");
|
SRS_OVERWRITE_BY_ENV_STRING("srs.http_api.https.listen");
|
||||||
|
|
||||||
#ifdef SRS_UTEST
|
// We should not use static default, because we need to reset for different use scenarios.
|
||||||
// We should not use static default, because we need to reset for different testcase.
|
string DEFAULT = "1990";
|
||||||
string DEFAULT = "";
|
|
||||||
#else
|
|
||||||
static string DEFAULT = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Follow the HTTPS server if config HTTP API as the same of HTTP server.
|
// Follow the HTTPS server if config HTTP API as the same of HTTP server.
|
||||||
if (DEFAULT.empty()) {
|
if (get_http_api_listen() == get_http_stream_listen()) {
|
||||||
if (get_http_api_listen() == get_http_stream_listen()) {
|
DEFAULT = get_https_stream_listen();
|
||||||
DEFAULT = get_https_stream_listen();
|
|
||||||
} else {
|
|
||||||
DEFAULT = "1990";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsConfDirective* conf = get_https_api();
|
SrsConfDirective* conf = get_https_api();
|
||||||
|
|
|
@ -172,7 +172,7 @@ private:
|
||||||
public:
|
public:
|
||||||
SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h);
|
SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h);
|
||||||
SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h, SrsContextId cid);
|
SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h, SrsContextId cid);
|
||||||
~SrsFastCoroutine();
|
virtual ~SrsFastCoroutine();
|
||||||
public:
|
public:
|
||||||
void set_stack_size(int v);
|
void set_stack_size(int v);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2047,7 +2047,7 @@ std::string SrsApmSpan::text_propagator()
|
||||||
// For text based propagation, for example, HTTP header "Traceparent: 00-bb8dedf16c53ab4b6ceb1f4ca6d985bb-29247096662468ab-01"
|
// For text based propagation, for example, HTTP header "Traceparent: 00-bb8dedf16c53ab4b6ceb1f4ca6d985bb-29247096662468ab-01"
|
||||||
// About the "%.2x", please see https://www.quora.com/What-does-2x-do-in-C-code for detail.
|
// About the "%.2x", please see https://www.quora.com/What-does-2x-do-in-C-code for detail.
|
||||||
int nn = snprintf(buf, sizeof(buf), "%.2x-%s-%s-%.2x", supportedVersion, ctx_->trace_id_.c_str(), ctx_->span_id_.c_str(), FlagsSampled);
|
int nn = snprintf(buf, sizeof(buf), "%.2x-%s-%s-%.2x", supportedVersion, ctx_->trace_id_.c_str(), ctx_->span_id_.c_str(), FlagsSampled);
|
||||||
if (nn > 0 && nn < sizeof(buf)) {
|
if (nn > 0 && nn < (int)sizeof(buf)) {
|
||||||
return string(buf, nn);
|
return string(buf, nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,11 @@ std::string SrsCplxError::summary() {
|
||||||
if (_summary.empty()) {
|
if (_summary.empty()) {
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
|
|
||||||
|
ss << "code=" << code;
|
||||||
|
|
||||||
|
string code_str = srs_error_code_str(this);
|
||||||
|
if (!code_str.empty()) ss << "(" << code_str << ")";
|
||||||
|
|
||||||
SrsCplxError* next = this;
|
SrsCplxError* next = this;
|
||||||
while (next) {
|
while (next) {
|
||||||
ss << " : " << next->msg;
|
ss << " : " << next->msg;
|
||||||
|
|
|
@ -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 SrsTsContext::encode_pat_pmt(ISrsStreamWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -812,24 +807,24 @@ SrsTsPacket* SrsTsPacket::create_pes_first(SrsTsContext* context,
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
|
|
||||||
pes->packet_start_code_prefix = 0x01;
|
pes->pes.packet_start_code_prefix = 0x01;
|
||||||
pes->stream_id = (uint8_t)sid;
|
pes->pes.stream_id = (uint8_t)sid;
|
||||||
pes->PES_packet_length = (size > 0xFFFF)? 0:size;
|
pes->pes.PES_packet_length = (size > 0xFFFF)? 0:size;
|
||||||
pes->PES_scrambling_control = 0;
|
pes->pes.PES_scrambling_control = 0;
|
||||||
pes->PES_priority = 0;
|
pes->pes.PES_priority = 0;
|
||||||
pes->data_alignment_indicator = 0;
|
pes->pes.data_alignment_indicator = 0;
|
||||||
pes->copyright = 0;
|
pes->pes.copyright = 0;
|
||||||
pes->original_or_copy = 0;
|
pes->pes.original_or_copy = 0;
|
||||||
pes->PTS_DTS_flags = (dts == pts)? 0x02:0x03;
|
pes->pes.PTS_DTS_flags = (dts == pts)? 0x02:0x03;
|
||||||
pes->ESCR_flag = 0;
|
pes->pes.ESCR_flag = 0;
|
||||||
pes->ES_rate_flag = 0;
|
pes->pes.ES_rate_flag = 0;
|
||||||
pes->DSM_trick_mode_flag = 0;
|
pes->pes.DSM_trick_mode_flag = 0;
|
||||||
pes->additional_copy_info_flag = 0;
|
pes->pes.additional_copy_info_flag = 0;
|
||||||
pes->PES_CRC_flag = 0;
|
pes->pes.PES_CRC_flag = 0;
|
||||||
pes->PES_extension_flag = 0;
|
pes->pes.PES_extension_flag = 0;
|
||||||
pes->PES_header_data_length = 0; // calc in size.
|
pes->pes.PES_header_data_length = 0; // calc in size.
|
||||||
pes->pts = pts;
|
pes->pes.pts = pts;
|
||||||
pes->dts = dts;
|
pes->pes.dts = dts;
|
||||||
return pkt;
|
return pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1249,7 +1244,7 @@ SrsTsPayload::~SrsTsPayload()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsTsPayloadPES::SrsTsPayloadPES(SrsTsPacket* p) : SrsTsPayload(p)
|
SrsMpegPES::SrsMpegPES()
|
||||||
{
|
{
|
||||||
nb_stuffings = 0;
|
nb_stuffings = 0;
|
||||||
nb_bytes = 0;
|
nb_bytes = 0;
|
||||||
|
@ -1291,409 +1286,308 @@ SrsTsPayloadPES::SrsTsPayloadPES(SrsTsPacket* p) : SrsTsPayload(p)
|
||||||
original_stuff_length = 0;
|
original_stuff_length = 0;
|
||||||
P_STD_buffer_scale = 0;
|
P_STD_buffer_scale = 0;
|
||||||
P_STD_buffer_size = 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;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
// find the channel from chunk.
|
// 6B fixed header.
|
||||||
SrsTsChannel* channel = packet->context->get(packet->pid);
|
if (!stream->require(6)) {
|
||||||
if (!channel) {
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE");
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES no channel for pid=%#x", packet->pid);
|
|
||||||
}
|
}
|
||||||
|
// 3B
|
||||||
|
packet_start_code_prefix = stream->read_3bytes();
|
||||||
|
// 1B
|
||||||
|
stream_id = stream->read_1bytes();
|
||||||
|
// 2B
|
||||||
|
PES_packet_length = stream->read_2bytes();
|
||||||
|
|
||||||
// init msg.
|
// check the packet start prefix.
|
||||||
SrsTsMessage* msg = channel->msg;
|
packet_start_code_prefix &= 0xFFFFFF;
|
||||||
if (!msg) {
|
if (packet_start_code_prefix != 0x01) {
|
||||||
msg = new SrsTsMessage(channel, packet);
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES start code failed, expect=0x01, actual=%#x", packet_start_code_prefix);
|
||||||
channel->msg = msg;
|
|
||||||
}
|
}
|
||||||
|
int pos_packet = stream->pos();
|
||||||
|
|
||||||
// we must cache the fresh state of msg,
|
// @remark the sid indicates the elementary stream format.
|
||||||
// for the PES_packet_length is 0, the first payload_unit_start_indicator always 1,
|
// the SrsTsPESStreamIdAudio and SrsTsPESStreamIdVideo is start by 0b110 or 0b1110
|
||||||
// so should check for the fresh and not completed it.
|
SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id;
|
||||||
bool is_fresh_msg = msg->fresh();
|
if (sid != SrsTsPESStreamIdProgramStreamMap
|
||||||
|
&& sid != SrsTsPESStreamIdPaddingStream
|
||||||
// check when fresh, the payload_unit_start_indicator
|
&& sid != SrsTsPESStreamIdPrivateStream2
|
||||||
// should be 1 for the fresh msg.
|
&& sid != SrsTsPESStreamIdEcmStream
|
||||||
if (is_fresh_msg && !packet->payload_unit_start_indicator) {
|
&& sid != SrsTsPESStreamIdEmmStream
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: PES fresh packet length=%d, us=%d, cc=%d",
|
&& sid != SrsTsPESStreamIdProgramStreamDirectory
|
||||||
msg->PES_packet_length, packet->payload_unit_start_indicator, packet->continuity_counter);
|
&& sid != SrsTsPESStreamIdDsmccStream
|
||||||
}
|
&& sid != SrsTsPESStreamIdH2221TypeE
|
||||||
|
) {
|
||||||
// check when not fresh and PES_packet_length>0,
|
// 3B flags.
|
||||||
// the payload_unit_start_indicator should never be 1 when not completed.
|
if (!stream->require(3)) {
|
||||||
if (!is_fresh_msg && msg->PES_packet_length > 0 && !msg->completed(packet->payload_unit_start_indicator) && packet->payload_unit_start_indicator) {
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE flags");
|
||||||
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");
|
|
||||||
}
|
|
||||||
// 3B
|
|
||||||
packet_start_code_prefix = stream->read_3bytes();
|
|
||||||
// 1B
|
// 1B
|
||||||
stream_id = stream->read_1bytes();
|
int8_t oocv = stream->read_1bytes();
|
||||||
// 2B
|
// 1B
|
||||||
PES_packet_length = stream->read_2bytes();
|
int8_t pefv = stream->read_1bytes();
|
||||||
|
// 1B
|
||||||
|
PES_header_data_length = stream->read_1bytes();
|
||||||
|
// position of header start.
|
||||||
|
int pos_header = stream->pos();
|
||||||
|
|
||||||
// check the packet start prefix.
|
const2bits = (oocv >> 6) & 0x03;
|
||||||
packet_start_code_prefix &= 0xFFFFFF;
|
PES_scrambling_control = (oocv >> 4) & 0x03;
|
||||||
if (packet_start_code_prefix != 0x01) {
|
PES_priority = (oocv >> 3) & 0x01;
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES start code failed, expect=0x01, actual=%#x", packet_start_code_prefix);
|
data_alignment_indicator = (oocv >> 2) & 0x01;
|
||||||
|
copyright = (oocv >> 1) & 0x01;
|
||||||
|
original_or_copy = oocv & 0x01;
|
||||||
|
|
||||||
|
PTS_DTS_flags = (pefv >> 6) & 0x03;
|
||||||
|
ESCR_flag = (pefv >> 5) & 0x01;
|
||||||
|
ES_rate_flag = (pefv >> 4) & 0x01;
|
||||||
|
DSM_trick_mode_flag = (pefv >> 3) & 0x01;
|
||||||
|
additional_copy_info_flag = (pefv >> 2) & 0x01;
|
||||||
|
PES_CRC_flag = (pefv >> 1) & 0x01;
|
||||||
|
PES_extension_flag = pefv & 0x01;
|
||||||
|
|
||||||
|
// check required together.
|
||||||
|
int nb_required = 0;
|
||||||
|
nb_required += (PTS_DTS_flags == 0x2)? 5:0;
|
||||||
|
nb_required += (PTS_DTS_flags == 0x3)? 10:0;
|
||||||
|
nb_required += ESCR_flag? 6:0;
|
||||||
|
nb_required += ES_rate_flag? 3:0;
|
||||||
|
nb_required += DSM_trick_mode_flag? 1:0;
|
||||||
|
nb_required += additional_copy_info_flag? 1:0;
|
||||||
|
nb_required += PES_CRC_flag? 2:0;
|
||||||
|
nb_required += PES_extension_flag? 1:0;
|
||||||
|
if (!stream->require(nb_required)) {
|
||||||
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE payload");
|
||||||
}
|
}
|
||||||
int pos_packet = stream->pos();
|
|
||||||
|
|
||||||
// @remark the sid indicates the elementary stream format.
|
// 5B
|
||||||
// the SrsTsPESStreamIdAudio and SrsTsPESStreamIdVideo is start by 0b110 or 0b1110
|
if (PTS_DTS_flags == 0x2) {
|
||||||
SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id;
|
if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) {
|
||||||
msg->sid = sid;
|
return srs_error_wrap(err, "dts/pts");
|
||||||
|
|
||||||
if (sid != SrsTsPESStreamIdProgramStreamMap
|
|
||||||
&& sid != SrsTsPESStreamIdPaddingStream
|
|
||||||
&& sid != SrsTsPESStreamIdPrivateStream2
|
|
||||||
&& sid != SrsTsPESStreamIdEcmStream
|
|
||||||
&& sid != SrsTsPESStreamIdEmmStream
|
|
||||||
&& sid != SrsTsPESStreamIdProgramStreamDirectory
|
|
||||||
&& sid != SrsTsPESStreamIdDsmccStream
|
|
||||||
&& sid != SrsTsPESStreamIdH2221TypeE
|
|
||||||
) {
|
|
||||||
// 3B flags.
|
|
||||||
if (!stream->require(3)) {
|
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE flags");
|
|
||||||
}
|
}
|
||||||
// 1B
|
dts = pts;
|
||||||
int8_t oocv = stream->read_1bytes();
|
}
|
||||||
// 1B
|
|
||||||
int8_t pefv = stream->read_1bytes();
|
|
||||||
// 1B
|
|
||||||
PES_header_data_length = stream->read_1bytes();
|
|
||||||
// position of header start.
|
|
||||||
int pos_header = stream->pos();
|
|
||||||
|
|
||||||
const2bits = (oocv >> 6) & 0x03;
|
// 10B
|
||||||
PES_scrambling_control = (oocv >> 4) & 0x03;
|
if (PTS_DTS_flags == 0x3) {
|
||||||
PES_priority = (oocv >> 3) & 0x01;
|
if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) {
|
||||||
data_alignment_indicator = (oocv >> 2) & 0x01;
|
return srs_error_wrap(err, "dts/pts");
|
||||||
copyright = (oocv >> 1) & 0x01;
|
}
|
||||||
original_or_copy = oocv & 0x01;
|
if ((err = decode_33bits_dts_pts(stream, &dts)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "dts/pts");
|
||||||
|
}
|
||||||
|
|
||||||
PTS_DTS_flags = (pefv >> 6) & 0x03;
|
// check sync, the diff of dts and pts should never greater than 1s.
|
||||||
ESCR_flag = (pefv >> 5) & 0x01;
|
if (dts - pts > 90000 || pts - dts > 90000) {
|
||||||
ES_rate_flag = (pefv >> 4) & 0x01;
|
srs_warn("ts: sync dts=%" PRId64 ", pts=%" PRId64, dts, pts);
|
||||||
DSM_trick_mode_flag = (pefv >> 3) & 0x01;
|
}
|
||||||
additional_copy_info_flag = (pefv >> 2) & 0x01;
|
}
|
||||||
PES_CRC_flag = (pefv >> 1) & 0x01;
|
|
||||||
PES_extension_flag = pefv & 0x01;
|
|
||||||
|
|
||||||
// check required together.
|
// Ignore coverage bellow, for we don't use them in HLS.
|
||||||
int nb_required = 0;
|
// LCOV_EXCL_START
|
||||||
nb_required += (PTS_DTS_flags == 0x2)? 5:0;
|
|
||||||
nb_required += (PTS_DTS_flags == 0x3)? 10:0;
|
// 6B
|
||||||
nb_required += ESCR_flag? 6:0;
|
if (ESCR_flag) {
|
||||||
nb_required += ES_rate_flag? 3:0;
|
ESCR_extension = 0;
|
||||||
nb_required += DSM_trick_mode_flag? 1:0;
|
ESCR_base = 0;
|
||||||
nb_required += additional_copy_info_flag? 1:0;
|
|
||||||
nb_required += PES_CRC_flag? 2:0;
|
stream->skip(6);
|
||||||
nb_required += PES_extension_flag? 1:0;
|
srs_warn("ts: demux PES, ignore the escr.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3B
|
||||||
|
if (ES_rate_flag) {
|
||||||
|
ES_rate = stream->read_3bytes();
|
||||||
|
|
||||||
|
ES_rate = ES_rate >> 1;
|
||||||
|
ES_rate &= 0x3FFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
if (DSM_trick_mode_flag) {
|
||||||
|
trick_mode_control = stream->read_1bytes();
|
||||||
|
|
||||||
|
trick_mode_value = trick_mode_control & 0x1f;
|
||||||
|
trick_mode_control = (trick_mode_control >> 5) & 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
if (additional_copy_info_flag) {
|
||||||
|
additional_copy_info = stream->read_1bytes();
|
||||||
|
|
||||||
|
additional_copy_info &= 0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2B
|
||||||
|
if (PES_CRC_flag) {
|
||||||
|
previous_PES_packet_CRC = stream->read_2bytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1B
|
||||||
|
if (PES_extension_flag) {
|
||||||
|
int8_t efv = stream->read_1bytes();
|
||||||
|
|
||||||
|
PES_private_data_flag = (efv >> 7) & 0x01;
|
||||||
|
pack_header_field_flag = (efv >> 6) & 0x01;
|
||||||
|
program_packet_sequence_counter_flag = (efv >> 5) & 0x01;
|
||||||
|
P_STD_buffer_flag = (efv >> 4) & 0x01;
|
||||||
|
const1_value0 = (efv >> 1) & 0x07;
|
||||||
|
PES_extension_flag_2 = efv & 0x01;
|
||||||
|
|
||||||
|
nb_required = 0;
|
||||||
|
nb_required += PES_private_data_flag? 16:0;
|
||||||
|
nb_required += pack_header_field_flag? 1:0; // 1+x bytes.
|
||||||
|
nb_required += program_packet_sequence_counter_flag? 2:0;
|
||||||
|
nb_required += P_STD_buffer_flag? 2:0;
|
||||||
|
nb_required += PES_extension_flag_2? 1:0; // 1+x bytes.
|
||||||
if (!stream->require(nb_required)) {
|
if (!stream->require(nb_required)) {
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE payload");
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext payload");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5B
|
// 16B
|
||||||
if (PTS_DTS_flags == 0x2) {
|
if (PES_private_data_flag) {
|
||||||
if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) {
|
PES_private_data.resize(16);
|
||||||
return srs_error_wrap(err, "dts/pts");
|
stream->read_bytes(&PES_private_data[0], 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (1+x)B
|
||||||
|
if (pack_header_field_flag) {
|
||||||
|
// This is an 8-bit field which indicates the length, in bytes, of the pack_header_field()
|
||||||
|
uint8_t pack_field_length = stream->read_1bytes();
|
||||||
|
if (pack_field_length > 0) {
|
||||||
|
// the adjust required bytes.
|
||||||
|
nb_required = nb_required - 16 - 1 + pack_field_length;
|
||||||
|
if (!stream->require(nb_required)) {
|
||||||
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext pack");
|
||||||
|
}
|
||||||
|
pack_field.resize(pack_field_length);
|
||||||
|
stream->read_bytes(&pack_field[0], pack_field_length);
|
||||||
}
|
}
|
||||||
dts = pts;
|
|
||||||
|
|
||||||
// update the dts and pts of message.
|
|
||||||
msg->dts = dts;
|
|
||||||
msg->pts = pts;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 10B
|
|
||||||
if (PTS_DTS_flags == 0x3) {
|
|
||||||
if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "dts/pts");
|
|
||||||
}
|
|
||||||
if ((err = decode_33bits_dts_pts(stream, &dts)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "dts/pts");
|
|
||||||
}
|
|
||||||
|
|
||||||
// check sync, the diff of dts and pts should never greater than 1s.
|
|
||||||
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.
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
|
|
||||||
// 6B
|
|
||||||
if (ESCR_flag) {
|
|
||||||
ESCR_extension = 0;
|
|
||||||
ESCR_base = 0;
|
|
||||||
|
|
||||||
stream->skip(6);
|
|
||||||
srs_warn("ts: demux PES, ignore the escr.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3B
|
|
||||||
if (ES_rate_flag) {
|
|
||||||
ES_rate = stream->read_3bytes();
|
|
||||||
|
|
||||||
ES_rate = ES_rate >> 1;
|
|
||||||
ES_rate &= 0x3FFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1B
|
|
||||||
if (DSM_trick_mode_flag) {
|
|
||||||
trick_mode_control = stream->read_1bytes();
|
|
||||||
|
|
||||||
trick_mode_value = trick_mode_control & 0x1f;
|
|
||||||
trick_mode_control = (trick_mode_control >> 5) & 0x03;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1B
|
|
||||||
if (additional_copy_info_flag) {
|
|
||||||
additional_copy_info = stream->read_1bytes();
|
|
||||||
|
|
||||||
additional_copy_info &= 0x7f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2B
|
// 2B
|
||||||
if (PES_CRC_flag) {
|
if (program_packet_sequence_counter_flag) {
|
||||||
previous_PES_packet_CRC = stream->read_2bytes();
|
program_packet_sequence_counter = stream->read_1bytes();
|
||||||
|
program_packet_sequence_counter &= 0x7f;
|
||||||
|
|
||||||
|
original_stuff_length = stream->read_1bytes();
|
||||||
|
MPEG1_MPEG2_identifier = (original_stuff_length >> 6) & 0x01;
|
||||||
|
original_stuff_length &= 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1B
|
// 2B
|
||||||
if (PES_extension_flag) {
|
if (P_STD_buffer_flag) {
|
||||||
int8_t efv = stream->read_1bytes();
|
P_STD_buffer_size = stream->read_2bytes();
|
||||||
|
|
||||||
PES_private_data_flag = (efv >> 7) & 0x01;
|
// '01'
|
||||||
pack_header_field_flag = (efv >> 6) & 0x01;
|
//int8_t const2bits = (P_STD_buffer_scale >>14) & 0x03;
|
||||||
program_packet_sequence_counter_flag = (efv >> 5) & 0x01;
|
|
||||||
P_STD_buffer_flag = (efv >> 4) & 0x01;
|
|
||||||
const1_value0 = (efv >> 1) & 0x07;
|
|
||||||
PES_extension_flag_2 = efv & 0x01;
|
|
||||||
|
|
||||||
nb_required = 0;
|
P_STD_buffer_scale = (P_STD_buffer_scale >>13) & 0x01;
|
||||||
nb_required += PES_private_data_flag? 16:0;
|
P_STD_buffer_size &= 0x1FFF;
|
||||||
nb_required += pack_header_field_flag? 1:0; // 1+x bytes.
|
}
|
||||||
nb_required += program_packet_sequence_counter_flag? 2:0;
|
|
||||||
nb_required += P_STD_buffer_flag? 2:0;
|
|
||||||
nb_required += PES_extension_flag_2? 1:0; // 1+x bytes.
|
|
||||||
if (!stream->require(nb_required)) {
|
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext payload");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 16B
|
// (1+x)B
|
||||||
if (PES_private_data_flag) {
|
if (PES_extension_flag_2) {
|
||||||
PES_private_data.resize(16);
|
/**
|
||||||
stream->read_bytes(&PES_private_data[0], 16);
|
* This is a 7-bit field which specifies the length, in bytes, of the data following this field in
|
||||||
}
|
* the PES extension field up to and including any reserved bytes.
|
||||||
|
*/
|
||||||
|
uint8_t PES_extension_field_length = stream->read_1bytes();
|
||||||
|
PES_extension_field_length &= 0x7F;
|
||||||
|
|
||||||
// (1+x)B
|
if (PES_extension_field_length > 0) {
|
||||||
if (pack_header_field_flag) {
|
if (!stream->require(PES_extension_field_length)) {
|
||||||
// This is an 8-bit field which indicates the length, in bytes, of the pack_header_field()
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext field");
|
||||||
uint8_t pack_field_length = stream->read_1bytes();
|
|
||||||
if (pack_field_length > 0) {
|
|
||||||
// the adjust required bytes.
|
|
||||||
nb_required = nb_required - 16 - 1 + pack_field_length;
|
|
||||||
if (!stream->require(nb_required)) {
|
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext pack");
|
|
||||||
}
|
|
||||||
pack_field.resize(pack_field_length);
|
|
||||||
stream->read_bytes(&pack_field[0], pack_field_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2B
|
|
||||||
if (program_packet_sequence_counter_flag) {
|
|
||||||
program_packet_sequence_counter = stream->read_1bytes();
|
|
||||||
program_packet_sequence_counter &= 0x7f;
|
|
||||||
|
|
||||||
original_stuff_length = stream->read_1bytes();
|
|
||||||
MPEG1_MPEG2_identifier = (original_stuff_length >> 6) & 0x01;
|
|
||||||
original_stuff_length &= 0x3f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2B
|
|
||||||
if (P_STD_buffer_flag) {
|
|
||||||
P_STD_buffer_size = stream->read_2bytes();
|
|
||||||
|
|
||||||
// '01'
|
|
||||||
//int8_t const2bits = (P_STD_buffer_scale >>14) & 0x03;
|
|
||||||
|
|
||||||
P_STD_buffer_scale = (P_STD_buffer_scale >>13) & 0x01;
|
|
||||||
P_STD_buffer_size &= 0x1FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (1+x)B
|
|
||||||
if (PES_extension_flag_2) {
|
|
||||||
/**
|
|
||||||
* This is a 7-bit field which specifies the length, in bytes, of the data following this field in
|
|
||||||
* the PES extension field up to and including any reserved bytes.
|
|
||||||
*/
|
|
||||||
uint8_t PES_extension_field_length = stream->read_1bytes();
|
|
||||||
PES_extension_field_length &= 0x7F;
|
|
||||||
|
|
||||||
if (PES_extension_field_length > 0) {
|
|
||||||
if (!stream->require(PES_extension_field_length)) {
|
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext field");
|
|
||||||
}
|
|
||||||
PES_extension_field.resize(PES_extension_field_length);
|
|
||||||
stream->read_bytes(&PES_extension_field[0], PES_extension_field_length);
|
|
||||||
}
|
}
|
||||||
|
PES_extension_field.resize(PES_extension_field_length);
|
||||||
|
stream->read_bytes(&PES_extension_field[0], PES_extension_field_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// stuffing_byte
|
|
||||||
nb_stuffings = PES_header_data_length - (stream->pos() - pos_header);
|
|
||||||
if (nb_stuffings > 0) {
|
|
||||||
if (!stream->require(nb_stuffings)) {
|
|
||||||
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE stuffings");
|
|
||||||
}
|
|
||||||
stream->skip(nb_stuffings);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
|
|
||||||
// PES_packet_data_byte, page58.
|
|
||||||
// the packet size contains the header size.
|
|
||||||
// The number of PES_packet_data_bytes, N, is specified by the
|
|
||||||
// PES_packet_length field. N shall be equal to the value
|
|
||||||
// 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 (PES_packet_length > 0) {
|
|
||||||
int nb_packet = PES_packet_length - (stream->pos() - pos_packet);
|
|
||||||
msg->PES_packet_length = srs_max(0, nb_packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// xB
|
|
||||||
if ((err = msg->dump(stream, &nb_bytes)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "dump pes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore coverage bellow, for we don't use them in HLS.
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
} else if (sid == SrsTsPESStreamIdProgramStreamMap
|
|
||||||
|| sid == SrsTsPESStreamIdPrivateStream2
|
|
||||||
|| sid == SrsTsPESStreamIdEcmStream
|
|
||||||
|| sid == SrsTsPESStreamIdEmmStream
|
|
||||||
|| sid == SrsTsPESStreamIdProgramStreamDirectory
|
|
||||||
|| sid == SrsTsPESStreamIdDsmccStream
|
|
||||||
|| sid == SrsTsPESStreamIdH2221TypeE
|
|
||||||
) {
|
|
||||||
// for (i = 0; i < PES_packet_length; i++) {
|
|
||||||
// PES_packet_data_byte
|
|
||||||
// }
|
|
||||||
|
|
||||||
// xB
|
|
||||||
if ((err = msg->dump(stream, &nb_bytes)) != srs_success) {
|
|
||||||
return srs_error_wrap(err, "dump packet");
|
|
||||||
}
|
|
||||||
} else if (sid == SrsTsPESStreamIdPaddingStream) {
|
|
||||||
// for (i = 0; i < PES_packet_length; i++) {
|
|
||||||
// padding_byte
|
|
||||||
// }
|
|
||||||
nb_paddings = stream->size() - stream->pos();
|
|
||||||
stream->skip(nb_paddings);
|
|
||||||
srs_info("ts: drop %dB padding bytes", nb_paddings);
|
|
||||||
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
} else {
|
|
||||||
int nb_drop = stream->size() - stream->pos();
|
|
||||||
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,
|
// stuffing_byte
|
||||||
// the payload_unit_start_indicator always be 1,
|
nb_stuffings = PES_header_data_length - (stream->pos() - pos_header);
|
||||||
// the message should never EOF for the first packet.
|
if (nb_stuffings > 0) {
|
||||||
if (is_fresh_msg && msg->PES_packet_length == 0) {
|
if (!stream->require(nb_stuffings)) {
|
||||||
return err;
|
return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE stuffings");
|
||||||
}
|
}
|
||||||
|
stream->skip(nb_stuffings);
|
||||||
|
}
|
||||||
|
|
||||||
// check msg, reap when completed.
|
// LCOV_EXCL_STOP
|
||||||
if (msg->completed(packet->payload_unit_start_indicator)) {
|
|
||||||
*ppmsg = msg;
|
// PES_packet_data_byte, page58.
|
||||||
channel->msg = NULL;
|
// the packet size contains the header size.
|
||||||
srs_info("ts: reap msg for completed.");
|
// The number of PES_packet_data_bytes, N, is specified by the
|
||||||
|
// PES_packet_length field. N shall be equal to the value
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// 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);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|| sid == SrsTsPESStreamIdPrivateStream2
|
||||||
|
|| sid == SrsTsPESStreamIdEcmStream
|
||||||
|
|| sid == SrsTsPESStreamIdEmmStream
|
||||||
|
|| sid == SrsTsPESStreamIdProgramStreamDirectory
|
||||||
|
|| sid == SrsTsPESStreamIdDsmccStream
|
||||||
|
|| sid == SrsTsPESStreamIdH2221TypeE
|
||||||
|
) {
|
||||||
|
// for (i = 0; i < PES_packet_length; i++) {
|
||||||
|
// PES_packet_data_byte
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// }
|
||||||
|
nb_paddings = stream->size() - stream->pos();
|
||||||
|
stream->skip(nb_paddings);
|
||||||
|
srs_info("ts: drop %dB padding bytes", nb_paddings);
|
||||||
|
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
} else {
|
||||||
|
int nb_drop = stream->size() - stream->pos();
|
||||||
|
stream->skip(nb_drop);
|
||||||
|
srs_warn("ts: drop the pes packet %dB for stream_id=%#x", nb_drop, stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsTsPayloadPES::size()
|
int SrsMpegPES::size()
|
||||||
{
|
{
|
||||||
int sz = 0;
|
int sz = 0;
|
||||||
|
|
||||||
|
@ -1744,7 +1638,7 @@ int SrsTsPayloadPES::size()
|
||||||
|| sid == SrsTsPESStreamIdProgramStreamDirectory
|
|| sid == SrsTsPESStreamIdProgramStreamDirectory
|
||||||
|| sid == SrsTsPESStreamIdDsmccStream
|
|| sid == SrsTsPESStreamIdDsmccStream
|
||||||
|| sid == SrsTsPESStreamIdH2221TypeE
|
|| sid == SrsTsPESStreamIdH2221TypeE
|
||||||
) {
|
) {
|
||||||
// packet bytes
|
// packet bytes
|
||||||
} else {
|
} else {
|
||||||
// nb_drop
|
// nb_drop
|
||||||
|
@ -1753,7 +1647,7 @@ int SrsTsPayloadPES::size()
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream)
|
srs_error_t SrsMpegPES::encode(SrsBuffer* stream)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -1909,7 +1803,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream)
|
||||||
return err;
|
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;
|
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;
|
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;
|
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;
|
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)
|
SrsTsPayloadPSI::SrsTsPayloadPSI(SrsTsPacket* p) : SrsTsPayload(p)
|
||||||
{
|
{
|
||||||
pointer_field = 0;
|
pointer_field = 0;
|
||||||
|
|
|
@ -28,6 +28,7 @@ class SrsTsPayload;
|
||||||
class SrsTsMessage;
|
class SrsTsMessage;
|
||||||
class SrsTsPacket;
|
class SrsTsPacket;
|
||||||
class SrsTsContext;
|
class SrsTsContext;
|
||||||
|
class SrsPsPacket;
|
||||||
|
|
||||||
// Transport Stream packets are 188 bytes in length.
|
// Transport Stream packets are 188 bytes in length.
|
||||||
#define SRS_TS_PACKET_SIZE 188
|
#define SRS_TS_PACKET_SIZE 188
|
||||||
|
@ -90,14 +91,14 @@ enum SrsTsPidApply
|
||||||
{
|
{
|
||||||
SrsTsPidApplyReserved = 0, // TSPidTypeReserved, nothing parsed, used reserved.
|
SrsTsPidApplyReserved = 0, // TSPidTypeReserved, nothing parsed, used reserved.
|
||||||
|
|
||||||
SrsTsPidApplyPAT, // Program associtate table
|
SrsTsPidApplyPAT, // Program associtate table for TS.
|
||||||
SrsTsPidApplyPMT, // Program map table.
|
SrsTsPidApplyPMT, // Program map table for TS.
|
||||||
|
|
||||||
SrsTsPidApplyVideo, // for video
|
SrsTsPidApplyVideo, // for video
|
||||||
SrsTsPidApplyAudio, // vor audio
|
SrsTsPidApplyAudio, // vor audio
|
||||||
};
|
};
|
||||||
|
|
||||||
// Table 2-29 - Stream type assignments
|
// Table 2-29 - Stream type assignments, hls-mpeg-ts-iso13818-1.pdf, page 66
|
||||||
enum SrsTsStream
|
enum SrsTsStream
|
||||||
{
|
{
|
||||||
// ITU-T | ISO/IEC Reserved
|
// ITU-T | ISO/IEC Reserved
|
||||||
|
@ -215,9 +216,7 @@ enum SrsTsPESStreamId
|
||||||
class SrsTsMessage
|
class SrsTsMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// For decoder only,
|
// For decoder only, the ts message does not use them, for user to get the channel and packet.
|
||||||
// the ts messgae does not use them,
|
|
||||||
// for user to get the channel and packet.
|
|
||||||
SrsTsChannel* channel;
|
SrsTsChannel* channel;
|
||||||
SrsTsPacket* packet;
|
SrsTsPacket* packet;
|
||||||
public:
|
public:
|
||||||
|
@ -294,12 +293,10 @@ private:
|
||||||
// When PAT and PMT writen, the context is ready.
|
// When PAT and PMT writen, the context is ready.
|
||||||
// @see https://github.com/ossrs/srs/issues/834
|
// @see https://github.com/ossrs/srs/issues/834
|
||||||
bool ready;
|
bool ready;
|
||||||
// codec
|
|
||||||
private:
|
private:
|
||||||
std::map<int, SrsTsChannel*> pids;
|
std::map<int, SrsTsChannel*> pids;
|
||||||
bool pure_audio;
|
bool pure_audio;
|
||||||
int8_t sync_byte;
|
int8_t sync_byte;
|
||||||
// encoder
|
|
||||||
private:
|
private:
|
||||||
// when any codec changed, write the PAT/PMT.
|
// when any codec changed, write the PAT/PMT.
|
||||||
SrsVideoCodecId vcodec;
|
SrsVideoCodecId vcodec;
|
||||||
|
@ -309,37 +306,33 @@ public:
|
||||||
virtual ~SrsTsContext();
|
virtual ~SrsTsContext();
|
||||||
public:
|
public:
|
||||||
// Whether the hls stream is pure audio stream.
|
// Whether the hls stream is pure audio stream.
|
||||||
// TODO: FIXME: merge with muxer codec detect.
|
// TODO: FIXME: merge with muxer codec detect.
|
||||||
virtual bool is_pure_audio();
|
virtual bool is_pure_audio();
|
||||||
// When PMT table parsed, we know some info about stream.
|
// When PMT table parsed, we know some info about stream.
|
||||||
virtual void on_pmt_parsed();
|
virtual void on_pmt_parsed();
|
||||||
// Reset the context for a new ts segment start.
|
// Reset the context for a new ts segment start.
|
||||||
virtual void reset();
|
virtual void reset();
|
||||||
// codec
|
|
||||||
public:
|
public:
|
||||||
// Get the pid apply, the parsed pid.
|
// Get the pid apply, the parsed pid.
|
||||||
// @return the apply channel; NULL for invalid.
|
// @return the apply channel; NULL for invalid.
|
||||||
virtual SrsTsChannel* get(int pid);
|
virtual SrsTsChannel* get(int pid);
|
||||||
// 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:
|
public:
|
||||||
// The stream contains only one ts packet.
|
// Feed with ts packets, decode as ts message, callback handler if got one ts message.
|
||||||
// @param handler the ts message handler to process the msg.
|
// A ts video message can be decoded to NALUs by SrsRawH264Stream::annexb_demux.
|
||||||
// @remark we will consume all bytes in stream.
|
// A ts audio message can be decoded to RAW frame by SrsRawAacStream::adts_demux.
|
||||||
|
// @param handler The ts message handler to process the msg.
|
||||||
|
// @remark We will consume all bytes in stream.
|
||||||
virtual srs_error_t decode(SrsBuffer* stream, ISrsTsHandler* handler);
|
virtual srs_error_t decode(SrsBuffer* stream, ISrsTsHandler* handler);
|
||||||
// encode methods
|
|
||||||
public:
|
public:
|
||||||
// Write the PES packet, the video/audio stream.
|
// Encode ts video/audio messages to the PES packets, as PES stream.
|
||||||
// @param msg the video/audio msg to write to ts.
|
// @param msg The video/audio msg to write to ts.
|
||||||
// @param vc the video codec, write the PAT/PMT table when changed.
|
// A ts video message is a frame with one or more NALUs, generally encoded by SrsTsMessageCache.cache_video.
|
||||||
// @param ac the audio codec, write the PAT/PMT table when changed.
|
// A ts audio message is an audio packet, encoded by SrsTsMessageCache.cache_audio to ADTS for AAC.
|
||||||
|
// @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 srs_error_t encode(ISrsStreamWriter* writer, SrsTsMessage* msg, SrsVideoCodecId vc, SrsAudioCodecId ac);
|
virtual srs_error_t encode(ISrsStreamWriter* writer, SrsTsMessage* msg, SrsVideoCodecId vc, SrsAudioCodecId ac);
|
||||||
// drm methods
|
|
||||||
public:
|
|
||||||
// Set sync byte of ts segment.
|
|
||||||
// replace the standard ts sync byte to bravo sync byte.
|
|
||||||
virtual void set_sync_byte(int8_t sb);
|
|
||||||
private:
|
private:
|
||||||
virtual srs_error_t encode_pat_pmt(ISrsStreamWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as);
|
virtual srs_error_t encode_pat_pmt(ISrsStreamWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as);
|
||||||
virtual srs_error_t encode_pes(ISrsStreamWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio);
|
virtual srs_error_t encode_pes(ISrsStreamWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio);
|
||||||
|
@ -741,9 +734,8 @@ public:
|
||||||
virtual srs_error_t encode(SrsBuffer* stream) = 0;
|
virtual srs_error_t encode(SrsBuffer* stream) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The PES payload of ts packet.
|
// Common MPEG PES packet for both TS and PS.
|
||||||
// 2.4.3.6 PES packet, hls-mpeg-ts-iso13818-1.pdf, page 49
|
class SrsMpegPES
|
||||||
class SrsTsPayloadPES : public SrsTsPayload
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// 3B
|
// 3B
|
||||||
|
@ -993,6 +985,29 @@ public:
|
||||||
// NB
|
// NB
|
||||||
// This is a fixed 8-bit value equal to '1111 1111'. It is discarded by the decoder.
|
// This is a fixed 8-bit value equal to '1111 1111'. It is discarded by the decoder.
|
||||||
int nb_paddings;
|
int nb_paddings;
|
||||||
|
public:
|
||||||
|
// Whether contains payload to dump to message.
|
||||||
|
bool has_payload_;
|
||||||
|
int nb_payload_;
|
||||||
|
public:
|
||||||
|
SrsMpegPES();
|
||||||
|
virtual ~SrsMpegPES();
|
||||||
|
public:
|
||||||
|
virtual srs_error_t decode(SrsBuffer* stream);
|
||||||
|
public:
|
||||||
|
virtual int size();
|
||||||
|
virtual srs_error_t encode(SrsBuffer* stream);
|
||||||
|
private:
|
||||||
|
virtual srs_error_t decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv);
|
||||||
|
virtual srs_error_t encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v);
|
||||||
|
};
|
||||||
|
|
||||||
|
// The PES payload of ts packet.
|
||||||
|
// 2.4.3.6 PES packet, hls-mpeg-ts-iso13818-1.pdf, page 49
|
||||||
|
class SrsTsPayloadPES : public SrsTsPayload
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsMpegPES pes;
|
||||||
public:
|
public:
|
||||||
SrsTsPayloadPES(SrsTsPacket* p);
|
SrsTsPayloadPES(SrsTsPacket* p);
|
||||||
virtual ~SrsTsPayloadPES();
|
virtual ~SrsTsPayloadPES();
|
||||||
|
@ -1001,9 +1016,6 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int size();
|
virtual int size();
|
||||||
virtual srs_error_t encode(SrsBuffer* stream);
|
virtual srs_error_t encode(SrsBuffer* stream);
|
||||||
private:
|
|
||||||
virtual srs_error_t decode_33bits_dts_pts(SrsBuffer* stream, int64_t* pv);
|
|
||||||
virtual srs_error_t encode_33bits_dts_pts(SrsBuffer* stream, uint8_t fb, int64_t v);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The PSI payload of ts packet.
|
// The PSI payload of ts packet.
|
||||||
|
|
|
@ -765,7 +765,7 @@ VOID TEST(KernelRTCTest, NACKEncode)
|
||||||
vector<uint16_t> before = rtcp_nack_encode.get_lost_sns();
|
vector<uint16_t> before = rtcp_nack_encode.get_lost_sns();
|
||||||
vector<uint16_t> after = rtcp_nack_decode.get_lost_sns();
|
vector<uint16_t> after = rtcp_nack_decode.get_lost_sns();
|
||||||
EXPECT_TRUE(before.size() == after.size());
|
EXPECT_TRUE(before.size() == after.size());
|
||||||
for(int i = 0; i < before.size() && i < after.size(); ++i) {
|
for(int i = 0; i < (int)before.size() && i < (int)after.size(); ++i) {
|
||||||
EXPECT_TRUE(before.at(i) == after.at(i));
|
EXPECT_TRUE(before.at(i) == after.at(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -932,11 +932,11 @@ VOID TEST(KernelRTCTest, Ntp)
|
||||||
// Cover systime to ntp
|
// Cover systime to ntp
|
||||||
SrsNtp ntp = SrsNtp::from_time_ms(now_ms);
|
SrsNtp ntp = SrsNtp::from_time_ms(now_ms);
|
||||||
|
|
||||||
ASSERT_EQ(ntp.system_ms_, now_ms);
|
ASSERT_EQ((srs_utime_t)ntp.system_ms_, now_ms);
|
||||||
|
|
||||||
// Cover ntp to systime
|
// Cover ntp to systime
|
||||||
SrsNtp ntp1 = SrsNtp::to_time_ms(ntp.ntp_);
|
SrsNtp ntp1 = SrsNtp::to_time_ms(ntp.ntp_);
|
||||||
ASSERT_EQ(ntp1.system_ms_, now_ms);
|
ASSERT_EQ((srs_utime_t)ntp1.system_ms_, now_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,10 +945,10 @@ VOID TEST(KernelRTCTest, Ntp)
|
||||||
srs_utime_t now_ms = srs_get_system_time() / 1000;
|
srs_utime_t now_ms = srs_get_system_time() / 1000;
|
||||||
SrsNtp ntp = SrsNtp::from_time_ms(now_ms);
|
SrsNtp ntp = SrsNtp::from_time_ms(now_ms);
|
||||||
|
|
||||||
ASSERT_EQ(ntp.system_ms_, now_ms);
|
ASSERT_EQ((srs_utime_t)ntp.system_ms_, now_ms);
|
||||||
|
|
||||||
SrsNtp ntp1 = SrsNtp::to_time_ms(ntp.ntp_);
|
SrsNtp ntp1 = SrsNtp::to_time_ms(ntp.ntp_);
|
||||||
ASSERT_EQ(ntp1.system_ms_, now_ms);
|
ASSERT_EQ((srs_utime_t)ntp1.system_ms_, now_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,46 +1279,46 @@ VOID TEST(KernelRTCTest, JitterTimestamp)
|
||||||
SrsRtcTsJitter jitter(1000);
|
SrsRtcTsJitter jitter(1000);
|
||||||
|
|
||||||
// Starts from the base.
|
// Starts from the base.
|
||||||
EXPECT_EQ(1000, jitter.correct(0));
|
EXPECT_EQ((uint32_t)1000, jitter.correct(0));
|
||||||
|
|
||||||
// Start from here.
|
// Start from here.
|
||||||
EXPECT_EQ(1010, jitter.correct(10));
|
EXPECT_EQ((uint32_t)1010, jitter.correct(10));
|
||||||
EXPECT_EQ(1010, jitter.correct(10));
|
EXPECT_EQ((uint32_t)1010, jitter.correct(10));
|
||||||
EXPECT_EQ(1020, jitter.correct(20));
|
EXPECT_EQ((uint32_t)1020, jitter.correct(20));
|
||||||
|
|
||||||
// Reset the base for jitter detected.
|
// Reset the base for jitter detected.
|
||||||
EXPECT_EQ(1020, jitter.correct(20 + 90*3*1000 + 1));
|
EXPECT_EQ((uint32_t)1020, jitter.correct(20 + 90*3*1000 + 1));
|
||||||
EXPECT_EQ(1019, jitter.correct(20 + 90*3*1000));
|
EXPECT_EQ((uint32_t)1019, jitter.correct(20 + 90*3*1000));
|
||||||
EXPECT_EQ(1021, jitter.correct(20 + 90*3*1000 + 2));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(20 + 90*3*1000 + 2));
|
||||||
EXPECT_EQ(1019, jitter.correct(20 + 90*3*1000));
|
EXPECT_EQ((uint32_t)1019, jitter.correct(20 + 90*3*1000));
|
||||||
EXPECT_EQ(1020, jitter.correct(20 + 90*3*1000 + 1));
|
EXPECT_EQ((uint32_t)1020, jitter.correct(20 + 90*3*1000 + 1));
|
||||||
|
|
||||||
// Rollback the timestamp.
|
// Rollback the timestamp.
|
||||||
EXPECT_EQ(1020, jitter.correct(20));
|
EXPECT_EQ((uint32_t)1020, jitter.correct(20));
|
||||||
EXPECT_EQ(1021, jitter.correct(20 + 1));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(20 + 1));
|
||||||
EXPECT_EQ(1021, jitter.correct(21));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(21));
|
||||||
|
|
||||||
// Reset for jitter again.
|
// Reset for jitter again.
|
||||||
EXPECT_EQ(1021, jitter.correct(21 + 90*3*1000 + 1));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(21 + 90*3*1000 + 1));
|
||||||
EXPECT_EQ(1021, jitter.correct(21));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(21));
|
||||||
|
|
||||||
// No jitter at edge.
|
// No jitter at edge.
|
||||||
EXPECT_EQ(1021 + 90*3*1000, jitter.correct(21 + 90*3*1000));
|
EXPECT_EQ((uint32_t)(1021 + 90*3*1000), jitter.correct(21 + 90*3*1000));
|
||||||
EXPECT_EQ(1021 + 90*3*1000 + 1, jitter.correct(21 + 90*3*1000 + 1));
|
EXPECT_EQ((uint32_t)(1021 + 90*3*1000 + 1), jitter.correct(21 + 90*3*1000 + 1));
|
||||||
EXPECT_EQ(1021 + 1, jitter.correct(21 + 1));
|
EXPECT_EQ((uint32_t)(1021 + 1), jitter.correct(21 + 1));
|
||||||
|
|
||||||
// Also safety to decrease the value.
|
// Also safety to decrease the value.
|
||||||
EXPECT_EQ(1021, jitter.correct(21));
|
EXPECT_EQ((uint32_t)1021, jitter.correct(21));
|
||||||
EXPECT_EQ(1010, jitter.correct(10));
|
EXPECT_EQ((uint32_t)1010, jitter.correct(10));
|
||||||
|
|
||||||
// Try to reset to 0 base.
|
// Try to reset to 0 base.
|
||||||
EXPECT_EQ(1010, jitter.correct(10 + 90*3*1000 + 1010));
|
EXPECT_EQ((uint32_t)1010, jitter.correct(10 + 90*3*1000 + 1010));
|
||||||
EXPECT_EQ(0, jitter.correct(10 + 90*3*1000));
|
EXPECT_EQ((uint32_t)0, jitter.correct(10 + 90*3*1000));
|
||||||
EXPECT_EQ(0, jitter.correct(0));
|
EXPECT_EQ((uint32_t)0, jitter.correct(0));
|
||||||
|
|
||||||
// Also safety to start from zero.
|
// Also safety to start from zero.
|
||||||
EXPECT_EQ(10, jitter.correct(10));
|
EXPECT_EQ((uint32_t)10, jitter.correct(10));
|
||||||
EXPECT_EQ(11, jitter.correct(11));
|
EXPECT_EQ((uint32_t)11, jitter.correct(11));
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID TEST(KernelRTCTest, JitterSequence)
|
VOID TEST(KernelRTCTest, JitterSequence)
|
||||||
|
@ -1326,45 +1326,45 @@ VOID TEST(KernelRTCTest, JitterSequence)
|
||||||
SrsRtcSeqJitter jitter(100);
|
SrsRtcSeqJitter jitter(100);
|
||||||
|
|
||||||
// Starts from the base.
|
// Starts from the base.
|
||||||
EXPECT_EQ(100, jitter.correct(0));
|
EXPECT_EQ((uint32_t)100, jitter.correct(0));
|
||||||
|
|
||||||
// Normal without jitter.
|
// Normal without jitter.
|
||||||
EXPECT_EQ(101, jitter.correct(1));
|
EXPECT_EQ((uint32_t)101, jitter.correct(1));
|
||||||
EXPECT_EQ(102, jitter.correct(2));
|
EXPECT_EQ((uint32_t)102, jitter.correct(2));
|
||||||
EXPECT_EQ(101, jitter.correct(1));
|
EXPECT_EQ((uint32_t)101, jitter.correct(1));
|
||||||
EXPECT_EQ(103, jitter.correct(3));
|
EXPECT_EQ((uint32_t)103, jitter.correct(3));
|
||||||
EXPECT_EQ(110, jitter.correct(10));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10));
|
||||||
|
|
||||||
// Reset the base for jitter detected.
|
// Reset the base for jitter detected.
|
||||||
EXPECT_EQ(110, jitter.correct(10 + 128 + 1));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 1));
|
||||||
EXPECT_EQ(109, jitter.correct(10 + 128));
|
EXPECT_EQ((uint32_t)109, jitter.correct(10 + 128));
|
||||||
EXPECT_EQ(110, jitter.correct(10 + 128 + 1));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 1));
|
||||||
|
|
||||||
// Rollback the timestamp.
|
// Rollback the timestamp.
|
||||||
EXPECT_EQ(110, jitter.correct(10));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10));
|
||||||
EXPECT_EQ(111, jitter.correct(10 + 1));
|
EXPECT_EQ((uint32_t)111, jitter.correct(10 + 1));
|
||||||
EXPECT_EQ(111, jitter.correct(11));
|
EXPECT_EQ((uint32_t)111, jitter.correct(11));
|
||||||
|
|
||||||
// Reset for jitter again.
|
// Reset for jitter again.
|
||||||
EXPECT_EQ(111, jitter.correct(11 + 128 + 1));
|
EXPECT_EQ((uint32_t)111, jitter.correct(11 + 128 + 1));
|
||||||
EXPECT_EQ(111, jitter.correct(11));
|
EXPECT_EQ((uint32_t)111, jitter.correct(11));
|
||||||
|
|
||||||
// No jitter at edge.
|
// No jitter at edge.
|
||||||
EXPECT_EQ(111 + 128, jitter.correct(11 + 128));
|
EXPECT_EQ((uint32_t)(111 + 128), jitter.correct(11 + 128));
|
||||||
EXPECT_EQ(111 + 128 + 1, jitter.correct(11 + 128 + 1));
|
EXPECT_EQ((uint32_t)(111 + 128 + 1), jitter.correct(11 + 128 + 1));
|
||||||
EXPECT_EQ(111 + 1, jitter.correct(11 + 1));
|
EXPECT_EQ((uint32_t)(111 + 1), jitter.correct(11 + 1));
|
||||||
|
|
||||||
// Also safety to decrease the value.
|
// Also safety to decrease the value.
|
||||||
EXPECT_EQ(111, jitter.correct(11));
|
EXPECT_EQ((uint32_t)111, jitter.correct(11));
|
||||||
EXPECT_EQ(110, jitter.correct(10));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10));
|
||||||
|
|
||||||
// Try to reset to 0 base.
|
// Try to reset to 0 base.
|
||||||
EXPECT_EQ(110, jitter.correct(10 + 128 + 110));
|
EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 110));
|
||||||
EXPECT_EQ(0, jitter.correct(10 + 128));
|
EXPECT_EQ((uint32_t)0, jitter.correct(10 + 128));
|
||||||
EXPECT_EQ(0, jitter.correct(0));
|
EXPECT_EQ((uint32_t)0, jitter.correct(0));
|
||||||
|
|
||||||
// Also safety to start from zero.
|
// Also safety to start from zero.
|
||||||
EXPECT_EQ(10, jitter.correct(10));
|
EXPECT_EQ((uint32_t)10, jitter.correct(10));
|
||||||
EXPECT_EQ(11, jitter.correct(11));
|
EXPECT_EQ((uint32_t)11, jitter.correct(11));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,22 +275,22 @@ VOID TEST(ServiceStSRTTest, ReadWrite)
|
||||||
// Client send msg to server.
|
// Client send msg to server.
|
||||||
ssize_t nb_write = 0;
|
ssize_t nb_write = 0;
|
||||||
HELPER_EXPECT_SUCCESS(srt_client_socket->sendmsg((char*)content.data(), content.size(), &nb_write));
|
HELPER_EXPECT_SUCCESS(srt_client_socket->sendmsg((char*)content.data(), content.size(), &nb_write));
|
||||||
EXPECT_EQ(nb_write, content.size());
|
EXPECT_EQ((size_t)nb_write, content.size());
|
||||||
|
|
||||||
// Server recv msg from client
|
// Server recv msg from client
|
||||||
char buf[1500];
|
char buf[1500];
|
||||||
ssize_t nb_read = 0;
|
ssize_t nb_read = 0;
|
||||||
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->recvmsg(buf, sizeof(buf), &nb_read));
|
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->recvmsg(buf, sizeof(buf), &nb_read));
|
||||||
EXPECT_EQ(nb_read, content.size());
|
EXPECT_EQ((size_t)nb_read, content.size());
|
||||||
EXPECT_EQ(std::string(buf, nb_read), content);
|
EXPECT_EQ(std::string(buf, nb_read), content);
|
||||||
|
|
||||||
// Server echo msg back to client.
|
// Server echo msg back to client.
|
||||||
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->sendmsg(buf, nb_read, &nb_write));
|
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->sendmsg(buf, nb_read, &nb_write));
|
||||||
EXPECT_EQ(nb_write, content.size());
|
EXPECT_EQ((size_t)nb_write, content.size());
|
||||||
|
|
||||||
// Client recv echo msg from server.
|
// Client recv echo msg from server.
|
||||||
HELPER_EXPECT_SUCCESS(srt_client_socket->recvmsg(buf, sizeof(buf), &nb_read));
|
HELPER_EXPECT_SUCCESS(srt_client_socket->recvmsg(buf, sizeof(buf), &nb_read));
|
||||||
EXPECT_EQ(nb_read, content.size());
|
EXPECT_EQ((size_t)nb_read, content.size());
|
||||||
EXPECT_EQ(std::string(buf, nb_read), content);
|
EXPECT_EQ(std::string(buf, nb_read), content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue