diff --git a/trunk/src/app/srs_app_mpegts_udp.cpp b/trunk/src/app/srs_app_mpegts_udp.cpp index 564d50ebe..c84c052ac 100644 --- a/trunk/src/app/srs_app_mpegts_udp.cpp +++ b/trunk/src/app/srs_app_mpegts_udp.cpp @@ -36,6 +36,8 @@ using namespace std; #include #include #include +#include +#include #ifdef SRS_AUTO_STREAM_CASTER @@ -72,6 +74,39 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) // append to buffer. buffer->append(buf, nb_buf); + srs_info("udp: got %s:%d packet %d/%d bytes", + peer_ip.c_str(), peer_port, nb_buf, buffer->length()); + + // collect nMB data to parse in a time. + // TODO: FIXME: comment the following for release. + //if (buffer->length() < 3 * 1024 * 1024) return ret; + // TODO: FIXME: remove the debug to file. +#if 0 + SrsFileWriter fw; + if ((ret = fw.open("latest.ts")) != ERROR_SUCCESS) { + return ret; + } + if ((ret = fw.write(buffer->bytes(), buffer->length(), NULL)) != ERROR_SUCCESS) { + return ret; + } + fw.close(); +#endif +#if 0 + SrsFileReader fr; + if ((ret = fr.open("latest.ts")) != ERROR_SUCCESS) { + return ret; + } + buffer->erase(buffer->length()); + int nb_fbuf = fr.filesize(); + char* fbuf = new char[nb_fbuf]; + SrsAutoFree(char, fbuf); + if ((ret = fr.read(fbuf, nb_fbuf, NULL)) != ERROR_SUCCESS) { + return ret; + } + fr.close(); + buffer->append(fbuf, nb_fbuf); +#endif + // find the sync byte of mpegts. char* p = buffer->bytes(); for (int i = 0; i < buffer->length(); i++) { @@ -87,12 +122,10 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) // drop ts packet when size not modulus by 188 if (buffer->length() < SRS_TS_PACKET_SIZE) { - srs_info("udp: wait %s:%d packet %d/%d bytes", + srs_warn("udp: wait %s:%d packet %d/%d bytes", peer_ip.c_str(), peer_port, nb_buf, buffer->length()); return ret; } - srs_info("udp: got %s:%d packet %d/%d bytes", - peer_ip.c_str(), peer_port, nb_buf, buffer->length()); // use stream to parse ts packet. int nb_packet = buffer->length() / SRS_TS_PACKET_SIZE; @@ -122,6 +155,49 @@ int SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) int SrsMpegtsOverUdp::on_ts_message(SrsTsMessage* msg) { int ret = ERROR_SUCCESS; + + // about the bytes of msg, specified by elementary stream which indicates by PES_packet_data_byte and stream_id + // for example, when SrsTsStream of SrsTsChannel indicates stream_type is SrsTsStreamVideoMpeg4 and SrsTsStreamAudioMpeg4, + // the elementary stream can be mux in "2.11 Carriage of ISO/IEC 14496 data" in hls-mpeg-ts-iso13818-1.pdf, page 103 + // @remark, the most popular stream_id is 0xe0 for h.264 over mpegts, which indicates the stream_id is video and + // stream_number is 0, where I guess the elementary is specified in 13818-2(video part). + // because when audio stream_number is 0, the elementary is ADTS specified in 13818-7(aac part). + + // about the bytes of PES_packet_data_byte, defined in hls-mpeg-ts-iso13818-1.pdf, page 58 + // PES_packet_data_byte ¨C 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 + // Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 13818-3, the PES_packet_data_bytes shall be byte aligned to the bytes of this + // Recommendation | International Standard. The byte-order of the elementary stream shall be preserved. 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. + // + // 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. + + // about the bytes of stream_id, define in hls-mpeg-ts-iso13818-1.pdf, page 49 + // stream_id ¨C In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the + // stream_id Table 2-18. In Transport Streams, the stream_id may be set to any valid value which correctly describes the + // elementary stream type as defined in Table 2-18. In Transport Streams, the elementary stream type is specified in the + // Program Specific Information as specified in 2.4.4. + + // about the stream_id table, define in Table 2-18 ¨C Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. + // + // 110x xxxx + // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC + // 14496-3 audio stream number x xxxx + // ((sid >> 5) & 0x07) == SrsTsPESStreamIdAudio + // + // 1110 xxxx + // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC + // 14496-2 video stream number xxxx + // ((stream_id >> 4) & 0x0f) == SrsTsPESStreamIdVideo + + srs_trace("mpegts: got %s dts=%"PRId64", pts=%"PRId64", size=%d, us=%d, cc=%d, sid=%#x(%s-%d)", + (msg->channel->apply == SrsTsPidApplyVideo)? "Video":"Audio", msg->dts, msg->pts, msg->payload->length(), + msg->packet->payload_unit_start_indicator, msg->continuity_counter, msg->sid, + msg->is_audio()? "A":msg->is_video()? "V":"N", msg->stream_number()); + // TODO: FIXME: implements it. return ret; } diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index 781645dc7..51665d4a9 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -421,6 +421,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p) packet = p; dts = pts = 0; + sid = (SrsTsPESStreamId)0x00; continuity_counter = 0; PES_packet_length = 0; payload = new SrsSimpleBuffer(); @@ -474,6 +475,26 @@ bool SrsTsMessage::fresh() return payload->length() == 0; } +bool SrsTsMessage::is_audio() +{ + return ((sid >> 5) & 0x07) == SrsTsPESStreamIdAudio; +} + +bool SrsTsMessage::is_video() +{ + return ((sid >> 4) & 0x0f) == SrsTsPESStreamIdVideo; +} + +int SrsTsMessage::stream_number() +{ + if (is_audio()) { + return sid & 0x1f; + } else if (is_video()) { + return sid & 0x0f; + } + return -1; +} + ISrsTsHandler::ISrsTsHandler() { } @@ -945,21 +966,22 @@ int SrsTsPayloadPES::decode(SrsStream* stream, SrsTsMessage** ppmsg) // should be 1 for the fresh msg. if (msg->fresh() && !packet->payload_unit_start_indicator) { ret = ERROR_STREAM_CASTER_TS_PSE; - srs_error("ts: PES fresh packet length=%d, unit_start=%d. ret=%d", - msg->PES_packet_length, packet->payload_unit_start_indicator, ret); + srs_error("ts: PES fresh packet length=%d, us=%d, cc=%d. ret=%d", + msg->PES_packet_length, packet->payload_unit_start_indicator, packet->continuity_counter, + ret); return ret; } // check when not fresh and PES_packet_length>0, // the payload_unit_start_indicator should never be 1 when not completed. if (!msg->fresh() && msg->PES_packet_length > 0 - && packet->payload_unit_start_indicator && !msg->completed(packet->payload_unit_start_indicator) + && packet->payload_unit_start_indicator ) { ret = ERROR_STREAM_CASTER_TS_PSE; - srs_error("ts: PES packet length=%d, payload=%d, unit_start=%d. ret=%d", - msg->PES_packet_length, msg->payload->length(), - packet->payload_unit_start_indicator, ret); + srs_error("ts: PES packet length=%d, payload=%d, us=%d, cc=%d. ret=%d", + msg->PES_packet_length, msg->payload->length(), packet->payload_unit_start_indicator, + packet->continuity_counter, ret); // reparse current msg. stream->skip(stream->pos() * -1); @@ -975,7 +997,7 @@ int SrsTsPayloadPES::decode(SrsStream* stream, SrsTsMessage** ppmsg) if (msg->continuity_counter >= packet->continuity_counter && ((msg->continuity_counter + 1) & 0x0f) > packet->continuity_counter ) { - srs_warn("ts: drop PES %dB for duplicated continuity=%#x", msg->continuity_counter); + srs_warn("ts: drop PES %dB for duplicated cc=%#x", msg->continuity_counter); stream->skip(stream->size() - stream->pos()); return ret; } @@ -1037,8 +1059,10 @@ int SrsTsPayloadPES::decode(SrsStream* stream, SrsTsMessage** ppmsg) } int pos_packet = stream->pos(); - // @remark SrsTsPESStreamIdAudio and SrsTsPESStreamIdVideo is not used here. + // @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 diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp index d7c8c0abc..9fe15f64f 100644 --- a/trunk/src/kernel/srs_kernel_ts.hpp +++ b/trunk/src/kernel/srs_kernel_ts.hpp @@ -162,6 +162,7 @@ enum SrsTsStream // ISO/IEC 14496-2 Visual SrsTsStreamVideoMpeg4 = 0x10, // ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 / AMD 1 + SrsTsStreamAudioMpeg4 = 0x11, // ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets // ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC14496_sections. // ISO/IEC 13818-6 Synchronized Download Protocol @@ -188,19 +189,83 @@ struct SrsTsChannel virtual ~SrsTsChannel(); }; +/** +* the stream_id of PES payload of ts packet. +* Table 2-18 – Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. +*/ +enum SrsTsPESStreamId +{ + // program_stream_map + SrsTsPESStreamIdProgramStreamMap = 0xbc, // 0b10111100 + // private_stream_1 + SrsTsPESStreamIdPrivateStream1 = 0xbd, // 0b10111101 + // padding_stream + SrsTsPESStreamIdPaddingStream = 0xbe, // 0b10111110 + // private_stream_2 + SrsTsPESStreamIdPrivateStream2 = 0xbf, // 0b10111111 + + // 110x xxxx + // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC + // 14496-3 audio stream number x xxxx + // ((sid >> 5) & 0x07) == SrsTsPESStreamIdAudio + SrsTsPESStreamIdAudio = 0x06, // 0b110 + + // 1110 xxxx + // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC + // 14496-2 video stream number xxxx + // ((stream_id >> 4) & 0x0f) == SrsTsPESStreamIdVideo + SrsTsPESStreamIdVideo = 0x0e, // 0b1110 + + // ECM_stream + SrsTsPESStreamIdEcmStream = 0xf0, // 0b11110000 + // EMM_stream + SrsTsPESStreamIdEmmStream = 0xf1, // 0b11110001 + // DSMCC_stream + SrsTsPESStreamIdDsmccStream = 0xf2, // 0b11110010 + // 13522_stream + SrsTsPESStreamId13522Stream = 0xf3, // 0b11110011 + // H_222_1_type_A + SrsTsPESStreamIdH2221TypeA = 0xf4, // 0b11110100 + // H_222_1_type_B + SrsTsPESStreamIdH2221TypeB = 0xf5, // 0b11110101 + // H_222_1_type_C + SrsTsPESStreamIdH2221TypeC = 0xf6, // 0b11110110 + // H_222_1_type_D + SrsTsPESStreamIdH2221TypeD = 0xf7, // 0b11110111 + // H_222_1_type_E + SrsTsPESStreamIdH2221TypeE = 0xf8, // 0b11111000 + // ancillary_stream + SrsTsPESStreamIdAncillaryStream = 0xf9, // 0b11111001 + // SL_packetized_stream + SrsTsPESStreamIdSlPacketizedStream = 0xfa, // 0b11111010 + // FlexMux_stream + SrsTsPESStreamIdFlexMuxStream = 0xfb, // 0b11111011 + // reserved data stream + // 1111 1100 … 1111 1110 + // program_stream_directory + SrsTsPESStreamIdProgramStreamDirectory = 0xff, // 0b11111111 +}; + /** * the media audio/video message parsed from PES packet. */ class SrsTsMessage { -private: +public: SrsTsChannel* channel; SrsTsPacket* packet; public: + // the timestamp in 90khz int64_t dts; int64_t pts; + // the id of pes stream to indicates the payload codec. + // @remark use is_audio() and is_video() to check it, and stream_number() to finger it out. + SrsTsPESStreamId sid; + // the size of payload, 0 indicates the length() of payload. u_int16_t PES_packet_length; + // the chunk id. u_int8_t continuity_counter; + // the payload bytes. SrsSimpleBuffer* payload; public: SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p); @@ -223,6 +288,20 @@ public: * whether the message is fresh. */ virtual bool fresh(); +public: + /** + * whether the sid indicates the elementary stream audio. + */ + virtual bool is_audio(); + /** + * whether the sid indicates the elementary stream video. + */ + virtual bool is_video(); + /** + * when audio or video, get the stream number which specifies the format of stream. + * @return the stream number for audio/video; otherwise, -1. + */ + virtual int stream_number(); }; /** @@ -722,63 +801,6 @@ public: virtual int decode(SrsStream* stream, SrsTsMessage** ppmsg) = 0; }; -/** -* the stream_id of PES payload of ts packet. -* Table 2-18 – Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. -*/ -enum SrsTsPESStreamId -{ - // program_stream_map - SrsTsPESStreamIdProgramStreamMap = 0xbc, // 0b10111100 - // private_stream_1 - SrsTsPESStreamIdPrivateStream1 = 0xbd, // 0b10111101 - // padding_stream - SrsTsPESStreamIdPaddingStream = 0xbe, // 0b10111110 - // private_stream_2 - SrsTsPESStreamIdPrivateStream2 = 0xbf, // 0b10111111 - - // 110x xxxx - // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC - // 14496-3 audio stream number x xxxx - // (stream_id>>5)&0x07 == SrsTsPESStreamIdAudio - SrsTsPESStreamIdAudio = 0x06, // 0b110 - - // 1110 xxxx - // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 or ISO/IEC - // 14496-2 video stream number xxxx - // (stream_id>>4)&0x0f == SrsTsPESStreamIdVideo - SrsTsPESStreamIdVideo = 0x0e, // 0b1110 - - // ECM_stream - SrsTsPESStreamIdEcmStream = 0xf0, // 0b11110000 - // EMM_stream - SrsTsPESStreamIdEmmStream = 0xf1, // 0b11110001 - // DSMCC_stream - SrsTsPESStreamIdDsmccStream = 0xf2, // 0b11110010 - // 13522_stream - SrsTsPESStreamId13522Stream = 0xf3, // 0b11110011 - // H_222_1_type_A - SrsTsPESStreamIdH2221TypeA = 0xf4, // 0b11110100 - // H_222_1_type_B - SrsTsPESStreamIdH2221TypeB = 0xf5, // 0b11110101 - // H_222_1_type_C - SrsTsPESStreamIdH2221TypeC = 0xf6, // 0b11110110 - // H_222_1_type_D - SrsTsPESStreamIdH2221TypeD = 0xf7, // 0b11110111 - // H_222_1_type_E - SrsTsPESStreamIdH2221TypeE = 0xf8, // 0b11111000 - // ancillary_stream - SrsTsPESStreamIdAncillaryStream = 0xf9, // 0b11111001 - // SL_packetized_stream - SrsTsPESStreamIdSlPacketizedStream = 0xfa, // 0b11111010 - // FlexMux_stream - SrsTsPESStreamIdFlexMuxStream = 0xfb, // 0b11111011 - // reserved data stream - // 1111 1100 … 1111 1110 - // program_stream_directory - SrsTsPESStreamIdProgramStreamDirectory = 0xff, // 0b11111111 -}; - /** * the PES payload of ts packet. * 2.4.3.6 PES packet, hls-mpeg-ts-iso13818-1.pdf, page 49