int SrsGopCache::cache(SrsSharedPtrMessage* __msg) { int ret = ERROR_SUCCESS; if (!enable_gop_cache) { srs_verbose("gop cache is disabled."); return ret; } // the gop cache know when to gop it. SrsSharedPtrMessage* msg = __msg; // disable gop cache when not h.264 if (!SrsFlvCodec::video_is_h264(msg->payload, msg->size)) { srs_info("gop donot cache video for none h.264"); return ret; } // got video, update the video count if acceptable if (msg->is_video()) { cached_video_count++; audio_after_last_video_count = 0; } // no acceptable video or pure audio, disable the cache. if (pure_audio()) { srs_verbose("ignore any frame util got a h264 video frame."); return ret; } // ok, gop cache enabled, and got an audio. if (msg->is_audio()) { audio_after_last_video_count++; } // clear gop cache when pure audio count overflow if (audio_after_last_video_count > __SRS_PURE_AUDIO_GUESS_COUNT) { srs_warn("clear gop cache for guess pure audio overflow"); clear(); return ret; } // clear gop cache when got key frame if (msg->is_video() && SrsFlvCodec::video_is_keyframe(msg->payload, msg->size)) { srs_info("clear gop cache when got keyframe. vcount=%d, count=%d", cached_video_count, (int)gop_cache.size()); clear(); // curent msg is video frame, so we set to 1. cached_video_count = 1; } // cache the frame. gop_cache.push_back(msg->copy()); return ret; }
void SrsMessageQueue::shrink() { int iframe_index = -1; // issue the first iframe. // skip the first frame, whatever the type of it, // for when we shrinked, the first is the iframe, // we will directly remove the gop next time. for (int i = 1; i < (int)msgs.size(); i++) { SrsSharedPtrMessage* msg = msgs.at(i); if (msg->is_video()) { if (SrsFlvCodec::video_is_keyframe(msg->payload, msg->size)) { // the max frame index to remove. iframe_index = i; // set the start time, we will remove until this frame. av_start_time = msg->timestamp; break; } } } // no iframe, for audio, clear the queue. // it is ok to clear for audio, for the shrink tell us the queue is full. // for video, we clear util the I-Frame, for the decoding must start from I-frame, // for audio, it's ok to clear any data, also we can clear the whole queue. // @see: https://github.com/winlinvip/simple-rtmp-server/issues/134 if (iframe_index < 0) { clear(); return; } srs_trace("shrink the cache queue, size=%d, removed=%d, max=%.2f", (int)msgs.size(), iframe_index, queue_size_ms / 1000.0); // remove the first gop from the front for (int i = 0; i < iframe_index; i++) { SrsSharedPtrMessage* msg = msgs.at(i); srs_freep(msg); } msgs.erase(msgs.begin(), msgs.begin() + iframe_index); }
int SrsLiveStream::streaming_send_messages(ISrsBufferEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs) { int ret = ERROR_SUCCESS; for (int i = 0; i < nb_msgs; i++) { SrsSharedPtrMessage* msg = msgs[i]; if (msg->is_audio()) { ret = enc->write_audio(msg->timestamp, msg->payload, msg->size); } else if (msg->is_video()) { ret = enc->write_video(msg->timestamp, msg->payload, msg->size); } else { ret = enc->write_metadata(msg->timestamp, msg->payload, msg->size); } if (ret != ERROR_SUCCESS) { return ret; } } return ret; }