From 29ac4c724b2944453ea01d265624abeed766f69b Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 7 Apr 2015 17:55:45 +0800 Subject: [PATCH 1/3] change default log tank to file. --- trunk/src/app/srs_app_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index c24fa0958..f9ef7390f 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -3093,7 +3093,7 @@ bool SrsConfig::get_log_tank_file() SrsConfDirective* conf = root->get("srs_log_tank"); if (!conf || conf->arg0().empty()) { - return false; + return true; } return conf->arg0() != SRS_CONF_DEFAULT_LOG_TANK_CONSOLE; From 546be09219d1b9f1eb5707dd66b91745adec1a34 Mon Sep 17 00:00:00 2001 From: winlin Date: Wed, 8 Apr 2015 16:52:43 +0800 Subject: [PATCH 2/3] fix #375, fix hls bug, keep cc continous between ts files. 2.0.159. --- README.md | 1 + trunk/src/app/srs_app_hls.cpp | 18 +++++++-- trunk/src/app/srs_app_hls.hpp | 8 +++- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_ts.cpp | 59 ++++++++++++++++++++---------- trunk/src/kernel/srs_kernel_ts.hpp | 11 +++++- 6 files changed, 72 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index d1ededdc0..91d4f1f28 100755 --- a/README.md +++ b/README.md @@ -562,6 +562,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* v2.0, 2015-04-08, for [#375](https://github.com/winlinvip/simple-rtmp-server/issues/375), fix hls bug, keep cc continous between ts files. 2.0.159. * v2.0, 2015-04-04, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite annexb mux for ts, refer to apple sample. 2.0.157. * v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156. * v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155. diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 74031ee2a..559966e79 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -138,14 +138,14 @@ string SrsHlsCacheWriter::cache() return data; } -SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc) +SrsHlsSegment::SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc) { duration = 0; sequence_no = 0; segment_start_dts = 0; is_sequence_header = false; writer = new SrsHlsCacheWriter(write_cache, write_file); - muxer = new SrsTSMuxer(writer, ac, vc); + muxer = new SrsTSMuxer(writer, c, ac, vc); } SrsHlsSegment::~SrsHlsSegment() @@ -236,6 +236,7 @@ SrsHlsMuxer::SrsHlsMuxer() should_write_cache = false; should_write_file = true; async = new SrsDvrAsyncCallThread(); + context = new SrsTsContext(); } SrsHlsMuxer::~SrsHlsMuxer() @@ -250,6 +251,7 @@ SrsHlsMuxer::~SrsHlsMuxer() srs_freep(current); srs_freep(req); srs_freep(async); + srs_freep(context); } int SrsHlsMuxer::sequence_no() @@ -269,11 +271,21 @@ double SrsHlsMuxer::duration() double SrsHlsMuxer::deviation() { + // no floor, no deviation. + if (!hls_ts_floor) { + return 0; + } + return hls_fragment_deviation; } int SrsHlsMuxer::absolute_deviation() { + // no floor, no deviation. + if (!hls_ts_floor) { + return 0; + } + // accept the floor ts for the first piece. int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); return (int)(accept_floor_ts - (floor_ts - 1)); @@ -391,7 +403,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) } // new segment. - current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec, default_vcodec); + current = new SrsHlsSegment(context, should_write_cache, should_write_file, default_acodec, default_vcodec); current->sequence_no = _sequence_no++; current->segment_start_dts = segment_start_dts; diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 03f3e0cfc..485368699 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -56,6 +56,7 @@ class SrsTsAacJitter; class SrsTsCache; class SrsHlsSegment; class SrsTsCache; +class SrsTsContext; /** * the handler for hls event. @@ -145,7 +146,7 @@ public: // whether current segement is sequence header. bool is_sequence_header; public: - SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc); + SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc); virtual ~SrsHlsSegment(); public: /** @@ -229,6 +230,11 @@ private: * @see https://github.com/winlinvip/simple-rtmp-server/issues/301 */ SrsCodecAudio acodec; + /** + * the ts context, to keep cc continous between ts. + * @see https://github.com/winlinvip/simple-rtmp-server/issues/375 + */ + SrsTsContext* context; public: SrsHlsMuxer(); virtual ~SrsHlsMuxer(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index cdeb990e3..23e6f4dec 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 158 +#define VERSION_REVISION 159 // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index b813710ad..bc71c80d7 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -51,10 +51,10 @@ using namespace std; // the mpegts header specifed the video/audio pid. #define TS_PMT_NUMBER 1 -#define TS_PMT_PID 0x100 -#define TS_VIDEO_AVC_PID 0x101 -#define TS_AUDIO_AAC_PID 0x102 -#define TS_AUDIO_MP3_PID 0x103 +#define TS_PMT_PID 0x1001 +#define TS_VIDEO_AVC_PID 0x100 +#define TS_AUDIO_AAC_PID 0x101 +#define TS_AUDIO_MP3_PID 0x102 string srs_ts_stream2string(SrsTsStream stream) { @@ -95,6 +95,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p) continuity_counter = 0; PES_packet_length = 0; payload = new SrsSimpleBuffer(); + is_discontinuity = false; start_pts = 0; write_pcr = false; @@ -192,6 +193,12 @@ SrsTsContext::~SrsTsContext() pids.clear(); } +void SrsTsContext::reset() +{ + vcodec = SrsCodecVideoReserved; + acodec = SrsCodecAudioReserved1; +} + SrsTsChannel* SrsTsContext::get(int pid) { if (pids.find(pid) == pids.end()) { @@ -251,7 +258,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo int ret = ERROR_SUCCESS; SrsTsStream vs, as; - int16_t video_pid, audio_pid; + int16_t video_pid = 0, audio_pid = 0; switch (vc) { case SrsCodecVideoAVC: vs = SrsTsStreamVideoH264; @@ -401,9 +408,14 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p write_pcr = true; } + // it's ok to set pcr equals to dts, + // @see https://github.com/winlinvip/simple-rtmp-server/issues/311 + int64_t pcr = write_pcr? msg->dts : -1; + + // TODO: FIXME: finger it why use discontinuity of msg. pkt = SrsTsPacket::create_pes_first(this, - pid, msg->sid, channel->continuity_counter++, msg->discontinuity, - write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length() + pid, msg->sid, channel->continuity_counter++, msg->is_discontinuity, + pcr, msg->dts, msg->pts, msg->payload->length() ); } else { pkt = SrsTsPacket::create_pes_continue(this, @@ -419,7 +431,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p int nb_buf = pkt->size(); srs_assert(nb_buf < SRS_TS_PACKET_SIZE); - int left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); + int left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); int nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left; if (nb_stuffings > 0) { // set all bytes to stuffings. @@ -432,7 +444,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p nb_buf = pkt->size(); srs_assert(nb_buf < SRS_TS_PACKET_SIZE); - left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); + left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left; srs_assert(nb_stuffings == 0); } @@ -703,13 +715,18 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, pmt->section_number = 0; pmt->last_section_number = 0; pmt->program_info_length = 0; + + // use audio to carray pcr by default. + // for hls, there must be atleast one audio channel. + pmt->PCR_PID = apid; + pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); + + // if h.264 specified, use video to carry pcr. if (vs == SrsTsStreamVideoH264) { pmt->PCR_PID = vpid; pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); - } else { - pmt->PCR_PID = apid; } - pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); + pmt->CRC_32 = 0; // calc in encode. return pkt; } @@ -2604,10 +2621,10 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream) return ret; } -SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc) +SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc) { writer = w; - context = NULL; + context = c; acodec = ac; vcodec = vc; @@ -2625,10 +2642,9 @@ int SrsTSMuxer::open(string _path) path = _path; close(); - - // use context to write ts file. - srs_freep(context); - context = new SrsTsContext(); + + // reset the context for a new ts start. + context->reset(); if ((ret = writer->open(path)) != ERROR_SUCCESS) { return ret; @@ -2677,7 +2693,6 @@ int SrsTSMuxer::write_video(SrsTsMessage* video) void SrsTSMuxer::close() { - srs_freep(context); writer->close(); } @@ -2911,6 +2926,8 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) // 9, SI (SI slice) // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; + + // always append a aud nalu for each frame. video->payload->append((const char*)fresh_nalu_header, 4); video->payload->append((const char*)aud_nalu_7, 2); @@ -2973,6 +2990,7 @@ SrsTsEncoder::SrsTsEncoder() codec = new SrsAvcAacCodec(); sample = new SrsCodecSample(); cache = new SrsTsCache(); + context = new SrsTsContext(); muxer = NULL; } @@ -2982,6 +3000,7 @@ SrsTsEncoder::~SrsTsEncoder() srs_freep(sample); srs_freep(cache); srs_freep(muxer); + srs_freep(context); } int SrsTsEncoder::initialize(SrsFileWriter* fs) @@ -2999,7 +3018,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) _fs = fs; srs_freep(muxer); - muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC, SrsCodecVideoAVC); + muxer = new SrsTSMuxer(fs, context, SrsCodecAudioAAC, SrsCodecVideoAVC); if ((ret = muxer->open("")) != ERROR_SUCCESS) { return ret; diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp index a37f8f328..2d5b14887 100644 --- a/trunk/src/kernel/srs_kernel_ts.hpp +++ b/trunk/src/kernel/srs_kernel_ts.hpp @@ -47,6 +47,7 @@ class SrsTsAdaptationField; class SrsTsPayload; class SrsTsMessage; class SrsTsPacket; +class SrsTsContext; // Transport Stream packets are 188 bytes in length. #define SRS_TS_PACKET_SIZE 188 @@ -258,7 +259,7 @@ public: // generally, the video IDR(I frame, the keyframe of h.264) carray the pcr info. bool write_pcr; // whether got discontinuity ts, for example, sequence header changed. - bool discontinuity; + bool is_discontinuity; public: // the timestamp in 90khz int64_t dts; @@ -343,6 +344,11 @@ private: public: SrsTsContext(); virtual ~SrsTsContext(); +public: + /** + * reset the context for a new ts segment start. + */ + virtual void reset(); // codec public: /** @@ -1533,7 +1539,7 @@ private: SrsFileWriter* writer; std::string path; public: - SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc); + SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc); virtual ~SrsTSMuxer(); public: /** @@ -1608,6 +1614,7 @@ private: SrsCodecSample* sample; SrsTsCache* cache; SrsTSMuxer* muxer; + SrsTsContext* context; public: SrsTsEncoder(); virtual ~SrsTsEncoder(); From bd77f995bfb8761015e6e59ede48f531340d7dab Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 9 Apr 2015 12:35:17 +0800 Subject: [PATCH 3/3] ignore the unknown flv tag. --- trunk/research/librtmp/srs_ingest_rtmp.c | 6 ++++++ trunk/src/libs/srs_librtmp.cpp | 9 +++++++-- trunk/src/libs/srs_librtmp.hpp | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/trunk/research/librtmp/srs_ingest_rtmp.c b/trunk/research/librtmp/srs_ingest_rtmp.c index d4c8606cd..c0db88f91 100644 --- a/trunk/research/librtmp/srs_ingest_rtmp.c +++ b/trunk/research/librtmp/srs_ingest_rtmp.c @@ -127,6 +127,12 @@ int proxy(srs_rtmp_t irtmp, srs_rtmp_t ortmp) return ret; } + if (!srs_utils_flv_tag_is_ok(type)) { + srs_human_trace("ignore invalid flv tag=%d, dts=%d, %d bytes", type, timestamp, size); + free(data); + continue; + } + if ((ret = srs_human_print_rtmp_packet(type, timestamp, data, size)) != 0) { srs_human_trace("print packet failed. ret=%d", ret); return ret; diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index b2c623718..dffd90149 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -1973,6 +1973,11 @@ int srs_utils_parse_timestamp( return ret; } + +srs_bool srs_utils_flv_tag_is_ok(char type) +{ + return type == SRS_RTMP_TYPE_AUDIO || type == SRS_RTMP_TYPE_VIDEO || type == SRS_RTMP_TYPE_SCRIPT; +} char srs_utils_flv_video_codec_id(char* data, int size) { @@ -2324,7 +2329,7 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int ); } else if (type == SRS_RTMP_TYPE_SCRIPT) { srs_human_verbose("Data packet type=%s, time=%d, size=%d", - srs_human_flv_tag_type2string(type), timestamp, size); + srs_human_flv_tag_type2string(type), timestamp, size); int nparsed = 0; while (nparsed < size) { int nb_parsed_this = 0; @@ -2332,7 +2337,7 @@ int srs_human_print_rtmp_packet(char type, u_int32_t timestamp, char* data, int if (amf0 == NULL) { break; } - + nparsed += nb_parsed_this; char* amf0_str = NULL; diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index 744575112..aee8b7a9f 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -655,6 +655,12 @@ extern int srs_utils_parse_timestamp( u_int32_t time, char type, char* data, int size, u_int32_t* ppts ); + +/** + * whether the flv tag specified by param type is ok. + * @return true when tag is video/audio/script-data; otherwise, false. + */ +extern srs_bool srs_utils_flv_tag_is_ok(char type); /** * get the CodecID of video tag.