winlin

fix #375, fix hls bug, keep cc continous between ts files. 2.0.159.

@@ -562,6 +562,7 @@ Supported operating systems and hardware: @@ -562,6 +562,7 @@ Supported operating systems and hardware:
562 562
563 ### SRS 2.0 history 563 ### SRS 2.0 history
564 564
  565 +* 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.
565 * 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. 566 * 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.
566 * v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156. 567 * v2.0, 2015-04-03, enhanced avc decode, parse the sps get width+height. 2.0.156.
567 * v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155. 568 * v2.0, 2015-04-03, for [#372](https://github.com/winlinvip/simple-rtmp-server/issues/372), support transform vhost of edge 2.0.155.
@@ -138,14 +138,14 @@ string SrsHlsCacheWriter::cache() @@ -138,14 +138,14 @@ string SrsHlsCacheWriter::cache()
138 return data; 138 return data;
139 } 139 }
140 140
141 -SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc) 141 +SrsHlsSegment::SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc)
142 { 142 {
143 duration = 0; 143 duration = 0;
144 sequence_no = 0; 144 sequence_no = 0;
145 segment_start_dts = 0; 145 segment_start_dts = 0;
146 is_sequence_header = false; 146 is_sequence_header = false;
147 writer = new SrsHlsCacheWriter(write_cache, write_file); 147 writer = new SrsHlsCacheWriter(write_cache, write_file);
148 - muxer = new SrsTSMuxer(writer, ac, vc); 148 + muxer = new SrsTSMuxer(writer, c, ac, vc);
149 } 149 }
150 150
151 SrsHlsSegment::~SrsHlsSegment() 151 SrsHlsSegment::~SrsHlsSegment()
@@ -236,6 +236,7 @@ SrsHlsMuxer::SrsHlsMuxer() @@ -236,6 +236,7 @@ SrsHlsMuxer::SrsHlsMuxer()
236 should_write_cache = false; 236 should_write_cache = false;
237 should_write_file = true; 237 should_write_file = true;
238 async = new SrsDvrAsyncCallThread(); 238 async = new SrsDvrAsyncCallThread();
  239 + context = new SrsTsContext();
239 } 240 }
240 241
241 SrsHlsMuxer::~SrsHlsMuxer() 242 SrsHlsMuxer::~SrsHlsMuxer()
@@ -250,6 +251,7 @@ SrsHlsMuxer::~SrsHlsMuxer() @@ -250,6 +251,7 @@ SrsHlsMuxer::~SrsHlsMuxer()
250 srs_freep(current); 251 srs_freep(current);
251 srs_freep(req); 252 srs_freep(req);
252 srs_freep(async); 253 srs_freep(async);
  254 + srs_freep(context);
253 } 255 }
254 256
255 int SrsHlsMuxer::sequence_no() 257 int SrsHlsMuxer::sequence_no()
@@ -269,11 +271,21 @@ double SrsHlsMuxer::duration() @@ -269,11 +271,21 @@ double SrsHlsMuxer::duration()
269 271
270 double SrsHlsMuxer::deviation() 272 double SrsHlsMuxer::deviation()
271 { 273 {
  274 + // no floor, no deviation.
  275 + if (!hls_ts_floor) {
  276 + return 0;
  277 + }
  278 +
272 return hls_fragment_deviation; 279 return hls_fragment_deviation;
273 } 280 }
274 281
275 int SrsHlsMuxer::absolute_deviation() 282 int SrsHlsMuxer::absolute_deviation()
276 { 283 {
  284 + // no floor, no deviation.
  285 + if (!hls_ts_floor) {
  286 + return 0;
  287 + }
  288 +
277 // accept the floor ts for the first piece. 289 // accept the floor ts for the first piece.
278 int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment)); 290 int64_t floor_ts = (int64_t)(srs_get_system_time_ms() / (1000 * hls_fragment));
279 return (int)(accept_floor_ts - (floor_ts - 1)); 291 return (int)(accept_floor_ts - (floor_ts - 1));
@@ -391,7 +403,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) @@ -391,7 +403,7 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
391 } 403 }
392 404
393 // new segment. 405 // new segment.
394 - current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec, default_vcodec); 406 + current = new SrsHlsSegment(context, should_write_cache, should_write_file, default_acodec, default_vcodec);
395 current->sequence_no = _sequence_no++; 407 current->sequence_no = _sequence_no++;
396 current->segment_start_dts = segment_start_dts; 408 current->segment_start_dts = segment_start_dts;
397 409
@@ -56,6 +56,7 @@ class SrsTsAacJitter; @@ -56,6 +56,7 @@ class SrsTsAacJitter;
56 class SrsTsCache; 56 class SrsTsCache;
57 class SrsHlsSegment; 57 class SrsHlsSegment;
58 class SrsTsCache; 58 class SrsTsCache;
  59 +class SrsTsContext;
59 60
60 /** 61 /**
61 * the handler for hls event. 62 * the handler for hls event.
@@ -145,7 +146,7 @@ public: @@ -145,7 +146,7 @@ public:
145 // whether current segement is sequence header. 146 // whether current segement is sequence header.
146 bool is_sequence_header; 147 bool is_sequence_header;
147 public: 148 public:
148 - SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc); 149 + SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc);
149 virtual ~SrsHlsSegment(); 150 virtual ~SrsHlsSegment();
150 public: 151 public:
151 /** 152 /**
@@ -229,6 +230,11 @@ private: @@ -229,6 +230,11 @@ private:
229 * @see https://github.com/winlinvip/simple-rtmp-server/issues/301 230 * @see https://github.com/winlinvip/simple-rtmp-server/issues/301
230 */ 231 */
231 SrsCodecAudio acodec; 232 SrsCodecAudio acodec;
  233 + /**
  234 + * the ts context, to keep cc continous between ts.
  235 + * @see https://github.com/winlinvip/simple-rtmp-server/issues/375
  236 + */
  237 + SrsTsContext* context;
232 public: 238 public:
233 SrsHlsMuxer(); 239 SrsHlsMuxer();
234 virtual ~SrsHlsMuxer(); 240 virtual ~SrsHlsMuxer();
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR 2 32 #define VERSION_MAJOR 2
33 #define VERSION_MINOR 0 33 #define VERSION_MINOR 0
34 -#define VERSION_REVISION 158 34 +#define VERSION_REVISION 159
35 35
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -51,10 +51,10 @@ using namespace std; @@ -51,10 +51,10 @@ using namespace std;
51 51
52 // the mpegts header specifed the video/audio pid. 52 // the mpegts header specifed the video/audio pid.
53 #define TS_PMT_NUMBER 1 53 #define TS_PMT_NUMBER 1
54 -#define TS_PMT_PID 0x100  
55 -#define TS_VIDEO_AVC_PID 0x101  
56 -#define TS_AUDIO_AAC_PID 0x102  
57 -#define TS_AUDIO_MP3_PID 0x103 54 +#define TS_PMT_PID 0x1001
  55 +#define TS_VIDEO_AVC_PID 0x100
  56 +#define TS_AUDIO_AAC_PID 0x101
  57 +#define TS_AUDIO_MP3_PID 0x102
58 58
59 string srs_ts_stream2string(SrsTsStream stream) 59 string srs_ts_stream2string(SrsTsStream stream)
60 { 60 {
@@ -95,6 +95,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p) @@ -95,6 +95,7 @@ SrsTsMessage::SrsTsMessage(SrsTsChannel* c, SrsTsPacket* p)
95 continuity_counter = 0; 95 continuity_counter = 0;
96 PES_packet_length = 0; 96 PES_packet_length = 0;
97 payload = new SrsSimpleBuffer(); 97 payload = new SrsSimpleBuffer();
  98 + is_discontinuity = false;
98 99
99 start_pts = 0; 100 start_pts = 0;
100 write_pcr = false; 101 write_pcr = false;
@@ -192,6 +193,12 @@ SrsTsContext::~SrsTsContext() @@ -192,6 +193,12 @@ SrsTsContext::~SrsTsContext()
192 pids.clear(); 193 pids.clear();
193 } 194 }
194 195
  196 +void SrsTsContext::reset()
  197 +{
  198 + vcodec = SrsCodecVideoReserved;
  199 + acodec = SrsCodecAudioReserved1;
  200 +}
  201 +
195 SrsTsChannel* SrsTsContext::get(int pid) 202 SrsTsChannel* SrsTsContext::get(int pid)
196 { 203 {
197 if (pids.find(pid) == pids.end()) { 204 if (pids.find(pid) == pids.end()) {
@@ -251,7 +258,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo @@ -251,7 +258,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
251 int ret = ERROR_SUCCESS; 258 int ret = ERROR_SUCCESS;
252 259
253 SrsTsStream vs, as; 260 SrsTsStream vs, as;
254 - int16_t video_pid, audio_pid; 261 + int16_t video_pid = 0, audio_pid = 0;
255 switch (vc) { 262 switch (vc) {
256 case SrsCodecVideoAVC: 263 case SrsCodecVideoAVC:
257 vs = SrsTsStreamVideoH264; 264 vs = SrsTsStreamVideoH264;
@@ -401,9 +408,14 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p @@ -401,9 +408,14 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
401 write_pcr = true; 408 write_pcr = true;
402 } 409 }
403 410
  411 + // it's ok to set pcr equals to dts,
  412 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/311
  413 + int64_t pcr = write_pcr? msg->dts : -1;
  414 +
  415 + // TODO: FIXME: finger it why use discontinuity of msg.
404 pkt = SrsTsPacket::create_pes_first(this, 416 pkt = SrsTsPacket::create_pes_first(this,
405 - pid, msg->sid, channel->continuity_counter++, msg->discontinuity,  
406 - write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length() 417 + pid, msg->sid, channel->continuity_counter++, msg->is_discontinuity,
  418 + pcr, msg->dts, msg->pts, msg->payload->length()
407 ); 419 );
408 } else { 420 } else {
409 pkt = SrsTsPacket::create_pes_continue(this, 421 pkt = SrsTsPacket::create_pes_continue(this,
@@ -419,7 +431,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p @@ -419,7 +431,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
419 int nb_buf = pkt->size(); 431 int nb_buf = pkt->size();
420 srs_assert(nb_buf < SRS_TS_PACKET_SIZE); 432 srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
421 433
422 - int left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); 434 + int left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
423 int nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left; 435 int nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
424 if (nb_stuffings > 0) { 436 if (nb_stuffings > 0) {
425 // set all bytes to stuffings. 437 // set all bytes to stuffings.
@@ -432,7 +444,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p @@ -432,7 +444,7 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p
432 nb_buf = pkt->size(); 444 nb_buf = pkt->size();
433 srs_assert(nb_buf < SRS_TS_PACKET_SIZE); 445 srs_assert(nb_buf < SRS_TS_PACKET_SIZE);
434 446
435 - left = srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf); 447 + left = (int)srs_min(end - p, SRS_TS_PACKET_SIZE - nb_buf);
436 nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left; 448 nb_stuffings = SRS_TS_PACKET_SIZE - nb_buf - left;
437 srs_assert(nb_stuffings == 0); 449 srs_assert(nb_stuffings == 0);
438 } 450 }
@@ -703,13 +715,18 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, @@ -703,13 +715,18 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number,
703 pmt->section_number = 0; 715 pmt->section_number = 0;
704 pmt->last_section_number = 0; 716 pmt->last_section_number = 0;
705 pmt->program_info_length = 0; 717 pmt->program_info_length = 0;
  718 +
  719 + // use audio to carray pcr by default.
  720 + // for hls, there must be atleast one audio channel.
  721 + pmt->PCR_PID = apid;
  722 + pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
  723 +
  724 + // if h.264 specified, use video to carry pcr.
706 if (vs == SrsTsStreamVideoH264) { 725 if (vs == SrsTsStreamVideoH264) {
707 pmt->PCR_PID = vpid; 726 pmt->PCR_PID = vpid;
708 pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); 727 pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid));
709 - } else {  
710 - pmt->PCR_PID = apid;  
711 } 728 }
712 - pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); 729 +
713 pmt->CRC_32 = 0; // calc in encode. 730 pmt->CRC_32 = 0; // calc in encode.
714 return pkt; 731 return pkt;
715 } 732 }
@@ -2604,10 +2621,10 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream) @@ -2604,10 +2621,10 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream)
2604 return ret; 2621 return ret;
2605 } 2622 }
2606 2623
2607 -SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc) 2624 +SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc)
2608 { 2625 {
2609 writer = w; 2626 writer = w;
2610 - context = NULL; 2627 + context = c;
2611 2628
2612 acodec = ac; 2629 acodec = ac;
2613 vcodec = vc; 2630 vcodec = vc;
@@ -2625,10 +2642,9 @@ int SrsTSMuxer::open(string _path) @@ -2625,10 +2642,9 @@ int SrsTSMuxer::open(string _path)
2625 path = _path; 2642 path = _path;
2626 2643
2627 close(); 2644 close();
2628 -  
2629 - // use context to write ts file.  
2630 - srs_freep(context);  
2631 - context = new SrsTsContext(); 2645 +
  2646 + // reset the context for a new ts start.
  2647 + context->reset();
2632 2648
2633 if ((ret = writer->open(path)) != ERROR_SUCCESS) { 2649 if ((ret = writer->open(path)) != ERROR_SUCCESS) {
2634 return ret; 2650 return ret;
@@ -2677,7 +2693,6 @@ int SrsTSMuxer::write_video(SrsTsMessage* video) @@ -2677,7 +2693,6 @@ int SrsTSMuxer::write_video(SrsTsMessage* video)
2677 2693
2678 void SrsTSMuxer::close() 2694 void SrsTSMuxer::close()
2679 { 2695 {
2680 - srs_freep(context);  
2681 writer->close(); 2696 writer->close();
2682 } 2697 }
2683 2698
@@ -2911,6 +2926,8 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample) @@ -2911,6 +2926,8 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
2911 // 9, SI (SI slice) 2926 // 9, SI (SI slice)
2912 // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105. 2927 // H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105.
2913 static u_int8_t aud_nalu_7[] = { 0x09, 0xf0}; 2928 static u_int8_t aud_nalu_7[] = { 0x09, 0xf0};
  2929 +
  2930 + // always append a aud nalu for each frame.
2914 video->payload->append((const char*)fresh_nalu_header, 4); 2931 video->payload->append((const char*)fresh_nalu_header, 4);
2915 video->payload->append((const char*)aud_nalu_7, 2); 2932 video->payload->append((const char*)aud_nalu_7, 2);
2916 2933
@@ -2973,6 +2990,7 @@ SrsTsEncoder::SrsTsEncoder() @@ -2973,6 +2990,7 @@ SrsTsEncoder::SrsTsEncoder()
2973 codec = new SrsAvcAacCodec(); 2990 codec = new SrsAvcAacCodec();
2974 sample = new SrsCodecSample(); 2991 sample = new SrsCodecSample();
2975 cache = new SrsTsCache(); 2992 cache = new SrsTsCache();
  2993 + context = new SrsTsContext();
2976 muxer = NULL; 2994 muxer = NULL;
2977 } 2995 }
2978 2996
@@ -2982,6 +3000,7 @@ SrsTsEncoder::~SrsTsEncoder() @@ -2982,6 +3000,7 @@ SrsTsEncoder::~SrsTsEncoder()
2982 srs_freep(sample); 3000 srs_freep(sample);
2983 srs_freep(cache); 3001 srs_freep(cache);
2984 srs_freep(muxer); 3002 srs_freep(muxer);
  3003 + srs_freep(context);
2985 } 3004 }
2986 3005
2987 int SrsTsEncoder::initialize(SrsFileWriter* fs) 3006 int SrsTsEncoder::initialize(SrsFileWriter* fs)
@@ -2999,7 +3018,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) @@ -2999,7 +3018,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs)
2999 _fs = fs; 3018 _fs = fs;
3000 3019
3001 srs_freep(muxer); 3020 srs_freep(muxer);
3002 - muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC, SrsCodecVideoAVC); 3021 + muxer = new SrsTSMuxer(fs, context, SrsCodecAudioAAC, SrsCodecVideoAVC);
3003 3022
3004 if ((ret = muxer->open("")) != ERROR_SUCCESS) { 3023 if ((ret = muxer->open("")) != ERROR_SUCCESS) {
3005 return ret; 3024 return ret;
@@ -47,6 +47,7 @@ class SrsTsAdaptationField; @@ -47,6 +47,7 @@ class SrsTsAdaptationField;
47 class SrsTsPayload; 47 class SrsTsPayload;
48 class SrsTsMessage; 48 class SrsTsMessage;
49 class SrsTsPacket; 49 class SrsTsPacket;
  50 +class SrsTsContext;
50 51
51 // Transport Stream packets are 188 bytes in length. 52 // Transport Stream packets are 188 bytes in length.
52 #define SRS_TS_PACKET_SIZE 188 53 #define SRS_TS_PACKET_SIZE 188
@@ -258,7 +259,7 @@ public: @@ -258,7 +259,7 @@ public:
258 // generally, the video IDR(I frame, the keyframe of h.264) carray the pcr info. 259 // generally, the video IDR(I frame, the keyframe of h.264) carray the pcr info.
259 bool write_pcr; 260 bool write_pcr;
260 // whether got discontinuity ts, for example, sequence header changed. 261 // whether got discontinuity ts, for example, sequence header changed.
261 - bool discontinuity; 262 + bool is_discontinuity;
262 public: 263 public:
263 // the timestamp in 90khz 264 // the timestamp in 90khz
264 int64_t dts; 265 int64_t dts;
@@ -343,6 +344,11 @@ private: @@ -343,6 +344,11 @@ private:
343 public: 344 public:
344 SrsTsContext(); 345 SrsTsContext();
345 virtual ~SrsTsContext(); 346 virtual ~SrsTsContext();
  347 +public:
  348 + /**
  349 + * reset the context for a new ts segment start.
  350 + */
  351 + virtual void reset();
346 // codec 352 // codec
347 public: 353 public:
348 /** 354 /**
@@ -1533,7 +1539,7 @@ private: @@ -1533,7 +1539,7 @@ private:
1533 SrsFileWriter* writer; 1539 SrsFileWriter* writer;
1534 std::string path; 1540 std::string path;
1535 public: 1541 public:
1536 - SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc); 1542 + SrsTSMuxer(SrsFileWriter* w, SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
1537 virtual ~SrsTSMuxer(); 1543 virtual ~SrsTSMuxer();
1538 public: 1544 public:
1539 /** 1545 /**
@@ -1608,6 +1614,7 @@ private: @@ -1608,6 +1614,7 @@ private:
1608 SrsCodecSample* sample; 1614 SrsCodecSample* sample;
1609 SrsTsCache* cache; 1615 SrsTsCache* cache;
1610 SrsTSMuxer* muxer; 1616 SrsTSMuxer* muxer;
  1617 + SrsTsContext* context;
1611 public: 1618 public:
1612 SrsTsEncoder(); 1619 SrsTsEncoder();
1613 virtual ~SrsTsEncoder(); 1620 virtual ~SrsTsEncoder();