winlin

for #293, add http stream cache for audio mp3/aac stream.

@@ -140,6 +140,36 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -140,6 +140,36 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
140 return ret; 140 return ret;
141 } 141 }
142 142
  143 +SrsStreamCache::SrsStreamCache(SrsSource* s)
  144 +{
  145 + source = s;
  146 + pthread = new SrsThread("http-stream",
  147 + this, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US, false);
  148 +}
  149 +
  150 +SrsStreamCache::~SrsStreamCache()
  151 +{
  152 + pthread->stop();
  153 + srs_freep(pthread);
  154 +}
  155 +
  156 +int SrsStreamCache::start()
  157 +{
  158 + return pthread->start();
  159 +}
  160 +
  161 +int SrsStreamCache::dump_cache(SrsConsumer* consumer)
  162 +{
  163 + int ret = ERROR_SUCCESS;
  164 + return ret;
  165 +}
  166 +
  167 +int SrsStreamCache::cycle()
  168 +{
  169 + int ret = ERROR_SUCCESS;
  170 + return ret;
  171 +}
  172 +
143 ISrsStreamEncoder::ISrsStreamEncoder() 173 ISrsStreamEncoder::ISrsStreamEncoder()
144 { 174 {
145 } 175 }
@@ -158,7 +188,7 @@ SrsFlvStreamEncoder::~SrsFlvStreamEncoder() @@ -158,7 +188,7 @@ SrsFlvStreamEncoder::~SrsFlvStreamEncoder()
158 srs_freep(enc); 188 srs_freep(enc);
159 } 189 }
160 190
161 -int SrsFlvStreamEncoder::initialize(SrsFileWriter* w) 191 +int SrsFlvStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* /*c*/)
162 { 192 {
163 int ret = ERROR_SUCCESS; 193 int ret = ERROR_SUCCESS;
164 194
@@ -189,9 +219,22 @@ int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size) @@ -189,9 +219,22 @@ int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size)
189 return enc->write_metadata(timestamp, data, size); 219 return enc->write_metadata(timestamp, data, size);
190 } 220 }
191 221
  222 +bool SrsFlvStreamEncoder::has_cache()
  223 +{
  224 + // for flv stream, use gop cache of SrsSource is ok.
  225 + return false;
  226 +}
  227 +
  228 +int SrsFlvStreamEncoder::dump_cache(SrsConsumer* /*consumer*/)
  229 +{
  230 + // for flv stream, ignore cache.
  231 + return ERROR_SUCCESS;
  232 +}
  233 +
192 SrsAacStreamEncoder::SrsAacStreamEncoder() 234 SrsAacStreamEncoder::SrsAacStreamEncoder()
193 { 235 {
194 enc = new SrsAacEncoder(); 236 enc = new SrsAacEncoder();
  237 + cache = NULL;
195 } 238 }
196 239
197 SrsAacStreamEncoder::~SrsAacStreamEncoder() 240 SrsAacStreamEncoder::~SrsAacStreamEncoder()
@@ -199,10 +242,12 @@ SrsAacStreamEncoder::~SrsAacStreamEncoder() @@ -199,10 +242,12 @@ SrsAacStreamEncoder::~SrsAacStreamEncoder()
199 srs_freep(enc); 242 srs_freep(enc);
200 } 243 }
201 244
202 -int SrsAacStreamEncoder::initialize(SrsFileWriter* w) 245 +int SrsAacStreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)
203 { 246 {
204 int ret = ERROR_SUCCESS; 247 int ret = ERROR_SUCCESS;
205 248
  249 + cache = c;
  250 +
206 if ((ret = enc->initialize(w)) != ERROR_SUCCESS) { 251 if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
207 return ret; 252 return ret;
208 } 253 }
@@ -227,9 +272,21 @@ int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, i @@ -227,9 +272,21 @@ int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, i
227 return ERROR_SUCCESS; 272 return ERROR_SUCCESS;
228 } 273 }
229 274
  275 +bool SrsAacStreamEncoder::has_cache()
  276 +{
  277 + return true;
  278 +}
  279 +
  280 +int SrsAacStreamEncoder::dump_cache(SrsConsumer* consumer)
  281 +{
  282 + srs_assert(cache);
  283 + return cache->dump_cache(consumer);
  284 +}
  285 +
230 SrsMp3StreamEncoder::SrsMp3StreamEncoder() 286 SrsMp3StreamEncoder::SrsMp3StreamEncoder()
231 { 287 {
232 enc = new SrsMp3Encoder(); 288 enc = new SrsMp3Encoder();
  289 + cache = NULL;
233 } 290 }
234 291
235 SrsMp3StreamEncoder::~SrsMp3StreamEncoder() 292 SrsMp3StreamEncoder::~SrsMp3StreamEncoder()
@@ -237,10 +294,12 @@ SrsMp3StreamEncoder::~SrsMp3StreamEncoder() @@ -237,10 +294,12 @@ SrsMp3StreamEncoder::~SrsMp3StreamEncoder()
237 srs_freep(enc); 294 srs_freep(enc);
238 } 295 }
239 296
240 -int SrsMp3StreamEncoder::initialize(SrsFileWriter* w) 297 +int SrsMp3StreamEncoder::initialize(SrsFileWriter* w, SrsStreamCache* c)
241 { 298 {
242 int ret = ERROR_SUCCESS; 299 int ret = ERROR_SUCCESS;
243 300
  301 + cache = c;
  302 +
244 if ((ret = enc->initialize(w)) != ERROR_SUCCESS) { 303 if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
245 return ret; 304 return ret;
246 } 305 }
@@ -269,6 +328,17 @@ int SrsMp3StreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, i @@ -269,6 +328,17 @@ int SrsMp3StreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, i
269 return ERROR_SUCCESS; 328 return ERROR_SUCCESS;
270 } 329 }
271 330
  331 +bool SrsMp3StreamEncoder::has_cache()
  332 +{
  333 + return true;
  334 +}
  335 +
  336 +int SrsMp3StreamEncoder::dump_cache(SrsConsumer* consumer)
  337 +{
  338 + srs_assert(cache);
  339 + return cache->dump_cache(consumer);
  340 +}
  341 +
272 SrsStreamWriter::SrsStreamWriter(ISrsGoHttpResponseWriter* w) 342 SrsStreamWriter::SrsStreamWriter(ISrsGoHttpResponseWriter* w)
273 { 343 {
274 writer = w; 344 writer = w;
@@ -305,9 +375,10 @@ int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite) @@ -305,9 +375,10 @@ int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)
305 return writer->write((char*)buf, (int)count); 375 return writer->write((char*)buf, (int)count);
306 } 376 }
307 377
308 -SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r) 378 +SrsLiveStream::SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c)
309 { 379 {
310 source = s; 380 source = s;
  381 + cache = c;
311 req = r->copy(); 382 req = r->copy();
312 } 383 }
313 384
@@ -339,9 +410,9 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -339,9 +410,9 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
339 } 410 }
340 SrsAutoFree(ISrsStreamEncoder, enc); 411 SrsAutoFree(ISrsStreamEncoder, enc);
341 412
342 - // create consumer of souce. 413 + // create consumer of souce, ignore gop cache, use the audio gop cache.
343 SrsConsumer* consumer = NULL; 414 SrsConsumer* consumer = NULL;
344 - if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { 415 + if ((ret = source->create_consumer(consumer, !enc->has_cache())) != ERROR_SUCCESS) {
345 srs_error("http: create consumer failed. ret=%d", ret); 416 srs_error("http: create consumer failed. ret=%d", ret);
346 return ret; 417 return ret;
347 } 418 }
@@ -353,10 +424,19 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -353,10 +424,19 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
353 424
354 // the memory writer. 425 // the memory writer.
355 SrsStreamWriter writer(w); 426 SrsStreamWriter writer(w);
356 - if ((ret = enc->initialize(&writer)) != ERROR_SUCCESS) { 427 + if ((ret = enc->initialize(&writer, cache)) != ERROR_SUCCESS) {
  428 + srs_error("http: initialize stream encoder failed. ret=%d", ret);
357 return ret; 429 return ret;
358 } 430 }
359 431
  432 + // if gop cache enabled for encoder, dump to consumer.
  433 + if (enc->has_cache()) {
  434 + if ((ret = enc->dump_cache(consumer)) != ERROR_SUCCESS) {
  435 + srs_error("http: dump cache to consumer failed. ret=%d", ret);
  436 + return ret;
  437 + }
  438 + }
  439 +
360 while (true) { 440 while (true) {
361 // get messages from consumer. 441 // get messages from consumer.
362 // each msg in msgs.msgs must be free, for the SrsMessageArray never free them. 442 // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
@@ -424,6 +504,7 @@ int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrM @@ -424,6 +504,7 @@ int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrM
424 SrsLiveEntry::SrsLiveEntry() 504 SrsLiveEntry::SrsLiveEntry()
425 { 505 {
426 stream = NULL; 506 stream = NULL;
  507 + cache = NULL;
427 } 508 }
428 509
429 SrsHttpServer::SrsHttpServer() 510 SrsHttpServer::SrsHttpServer()
@@ -485,7 +566,14 @@ int SrsHttpServer::mount(SrsSource* s, SrsRequest* r) @@ -485,7 +566,14 @@ int SrsHttpServer::mount(SrsSource* s, SrsRequest* r)
485 // remove the default vhost mount 566 // remove the default vhost mount
486 mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); 567 mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/");
487 568
488 - entry->stream = new SrsLiveStream(s, r); 569 + entry->cache = new SrsStreamCache(s);
  570 + entry->stream = new SrsLiveStream(s, r, entry->cache);
  571 +
  572 + // start http stream cache thread
  573 + if ((ret = entry->cache->start()) != ERROR_SUCCESS) {
  574 + srs_error("http: start stream cache failed. ret=%d", ret);
  575 + return ret;
  576 + }
489 577
490 // mount the http flv stream. 578 // mount the http flv stream.
491 if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) { 579 if ((ret = mux.handle(mount, entry->stream)) != ERROR_SUCCESS) {
@@ -37,9 +37,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -37,9 +37,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #include <srs_app_http.hpp> 37 #include <srs_app_http.hpp>
38 #include <srs_app_reload.hpp> 38 #include <srs_app_reload.hpp>
39 #include <srs_kernel_file.hpp> 39 #include <srs_kernel_file.hpp>
  40 +#include <srs_app_thread.hpp>
40 41
41 class SrsSource; 42 class SrsSource;
42 class SrsRequest; 43 class SrsRequest;
  44 +class SrsConsumer;
43 class SrsStSocket; 45 class SrsStSocket;
44 class SrsAacEncoder; 46 class SrsAacEncoder;
45 class SrsMp3Encoder; 47 class SrsMp3Encoder;
@@ -65,6 +67,27 @@ protected: @@ -65,6 +67,27 @@ protected:
65 }; 67 };
66 68
67 /** 69 /**
  70 +* for the srs http stream cache,
  71 +* for example, the audio stream cache to make android(weixin) happy.
  72 +* we start a thread to shrink the queue.
  73 +*/
  74 +class SrsStreamCache : public ISrsThreadHandler
  75 +{
  76 +private:
  77 + SrsSource* source;
  78 + SrsThread* pthread;
  79 +public:
  80 + SrsStreamCache(SrsSource* s);
  81 + virtual ~SrsStreamCache();
  82 +public:
  83 + virtual int start();
  84 + virtual int dump_cache(SrsConsumer* consumer);
  85 +// interface ISrsThreadHandler.
  86 +public:
  87 + virtual int cycle();
  88 +};
  89 +
  90 +/**
68 * the stream encoder in some codec, for example, flv or aac. 91 * the stream encoder in some codec, for example, flv or aac.
69 */ 92 */
70 class ISrsStreamEncoder 93 class ISrsStreamEncoder
@@ -73,10 +96,29 @@ public: @@ -73,10 +96,29 @@ public:
73 ISrsStreamEncoder(); 96 ISrsStreamEncoder();
74 virtual ~ISrsStreamEncoder(); 97 virtual ~ISrsStreamEncoder();
75 public: 98 public:
76 - virtual int initialize(SrsFileWriter* w) = 0; 99 + /**
  100 + * initialize the encoder with file writer(to http response) and stream cache.
  101 + * @param w the writer to write to http response.
  102 + * @param c the stream cache for audio stream fast startup.
  103 + */
  104 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c) = 0;
  105 + /**
  106 + * write rtmp video/audio/metadata.
  107 + */
77 virtual int write_audio(int64_t timestamp, char* data, int size) = 0; 108 virtual int write_audio(int64_t timestamp, char* data, int size) = 0;
78 virtual int write_video(int64_t timestamp, char* data, int size) = 0; 109 virtual int write_video(int64_t timestamp, char* data, int size) = 0;
79 virtual int write_metadata(int64_t timestamp, char* data, int size) = 0; 110 virtual int write_metadata(int64_t timestamp, char* data, int size) = 0;
  111 +public:
  112 + /**
  113 + * for some stream, for example, mp3 and aac, the audio stream,
  114 + * we use large gop cache in encoder, for the gop cache of SrsSource is ignore audio.
  115 + * @return true to use gop cache of encoder; otherwise, use SrsSource.
  116 + */
  117 + virtual bool has_cache() = 0;
  118 + /**
  119 + * dumps the cache of encoder to consumer.
  120 + */
  121 + virtual int dump_cache(SrsConsumer* consumer) = 0;
80 }; 122 };
81 123
82 /** 124 /**
@@ -90,10 +132,13 @@ public: @@ -90,10 +132,13 @@ public:
90 SrsFlvStreamEncoder(); 132 SrsFlvStreamEncoder();
91 virtual ~SrsFlvStreamEncoder(); 133 virtual ~SrsFlvStreamEncoder();
92 public: 134 public:
93 - virtual int initialize(SrsFileWriter* w); 135 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
94 virtual int write_audio(int64_t timestamp, char* data, int size); 136 virtual int write_audio(int64_t timestamp, char* data, int size);
95 virtual int write_video(int64_t timestamp, char* data, int size); 137 virtual int write_video(int64_t timestamp, char* data, int size);
96 virtual int write_metadata(int64_t timestamp, char* data, int size); 138 virtual int write_metadata(int64_t timestamp, char* data, int size);
  139 +public:
  140 + virtual bool has_cache();
  141 + virtual int dump_cache(SrsConsumer* consumer);
97 }; 142 };
98 143
99 /** 144 /**
@@ -103,14 +148,18 @@ class SrsAacStreamEncoder : public ISrsStreamEncoder @@ -103,14 +148,18 @@ class SrsAacStreamEncoder : public ISrsStreamEncoder
103 { 148 {
104 private: 149 private:
105 SrsAacEncoder* enc; 150 SrsAacEncoder* enc;
  151 + SrsStreamCache* cache;
106 public: 152 public:
107 SrsAacStreamEncoder(); 153 SrsAacStreamEncoder();
108 virtual ~SrsAacStreamEncoder(); 154 virtual ~SrsAacStreamEncoder();
109 public: 155 public:
110 - virtual int initialize(SrsFileWriter* w); 156 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
111 virtual int write_audio(int64_t timestamp, char* data, int size); 157 virtual int write_audio(int64_t timestamp, char* data, int size);
112 virtual int write_video(int64_t timestamp, char* data, int size); 158 virtual int write_video(int64_t timestamp, char* data, int size);
113 virtual int write_metadata(int64_t timestamp, char* data, int size); 159 virtual int write_metadata(int64_t timestamp, char* data, int size);
  160 +public:
  161 + virtual bool has_cache();
  162 + virtual int dump_cache(SrsConsumer* consumer);
114 }; 163 };
115 164
116 /** 165 /**
@@ -120,14 +169,18 @@ class SrsMp3StreamEncoder : public ISrsStreamEncoder @@ -120,14 +169,18 @@ class SrsMp3StreamEncoder : public ISrsStreamEncoder
120 { 169 {
121 private: 170 private:
122 SrsMp3Encoder* enc; 171 SrsMp3Encoder* enc;
  172 + SrsStreamCache* cache;
123 public: 173 public:
124 SrsMp3StreamEncoder(); 174 SrsMp3StreamEncoder();
125 virtual ~SrsMp3StreamEncoder(); 175 virtual ~SrsMp3StreamEncoder();
126 public: 176 public:
127 - virtual int initialize(SrsFileWriter* w); 177 + virtual int initialize(SrsFileWriter* w, SrsStreamCache* c);
128 virtual int write_audio(int64_t timestamp, char* data, int size); 178 virtual int write_audio(int64_t timestamp, char* data, int size);
129 virtual int write_video(int64_t timestamp, char* data, int size); 179 virtual int write_video(int64_t timestamp, char* data, int size);
130 virtual int write_metadata(int64_t timestamp, char* data, int size); 180 virtual int write_metadata(int64_t timestamp, char* data, int size);
  181 +public:
  182 + virtual bool has_cache();
  183 + virtual int dump_cache(SrsConsumer* consumer);
131 }; 184 };
132 185
133 /** 186 /**
@@ -159,8 +212,9 @@ class SrsLiveStream : public ISrsGoHttpHandler @@ -159,8 +212,9 @@ class SrsLiveStream : public ISrsGoHttpHandler
159 private: 212 private:
160 SrsRequest* req; 213 SrsRequest* req;
161 SrsSource* source; 214 SrsSource* source;
  215 + SrsStreamCache* cache;
162 public: 216 public:
163 - SrsLiveStream(SrsSource* s, SrsRequest* r); 217 + SrsLiveStream(SrsSource* s, SrsRequest* r, SrsStreamCache* c);
164 virtual ~SrsLiveStream(); 218 virtual ~SrsLiveStream();
165 public: 219 public:
166 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); 220 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
@@ -176,6 +230,7 @@ struct SrsLiveEntry @@ -176,6 +230,7 @@ struct SrsLiveEntry
176 std::string vhost; 230 std::string vhost;
177 std::string mount; 231 std::string mount;
178 SrsLiveStream* stream; 232 SrsLiveStream* stream;
  233 + SrsStreamCache* cache;
179 234
180 SrsLiveEntry(); 235 SrsLiveEntry();
181 }; 236 };
@@ -1702,7 +1702,7 @@ void SrsSource::on_unpublish() @@ -1702,7 +1702,7 @@ void SrsSource::on_unpublish()
1702 handler->on_unpublish(this, _req); 1702 handler->on_unpublish(this, _req);
1703 } 1703 }
1704 1704
1705 -int SrsSource::create_consumer(SrsConsumer*& consumer) 1705 +int SrsSource::create_consumer(SrsConsumer*& consumer, bool dump_gop_cache)
1706 { 1706 {
1707 int ret = ERROR_SUCCESS; 1707 int ret = ERROR_SUCCESS;
1708 1708
@@ -1750,12 +1750,15 @@ int SrsSource::create_consumer(SrsConsumer*& consumer) @@ -1750,12 +1750,15 @@ int SrsSource::create_consumer(SrsConsumer*& consumer)
1750 srs_info("dispatch audio sequence header success"); 1750 srs_info("dispatch audio sequence header success");
1751 1751
1752 // copy gop cache to client. 1752 // copy gop cache to client.
1753 - if ((ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) {  
1754 - return ret; 1753 + if (dump_gop_cache) {
  1754 + if ((ret = gop_cache->dump(consumer, atc, tba, tbv, ag)) != ERROR_SUCCESS) {
  1755 + return ret;
  1756 + }
  1757 + srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate);
  1758 + } else {
  1759 + srs_trace("create consumer, ignore gop cache, tba=%d, tbv=%d", sample_rate, frame_rate);
1755 } 1760 }
1756 1761
1757 - srs_trace("create consumer, queue_size=%.2f, tba=%d, tbv=%d", queue_size, sample_rate, frame_rate);  
1758 -  
1759 return ret; 1762 return ret;
1760 } 1763 }
1761 1764
@@ -494,7 +494,7 @@ public: @@ -494,7 +494,7 @@ public:
494 virtual void on_unpublish(); 494 virtual void on_unpublish();
495 // consumer methods 495 // consumer methods
496 public: 496 public:
497 - virtual int create_consumer(SrsConsumer*& consumer); 497 + virtual int create_consumer(SrsConsumer*& consumer, bool dump_gop_cache = true);
498 virtual void on_consumer_destroy(SrsConsumer* consumer); 498 virtual void on_consumer_destroy(SrsConsumer* consumer);
499 virtual void set_cache(bool enabled); 499 virtual void set_cache(bool enabled);
500 // internal 500 // internal