@@ -41,6 +41,7 @@ using namespace std;
4141#include < srs_app_edge.hpp>
4242#include < srs_kernel_utility.hpp>
4343#include < srs_app_avc_aac.hpp>
44+ #include < srs_protocol_msg_array.hpp>
4445
4546#define CONST_MAX_JITTER_MS 500
4647#define DEFAULT_FRAME_TIME_MS 40
@@ -166,22 +167,12 @@ SrsMessageQueue::~SrsMessageQueue()
166167 clear ();
167168}
168169
169- int SrsMessageQueue::count ()
170- {
171- return (int )msgs.size ();
172- }
173-
174- int SrsMessageQueue::duration ()
175- {
176- return (int )(av_end_time - av_start_time);
177- }
178-
179170void SrsMessageQueue::set_queue_size (double queue_size)
180171{
181172 queue_size_ms = (int )(queue_size * 1000 );
182173}
183174
184- int SrsMessageQueue::enqueue (SrsSharedPtrMessage* msg)
175+ int SrsMessageQueue::enqueue (SrsSharedPtrMessage* msg, bool * is_overflow )
185176{
186177 int ret = ERROR_SUCCESS;
187178
@@ -196,6 +187,11 @@ int SrsMessageQueue::enqueue(SrsSharedPtrMessage* msg)
196187 msgs.push_back (msg);
197188
198189 while (av_end_time - av_start_time > queue_size_ms) {
190+ // notice the caller queue already overflow and shrinked.
191+ if (is_overflow) {
192+ *is_overflow = true ;
193+ }
194+
199195 shrink ();
200196 }
201197
@@ -305,10 +301,20 @@ SrsConsumer::SrsConsumer(SrsSource* _source)
305301 mw_min_msgs = 0 ;
306302 mw_duration = 0 ;
307303 mw_waiting = false ;
304+
305+ mw_cache = new SrsMessageArray (SRS_PERF_MW_MSGS);
306+ mw_count = 0 ;
307+ mw_first_pkt = mw_last_pkt = 0 ;
308308}
309309
310310SrsConsumer::~SrsConsumer ()
311311{
312+ if (mw_cache) {
313+ mw_cache->free (mw_count);
314+ mw_count = 0 ;
315+ }
316+ srs_freep (mw_cache);
317+
312318 source->on_consumer_destroy (this );
313319 srs_freep (jitter);
314320 srs_freep (queue);
@@ -341,22 +347,53 @@ int SrsConsumer::enqueue(SrsSharedPtrMessage* msg, bool atc, int tba, int tbv, S
341347 }
342348 }
343349
344- if ((ret = queue->enqueue (msg)) != ERROR_SUCCESS) {
345- return ret;
350+ // use fast cache if available
351+ if (mw_count < mw_cache->max ) {
352+ // update fast cache timestamps
353+ if (mw_count == 0 ) {
354+ mw_first_pkt = msg->header .timestamp ;
355+ }
356+ mw_last_pkt = msg->header .timestamp ;
357+
358+ mw_cache->msgs [mw_count++] = msg;
359+ } else {
360+ // fast cache is full, use queue.
361+ bool is_overflow = false ;
362+ if ((ret = queue->enqueue (msg, &is_overflow)) != ERROR_SUCCESS) {
363+ return ret;
364+ }
365+ // when overflow, clear cache and refresh the fast cache.
366+ if (is_overflow) {
367+ mw_cache->free (mw_count);
368+ if ((ret = dumps_queue_to_fast_cache ()) != ERROR_SUCCESS) {
369+ return ret;
370+ }
371+ }
346372 }
347373
348374 // fire the mw when msgs is enough.
349- if (mw_waiting && queue->count () > mw_min_msgs && queue->duration () > mw_duration) {
350- st_cond_signal (mw_wait);
351- mw_waiting = false ;
375+ if (mw_waiting) {
376+ // when fast cache not overflow, always flush.
377+ // so we donot care about the queue.
378+ bool fast_cache_overflow = mw_count >= mw_cache->max ;
379+ int duration_ms = (int )(mw_last_pkt - mw_first_pkt);
380+ bool match_min_msgs = mw_count > mw_min_msgs;
381+
382+ // when fast cache overflow, or duration ok, signal to flush.
383+ if (fast_cache_overflow || (match_min_msgs && duration_ms > mw_duration)) {
384+ st_cond_signal (mw_wait);
385+ mw_waiting = false ;
386+ }
352387 }
353388
354389 return ret;
355390}
356391
357- int SrsConsumer::dump_packets (int max_count, SrsMessage** pmsgs , int & count)
392+ int SrsConsumer::dump_packets (SrsMessageArray* msgs , int * count)
358393{
359- srs_assert (max_count > 0 );
394+ int ret =ERROR_SUCCESS;
395+
396+ srs_assert (msgs->max > 0 );
360397
361398 if (should_update_source_id) {
362399 srs_trace (" update source_id=%d[%d]" , source->source_id (), source->source_id ());
@@ -365,25 +402,45 @@ int SrsConsumer::dump_packets(int max_count, SrsMessage** pmsgs, int& count)
365402
366403 // paused, return nothing.
367404 if (paused) {
368- return ERROR_SUCCESS;
405+ return ret;
406+ }
407+
408+ // only dumps an whole array to msgs.
409+ for (int i = 0 ; i < mw_count; i++) {
410+ msgs->msgs [i] = mw_cache->msgs [i];
369411 }
412+ *count = mw_count;
370413
371- return queue->dump_packets (max_count, pmsgs, count);
414+ // when fast cache is not filled,
415+ // we donot check the queue, direclty zero fast cache.
416+ if (mw_count < mw_cache->max ) {
417+ mw_count = 0 ;
418+ mw_first_pkt = mw_last_pkt = 0 ;
419+ return ret;
420+ }
421+
422+ return dumps_queue_to_fast_cache ();
372423}
373424
374425void SrsConsumer::wait (int nb_msgs, int duration)
375426{
376427 mw_min_msgs = nb_msgs;
377428 mw_duration = duration;
378429
379- // already ok, donot wait.
380- if (queue->count () > mw_min_msgs && queue->duration () > mw_duration) {
430+ // when fast cache not overflow, always flush.
431+ // so we donot care about the queue.
432+ bool fast_cache_overflow = mw_count >= mw_cache->max ;
433+ int duration_ms = (int )(mw_last_pkt - mw_first_pkt);
434+ bool match_min_msgs = mw_count > mw_min_msgs;
435+
436+ // when fast cache overflow, or duration ok, signal to flush.
437+ if (fast_cache_overflow || (match_min_msgs && duration_ms > mw_duration)) {
381438 return ;
382439 }
383440
384441 // the enqueue will notify this cond.
385442 mw_waiting = true ;
386-
443+ // wait for msgs to incoming.
387444 st_cond_wait (mw_wait);
388445}
389446
@@ -397,6 +454,26 @@ int SrsConsumer::on_play_client_pause(bool is_pause)
397454 return ret;
398455}
399456
457+ int SrsConsumer::dumps_queue_to_fast_cache ()
458+ {
459+ int ret =ERROR_SUCCESS;
460+
461+ // fill fast cache with queue.
462+ if ((ret = queue->dump_packets (mw_cache->max , mw_cache->msgs , mw_count)) != ERROR_SUCCESS) {
463+ return ret;
464+ }
465+ // set the timestamp when got message.
466+ if (mw_count > 0 ) {
467+ SrsMessage* first_msg = mw_cache->msgs [0 ];
468+ mw_first_pkt = first_msg->header .timestamp ;
469+
470+ SrsMessage* last_msg = mw_cache->msgs [mw_count - 1 ];
471+ mw_last_pkt = last_msg->header .timestamp ;
472+ }
473+
474+ return ret;
475+ }
476+
400477SrsGopCache::SrsGopCache ()
401478{
402479 cached_video_count = 0 ;
0 commit comments