From 9c81a0e1bdc367e9556a70310d077f77103a2283 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 5 Oct 2022 22:33:12 +0800 Subject: [PATCH] UTest: Fix utest warnings. --- trunk/src/app/srs_app_config.cpp | 17 +- trunk/src/app/srs_app_st.hpp | 2 +- trunk/src/app/srs_app_tencentcloud.cpp | 2 +- trunk/src/kernel/srs_kernel_error.cpp | 5 + trunk/src/kernel/srs_kernel_ts.cpp | 893 +++++++++++++------------ trunk/src/kernel/srs_kernel_ts.hpp | 110 +-- trunk/src/utest/srs_utest_rtc.cpp | 106 +-- trunk/src/utest/srs_utest_srt.cpp | 8 +- 8 files changed, 593 insertions(+), 550 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 4fd02e4a6..caa5d567b 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -7246,20 +7246,11 @@ string SrsConfig::get_https_api_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 testcase. - string DEFAULT = ""; -#else - static string DEFAULT = ""; -#endif - + // We should not use static default, because we need to reset for different use scenarios. + string DEFAULT = "1990"; // 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()) { - DEFAULT = get_https_stream_listen(); - } else { - DEFAULT = "1990"; - } + if (get_http_api_listen() == get_http_stream_listen()) { + DEFAULT = get_https_stream_listen(); } SrsConfDirective* conf = get_https_api(); diff --git a/trunk/src/app/srs_app_st.hpp b/trunk/src/app/srs_app_st.hpp index 536083a81..3c3a290cd 100644 --- a/trunk/src/app/srs_app_st.hpp +++ b/trunk/src/app/srs_app_st.hpp @@ -172,7 +172,7 @@ private: public: SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h); SrsFastCoroutine(std::string n, ISrsCoroutineHandler* h, SrsContextId cid); - ~SrsFastCoroutine(); + virtual ~SrsFastCoroutine(); public: void set_stack_size(int v); public: diff --git a/trunk/src/app/srs_app_tencentcloud.cpp b/trunk/src/app/srs_app_tencentcloud.cpp index 52053089e..961778cc4 100644 --- a/trunk/src/app/srs_app_tencentcloud.cpp +++ b/trunk/src/app/srs_app_tencentcloud.cpp @@ -2047,7 +2047,7 @@ std::string SrsApmSpan::text_propagator() // 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. 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); } diff --git a/trunk/src/kernel/srs_kernel_error.cpp b/trunk/src/kernel/srs_kernel_error.cpp index 545e301ae..8e33e07e8 100644 --- a/trunk/src/kernel/srs_kernel_error.cpp +++ b/trunk/src/kernel/srs_kernel_error.cpp @@ -91,6 +91,11 @@ std::string SrsCplxError::summary() { if (_summary.empty()) { stringstream ss; + ss << "code=" << code; + + string code_str = srs_error_code_str(this); + if (!code_str.empty()) ss << "(" << code_str << ")"; + SrsCplxError* next = this; while (next) { ss << " : " << next->msg; diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index cb26fe129..fb10356db 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -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,415 +1286,314 @@ 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); + + // 6B fixed header. + if (!stream->require(6)) { + return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE"); } - - // 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; + // 3B + packet_start_code_prefix = stream->read_3bytes(); + // 1B + stream_id = stream->read_1bytes(); + // 2B + PES_packet_length = stream->read_2bytes(); + + // check the packet start prefix. + packet_start_code_prefix &= 0xFFFFFF; + if (packet_start_code_prefix != 0x01) { + return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES start code failed, expect=0x01, actual=%#x", packet_start_code_prefix); } - - // 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; + int pos_packet = stream->pos(); + + // @remark the sid indicates the elementary stream format. + // the SrsTsPESStreamIdAudio and SrsTsPESStreamIdVideo is start by 0b110 or 0b1110 + SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id; + 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"); } - - // 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; + // 1B + 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; + PES_scrambling_control = (oocv >> 4) & 0x03; + PES_priority = (oocv >> 3) & 0x01; + 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"); } - } - 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"); + + // 5B + if (PTS_DTS_flags == 0x2) { + if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) { + return srs_error_wrap(err, "dts/pts"); + } + dts = pts; } - } - - // 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"); + + // 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); + } + } + + // 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 - packet_start_code_prefix = stream->read_3bytes(); + if (ES_rate_flag) { + ES_rate = stream->read_3bytes(); + + ES_rate = ES_rate >> 1; + ES_rate &= 0x3FFFFF; + } + // 1B - stream_id = stream->read_1bytes(); + 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 - PES_packet_length = stream->read_2bytes(); - - // check the packet start prefix. - packet_start_code_prefix &= 0xFFFFFF; - if (packet_start_code_prefix != 0x01) { - return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PES start code failed, expect=0x01, actual=%#x", packet_start_code_prefix); - } - int pos_packet = stream->pos(); - - // @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 - && 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 - 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; - PES_scrambling_control = (oocv >> 4) & 0x03; - PES_priority = (oocv >> 3) & 0x01; - 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 (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)) { - 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 - if (PTS_DTS_flags == 0x2) { - if ((err = decode_33bits_dts_pts(stream, &pts)) != srs_success) { - return srs_error_wrap(err, "dts/pts"); - } - dts = pts; - - // update the dts and pts of message. - msg->dts = dts; - msg->pts = pts; + + // 16B + if (PES_private_data_flag) { + PES_private_data.resize(16); + stream->read_bytes(&PES_private_data[0], 16); } - - // 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); + + // (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); } - - // 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 + // 2B + if (program_packet_sequence_counter_flag) { + program_packet_sequence_counter = stream->read_1bytes(); + program_packet_sequence_counter &= 0x7f; - // 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; + original_stuff_length = stream->read_1bytes(); + MPEG1_MPEG2_identifier = (original_stuff_length >> 6) & 0x01; + original_stuff_length &= 0x3f; } - - // 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(); + 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; } - - // 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)) { - return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE ext payload"); - } - - // 16B - if (PES_private_data_flag) { - PES_private_data.resize(16); - 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); - } - } - - // 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); + + // (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); } } - - // 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"); + // 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); + } - // 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 - // 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); + // 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. + // + // 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); } - - // 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; - + PES_header_data_length = 0; SrsTsPESStreamId sid = (SrsTsPESStreamId)stream_id; - + if (sid != SrsTsPESStreamIdProgramStreamMap && sid != SrsTsPESStreamIdPaddingStream && sid != SrsTsPESStreamIdPrivateStream2 @@ -1712,7 +1606,7 @@ int SrsTsPayloadPES::size() sz += 6; sz += 3; PES_header_data_length = sz; - + sz += (PTS_DTS_flags == 0x2)? 5:0; sz += (PTS_DTS_flags == 0x3)? 10:0; sz += ESCR_flag? 6:0; @@ -1733,9 +1627,9 @@ int SrsTsPayloadPES::size() // LCOV_EXCL_STOP } PES_header_data_length = sz - PES_header_data_length; - + sz += nb_stuffings; - + // packet bytes } else if (sid == SrsTsPESStreamIdProgramStreamMap || sid == SrsTsPESStreamIdPrivateStream2 @@ -1744,24 +1638,24 @@ int SrsTsPayloadPES::size() || sid == SrsTsPESStreamIdProgramStreamDirectory || sid == SrsTsPESStreamIdDsmccStream || sid == SrsTsPESStreamIdH2221TypeE - ) { + ) { // packet bytes } else { // nb_drop } - + return sz; } -srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) +srs_error_t SrsMpegPES::encode(SrsBuffer* stream) { srs_error_t err = srs_success; - + // 6B fixed header. if (!stream->require(6)) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: mux PSE"); } - + // 3B stream->write_3bytes(packet_start_code_prefix); // 1B @@ -1775,13 +1669,13 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) pplv = (pplv > 0xFFFF)? 0 : pplv; } stream->write_2bytes(pplv); - + // check the packet start prefix. packet_start_code_prefix &= 0xFFFFFF; if (packet_start_code_prefix != 0x01) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: mux PSE start code failed, expect=0x01, actual=%#x", packet_start_code_prefix); } - + // 3B flags. if (!stream->require(3)) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: mux PSE flags"); @@ -1805,7 +1699,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) stream->write_1bytes(pefv); // 1B stream->write_1bytes(PES_header_data_length); - + // check required together. int nb_required = 0; nb_required += (PTS_DTS_flags == 0x2)? 5:0; @@ -1819,14 +1713,14 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) if (!stream->require(nb_required)) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: mux PSE payload"); } - + // 5B if (PTS_DTS_flags == 0x2) { if ((err = encode_33bits_dts_pts(stream, 0x02, pts)) != srs_success) { return srs_error_wrap(err, "dts/pts"); } } - + // 10B if (PTS_DTS_flags == 0x3) { if ((err = encode_33bits_dts_pts(stream, 0x03, pts)) != srs_success) { @@ -1835,7 +1729,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) if ((err = encode_33bits_dts_pts(stream, 0x01, 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); @@ -1844,37 +1738,37 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) // Ignore coverage bellow, for we don't use them in HLS. // LCOV_EXCL_START - + // 6B if (ESCR_flag) { stream->skip(6); srs_warn("ts: demux PES, ignore the escr."); } - + // 3B if (ES_rate_flag) { stream->skip(3); srs_warn("ts: demux PES, ignore the ES_rate."); } - + // 1B if (DSM_trick_mode_flag) { stream->skip(1); srs_warn("ts: demux PES, ignore the DSM_trick_mode."); } - + // 1B if (additional_copy_info_flag) { stream->skip(1); srs_warn("ts: demux PES, ignore the additional_copy_info."); } - + // 2B if (PES_CRC_flag) { stream->skip(2); srs_warn("ts: demux PES, ignore the PES_CRC."); } - + // 1B if (PES_extension_flag) { int8_t efv = PES_extension_flag_2 & 0x01; @@ -1884,7 +1778,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) efv |= (P_STD_buffer_flag << 4) & 0x10; efv |= (const1_value0 << 1) & 0xE0; stream->write_1bytes(efv); - + nb_required = 0; nb_required += PES_private_data_flag? 16:0; nb_required += pack_header_field_flag ? 1 + pack_field.size() : 0; // 1+x bytes. @@ -1897,7 +1791,7 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) stream->skip(nb_required); srs_warn("ts: demux PES, ignore the PES_extension."); } - + // stuffing_byte if (nb_stuffings) { stream->skip(nb_stuffings); @@ -1905,18 +1799,18 @@ srs_error_t SrsTsPayloadPES::encode(SrsBuffer* stream) } // LCOV_EXCL_STOP - + 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; - + if (!stream->require(5)) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE dts/pts"); } - + // decode the 33bits schema. // ===========1B // 4bits const maybe '0001', '0010' or '0011'. @@ -1932,7 +1826,7 @@ srs_error_t SrsTsPayloadPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* p return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE dts/pts 30-32"); } dts_pts_30_32 = (dts_pts_30_32 >> 1) & 0x07; - + // ===========2B // 15bits DTS/PTS [29..15] // 1bit const '1' @@ -1941,7 +1835,7 @@ srs_error_t SrsTsPayloadPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* p return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE dts/pts 15-29"); } dts_pts_15_29 = (dts_pts_15_29 >> 1) & 0x7fff; - + // ===========2B // 15bits DTS/PTS [14..0] // 1bit const '1' @@ -1950,43 +1844,184 @@ srs_error_t SrsTsPayloadPES::decode_33bits_dts_pts(SrsBuffer* stream, int64_t* p return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: demux PSE dts/pts 0-14"); } dts_pts_0_14 = (dts_pts_0_14 >> 1) & 0x7fff; - + int64_t v = 0x00; v |= (dts_pts_30_32 << 30) & 0x1c0000000LL; v |= (dts_pts_15_29 << 15) & 0x3fff8000LL; v |= dts_pts_0_14 & 0x7fff; *pv = v; - + 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; - + if (!stream->require(5)) { return srs_error_new(ERROR_STREAM_CASTER_TS_PSE, "ts: mux PSE dts/pts"); } - + char* p = stream->data() + stream->pos(); stream->skip(5); - + int32_t val = 0; - + val = int32_t(fb << 4 | (((v >> 30) & 0x07) << 1) | 1); *p++ = val; - + val = int32_t((((v >> 15) & 0x7fff) << 1) | 1); *p++ = (val >> 8); *p++ = val; - + val = int32_t((((v) & 0x7fff) << 1) | 1); *p++ = (val >> 8); *p++ = val; - + 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; diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp index d986c2ab9..8efcb9fcc 100644 --- a/trunk/src/kernel/srs_kernel_ts.hpp +++ b/trunk/src/kernel/srs_kernel_ts.hpp @@ -28,6 +28,7 @@ class SrsTsPayload; class SrsTsMessage; class SrsTsPacket; class SrsTsContext; +class SrsPsPacket; // Transport Stream packets are 188 bytes in length. #define SRS_TS_PACKET_SIZE 188 @@ -90,14 +91,14 @@ enum SrsTsPidApply { SrsTsPidApplyReserved = 0, // TSPidTypeReserved, nothing parsed, used reserved. - SrsTsPidApplyPAT, // Program associtate table - SrsTsPidApplyPMT, // Program map table. + SrsTsPidApplyPAT, // Program associtate table for TS. + SrsTsPidApplyPMT, // Program map table for TS. SrsTsPidApplyVideo, // for video 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 { // ITU-T | ISO/IEC Reserved @@ -215,9 +216,7 @@ enum SrsTsPESStreamId class SrsTsMessage { public: - // For decoder only, - // the ts messgae does not use them, - // for user to get the channel and packet. + // For decoder only, the ts message does not use them, for user to get the channel and packet. SrsTsChannel* channel; SrsTsPacket* packet; public: @@ -294,12 +293,10 @@ private: // When PAT and PMT writen, the context is ready. // @see https://github.com/ossrs/srs/issues/834 bool ready; -// codec private: std::map pids; bool pure_audio; int8_t sync_byte; - // encoder private: // when any codec changed, write the PAT/PMT. SrsVideoCodecId vcodec; @@ -309,37 +306,33 @@ public: virtual ~SrsTsContext(); public: // 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(); // When PMT table parsed, we know some info about stream. virtual void on_pmt_parsed(); // Reset the context for a new ts segment start. virtual void reset(); - // codec public: // Get the pid apply, the parsed pid. // @return the apply channel; NULL for invalid. virtual SrsTsChannel* get(int pid); // Set the pid apply, the parsed pid. virtual void set(int pid, SrsTsPidApply apply_pid, SrsTsStream stream = SrsTsStreamReserved); - // decode methods public: - // The stream contains only one ts packet. - // @param handler the ts message handler to process the msg. - // @remark we will consume all bytes in stream. + // Feed with ts packets, decode as ts message, callback handler if got one ts message. + // A ts video message can be decoded to NALUs by SrsRawH264Stream::annexb_demux. + // 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); - // encode methods public: - // Write the PES packet, the video/audio stream. - // @param msg the video/audio msg to write to ts. - // @param vc the video codec, write the PAT/PMT table when changed. - // @param ac the audio codec, write the PAT/PMT table when changed. + // Encode ts video/audio messages to the PES packets, as PES stream. + // @param msg The video/audio msg to write to ts. + // A ts video message is a frame with one or more NALUs, generally encoded by SrsTsMessageCache.cache_video. + // 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); -// 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: 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); @@ -741,9 +734,8 @@ public: virtual srs_error_t encode(SrsBuffer* stream) = 0; }; -// The PES payload of ts packet. -// 2.4.3.6 PES packet, hls-mpeg-ts-iso13818-1.pdf, page 49 -class SrsTsPayloadPES : public SrsTsPayload +// Common MPEG PES packet for both TS and PS. +class SrsMpegPES { public: // 3B @@ -763,7 +755,7 @@ public: // field. A value of 0 indicates that the PES packet length is neither specified nor bounded and is allowed only in // PES packets whose payload consists of bytes from a video elementary stream contained in Transport Stream packets. uint16_t PES_packet_length; //16bits - + // 1B // 2bits const '10' int8_t const2bits; //2bits @@ -790,7 +782,7 @@ public: // This is a 1-bit field. When set to '1' the contents of the associated PES packet payload is an original. // When set to '0' it indicates that the contents of the associated PES packet payload is a copy. int8_t original_or_copy; //1bit - + // 1B // This is a 2-bit field. When the PTS_DTS_flags field is set to '10', the PTS fields shall be present in // the PES packet header. When the PTS_DTS_flags field is set to '11', both the PTS fields and DTS fields shall be present @@ -815,13 +807,13 @@ public: // A 1-bit flag, which when set to '1' indicates that an extension field exists in this PES packet // header. When set to '0' it indicates that this field is not present. int8_t PES_extension_flag; //1bit - + // 1B // An 8-bit field specifying the total number of bytes occupied by the optional fields and any // stuffing bytes contained in this PES packet header. The presence of optional fields is indicated in the byte that precedes // the PES_header_data_length field. uint8_t PES_header_data_length; //8bits - + // 5B // Presentation times shall be related to decoding times as follows: The PTS is a 33-bit // number coded in three separate fields. It indicates the time of presentation, tp n (k), in the system target decoder of a @@ -839,7 +831,7 @@ public: // 15bits PTS [14..0] // 1bit const '1' int64_t pts; // 33bits - + // 5B // The DTS is a 33-bit number coded in three separate fields. It indicates the decoding time, // td n (j), in the system target decoder of an access unit j of elementary stream n. The value of DTS is specified in units of @@ -855,7 +847,7 @@ public: // 15bits DTS [14..0] // 1bit const '1' int64_t dts; // 33bits - + // 6B // The elementary stream clock reference is a 42-bit field coded in two parts. The first // part, ESCR_base, is a 33-bit field whose value is given by ESCR_base(i), as given in equation 2-14. The second part, @@ -873,7 +865,7 @@ public: // 1bit const '1' int64_t ESCR_base; //33bits int16_t ESCR_extension; //9bits - + // 3B // The ES_rate field is a 22-bit unsigned integer specifying the rate at which the // system target decoder receives bytes of the PES packet in the case of a PES stream. The ES_rate is valid in the PES @@ -885,24 +877,24 @@ public: // 22bits ES_rate // 1bit const '1' int32_t ES_rate; //22bits - + // 1B // A 3-bit field that indicates which trick mode is applied to the associated video stream. In cases of // other types of elementary streams, the meanings of this field and those defined by the following five bits are undefined. // For the definition of trick_mode status, refer to the trick mode section of 2.4.2.3. int8_t trick_mode_control; //3bits int8_t trick_mode_value; //5bits - + // 1B // 1bit const '1' // This 7-bit field contains private data relating to copyright information. int8_t additional_copy_info; //7bits - + // 2B // The previous_PES_packet_CRC is a 16-bit field that contains the CRC value that yields // a zero output of the 16 registers in the decoder similar to the one defined in Annex A, int16_t previous_PES_packet_CRC; //16bits - + // 1B // A 1-bit flag which when set to '1' indicates that the PES packet header contains private data. // When set to a value of '0' it indicates that private data is not present in the PES header. @@ -926,15 +918,15 @@ public: // field and associated fields. When set to a value of '0' this indicates that the PES_extension_field_length field and any // associated fields are not present. int8_t PES_extension_flag_2; //1bit - + // 16B // This is a 16-byte field which contains private data. This data, combined with the fields before and // after, shall not emulate the packet_start_code_prefix (0x000001). std::vector PES_private_data; //128bits - + // (1+x)B std::vector pack_field; //[pack_field_length] bytes - + // 2B // 1bit const '1' // The program_packet_sequence_counter field is a 7-bit field. It is an optional @@ -952,7 +944,7 @@ public: // This 6-bit field specifies the number of stuffing bytes used in the original ITU-T // Rec. H.222.0 | ISO/IEC 13818-1 PES packet header or in the original ISO/IEC 11172-1 packet header. int8_t original_stuff_length; //6bits - + // 2B // 2bits const '01' // The P-STD_buffer_scale is a 1-bit field, the meaning of which is only defined if this PES packet @@ -966,17 +958,17 @@ public: // P-STD_buffer_scale has the value '0', then the P-STD_buffer_size measures the buffer size in units of 128 bytes. If // P-STD_buffer_scale has the value '1', then the P-STD_buffer_size measures the buffer size in units of 1024 bytes. int16_t P_STD_buffer_size; //13bits - + // (1+x)B // 1bit const '1' std::vector PES_extension_field; //[PES_extension_field_length] bytes - + // NB // This is a fixed 8-bit value equal to '1111 1111' that can be inserted by the encoder, for example to meet // the requirements of the channel. It is discarded by the decoder. No more than 32 stuffing bytes shall be present in one // PES packet header. int nb_stuffings; - + // NB // PES_packet_data_bytes shall be contiguous bytes of data from the elementary stream // indicated by the packet's stream_id or PID. When the elementary stream data conforms to ITU-T @@ -989,15 +981,19 @@ public: // In the case of a private_stream_1, private_stream_2, ECM_stream, or EMM_stream, the contents of the // PES_packet_data_byte field are user definable and will not be specified by ITU-T | ISO/IEC in the future. int nb_bytes; - + // NB // This is a fixed 8-bit value equal to '1111 1111'. It is discarded by the decoder. int nb_paddings; public: - SrsTsPayloadPES(SrsTsPacket* p); - virtual ~SrsTsPayloadPES(); + // Whether contains payload to dump to message. + bool has_payload_; + int nb_payload_; public: - virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg); + SrsMpegPES(); + virtual ~SrsMpegPES(); +public: + virtual srs_error_t decode(SrsBuffer* stream); public: virtual int size(); virtual srs_error_t encode(SrsBuffer* stream); @@ -1006,6 +1002,22 @@ private: 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: + SrsTsPayloadPES(SrsTsPacket* p); + virtual ~SrsTsPayloadPES(); +public: + virtual srs_error_t decode(SrsBuffer* stream, SrsTsMessage** ppmsg); +public: + virtual int size(); + virtual srs_error_t encode(SrsBuffer* stream); +}; + // The PSI payload of ts packet. // 2.4.4 Program specific information, hls-mpeg-ts-iso13818-1.pdf, page 59 class SrsTsPayloadPSI : public SrsTsPayload diff --git a/trunk/src/utest/srs_utest_rtc.cpp b/trunk/src/utest/srs_utest_rtc.cpp index 7c4be7b90..42f8993c1 100644 --- a/trunk/src/utest/srs_utest_rtc.cpp +++ b/trunk/src/utest/srs_utest_rtc.cpp @@ -765,7 +765,7 @@ VOID TEST(KernelRTCTest, NACKEncode) vector before = rtcp_nack_encode.get_lost_sns(); vector after = rtcp_nack_decode.get_lost_sns(); 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)); } } @@ -932,11 +932,11 @@ VOID TEST(KernelRTCTest, Ntp) // Cover systime to ntp 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 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; 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_); - 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); // Starts from the base. - EXPECT_EQ(1000, jitter.correct(0)); + EXPECT_EQ((uint32_t)1000, jitter.correct(0)); // Start from here. - EXPECT_EQ(1010, jitter.correct(10)); - EXPECT_EQ(1010, jitter.correct(10)); - EXPECT_EQ(1020, jitter.correct(20)); + EXPECT_EQ((uint32_t)1010, jitter.correct(10)); + EXPECT_EQ((uint32_t)1010, jitter.correct(10)); + EXPECT_EQ((uint32_t)1020, jitter.correct(20)); // Reset the base for jitter detected. - EXPECT_EQ(1020, jitter.correct(20 + 90*3*1000 + 1)); - EXPECT_EQ(1019, jitter.correct(20 + 90*3*1000)); - EXPECT_EQ(1021, jitter.correct(20 + 90*3*1000 + 2)); - EXPECT_EQ(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)); + EXPECT_EQ((uint32_t)1019, jitter.correct(20 + 90*3*1000)); + EXPECT_EQ((uint32_t)1021, jitter.correct(20 + 90*3*1000 + 2)); + EXPECT_EQ((uint32_t)1019, jitter.correct(20 + 90*3*1000)); + EXPECT_EQ((uint32_t)1020, jitter.correct(20 + 90*3*1000 + 1)); // Rollback the timestamp. - EXPECT_EQ(1020, jitter.correct(20)); - EXPECT_EQ(1021, jitter.correct(20 + 1)); - EXPECT_EQ(1021, jitter.correct(21)); + EXPECT_EQ((uint32_t)1020, jitter.correct(20)); + EXPECT_EQ((uint32_t)1021, jitter.correct(20 + 1)); + EXPECT_EQ((uint32_t)1021, jitter.correct(21)); // Reset for jitter again. - EXPECT_EQ(1021, jitter.correct(21 + 90*3*1000 + 1)); - EXPECT_EQ(1021, jitter.correct(21)); + EXPECT_EQ((uint32_t)1021, jitter.correct(21 + 90*3*1000 + 1)); + EXPECT_EQ((uint32_t)1021, jitter.correct(21)); // No jitter at edge. - EXPECT_EQ(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(1021 + 1, jitter.correct(21 + 1)); + EXPECT_EQ((uint32_t)(1021 + 90*3*1000), jitter.correct(21 + 90*3*1000)); + EXPECT_EQ((uint32_t)(1021 + 90*3*1000 + 1), jitter.correct(21 + 90*3*1000 + 1)); + EXPECT_EQ((uint32_t)(1021 + 1), jitter.correct(21 + 1)); // Also safety to decrease the value. - EXPECT_EQ(1021, jitter.correct(21)); - EXPECT_EQ(1010, jitter.correct(10)); + EXPECT_EQ((uint32_t)1021, jitter.correct(21)); + EXPECT_EQ((uint32_t)1010, jitter.correct(10)); // Try to reset to 0 base. - EXPECT_EQ(1010, jitter.correct(10 + 90*3*1000 + 1010)); - EXPECT_EQ(0, jitter.correct(10 + 90*3*1000)); - EXPECT_EQ(0, jitter.correct(0)); + EXPECT_EQ((uint32_t)1010, jitter.correct(10 + 90*3*1000 + 1010)); + EXPECT_EQ((uint32_t)0, jitter.correct(10 + 90*3*1000)); + EXPECT_EQ((uint32_t)0, jitter.correct(0)); // Also safety to start from zero. - EXPECT_EQ(10, jitter.correct(10)); - EXPECT_EQ(11, jitter.correct(11)); + EXPECT_EQ((uint32_t)10, jitter.correct(10)); + EXPECT_EQ((uint32_t)11, jitter.correct(11)); } VOID TEST(KernelRTCTest, JitterSequence) @@ -1326,45 +1326,45 @@ VOID TEST(KernelRTCTest, JitterSequence) SrsRtcSeqJitter jitter(100); // Starts from the base. - EXPECT_EQ(100, jitter.correct(0)); + EXPECT_EQ((uint32_t)100, jitter.correct(0)); // Normal without jitter. - EXPECT_EQ(101, jitter.correct(1)); - EXPECT_EQ(102, jitter.correct(2)); - EXPECT_EQ(101, jitter.correct(1)); - EXPECT_EQ(103, jitter.correct(3)); - EXPECT_EQ(110, jitter.correct(10)); + EXPECT_EQ((uint32_t)101, jitter.correct(1)); + EXPECT_EQ((uint32_t)102, jitter.correct(2)); + EXPECT_EQ((uint32_t)101, jitter.correct(1)); + EXPECT_EQ((uint32_t)103, jitter.correct(3)); + EXPECT_EQ((uint32_t)110, jitter.correct(10)); // Reset the base for jitter detected. - EXPECT_EQ(110, jitter.correct(10 + 128 + 1)); - EXPECT_EQ(109, jitter.correct(10 + 128)); - EXPECT_EQ(110, jitter.correct(10 + 128 + 1)); + EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 1)); + EXPECT_EQ((uint32_t)109, jitter.correct(10 + 128)); + EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 1)); // Rollback the timestamp. - EXPECT_EQ(110, jitter.correct(10)); - EXPECT_EQ(111, jitter.correct(10 + 1)); - EXPECT_EQ(111, jitter.correct(11)); + EXPECT_EQ((uint32_t)110, jitter.correct(10)); + EXPECT_EQ((uint32_t)111, jitter.correct(10 + 1)); + EXPECT_EQ((uint32_t)111, jitter.correct(11)); // Reset for jitter again. - EXPECT_EQ(111, jitter.correct(11 + 128 + 1)); - EXPECT_EQ(111, jitter.correct(11)); + EXPECT_EQ((uint32_t)111, jitter.correct(11 + 128 + 1)); + EXPECT_EQ((uint32_t)111, jitter.correct(11)); // No jitter at edge. - EXPECT_EQ(111 + 128, jitter.correct(11 + 128)); - EXPECT_EQ(111 + 128 + 1, jitter.correct(11 + 128 + 1)); - EXPECT_EQ(111 + 1, jitter.correct(11 + 1)); + EXPECT_EQ((uint32_t)(111 + 128), jitter.correct(11 + 128)); + EXPECT_EQ((uint32_t)(111 + 128 + 1), jitter.correct(11 + 128 + 1)); + EXPECT_EQ((uint32_t)(111 + 1), jitter.correct(11 + 1)); // Also safety to decrease the value. - EXPECT_EQ(111, jitter.correct(11)); - EXPECT_EQ(110, jitter.correct(10)); + EXPECT_EQ((uint32_t)111, jitter.correct(11)); + EXPECT_EQ((uint32_t)110, jitter.correct(10)); // Try to reset to 0 base. - EXPECT_EQ(110, jitter.correct(10 + 128 + 110)); - EXPECT_EQ(0, jitter.correct(10 + 128)); - EXPECT_EQ(0, jitter.correct(0)); + EXPECT_EQ((uint32_t)110, jitter.correct(10 + 128 + 110)); + EXPECT_EQ((uint32_t)0, jitter.correct(10 + 128)); + EXPECT_EQ((uint32_t)0, jitter.correct(0)); // Also safety to start from zero. - EXPECT_EQ(10, jitter.correct(10)); - EXPECT_EQ(11, jitter.correct(11)); + EXPECT_EQ((uint32_t)10, jitter.correct(10)); + EXPECT_EQ((uint32_t)11, jitter.correct(11)); } diff --git a/trunk/src/utest/srs_utest_srt.cpp b/trunk/src/utest/srs_utest_srt.cpp index b5ae0e9e9..1b662af06 100644 --- a/trunk/src/utest/srs_utest_srt.cpp +++ b/trunk/src/utest/srs_utest_srt.cpp @@ -275,22 +275,22 @@ VOID TEST(ServiceStSRTTest, ReadWrite) // Client send msg to server. ssize_t nb_write = 0; 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 char buf[1500]; ssize_t nb_read = 0; 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); // Server echo msg back to client. 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. 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); }