winlin

support cache last gop for video

@@ -45,7 +45,8 @@ url: rtmp://127.0.0.1:1935/live/livestream @@ -45,7 +45,8 @@ url: rtmp://127.0.0.1:1935/live/livestream
45 * nginx v1.5.0: 139524 lines <br/> 45 * nginx v1.5.0: 139524 lines <br/>
46 46
47 ### History 47 ### History
48 -* v0.2, 2013-10-23, v0.2 released. 10125 lines. 48 +* v0.3, 2013-10-27, support cache last gop for client fast startup.
  49 +* v0.2, 2013-10-25, v0.2 released. 10125 lines.
49 * v0.2, 2013-10-25, support flash publish. 50 * v0.2, 2013-10-25, support flash publish.
50 * v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake(SrsComplexHandshake). 51 * v0.2, 2013-10-25, support h264/avc codec by rtmp complex handshake(SrsComplexHandshake).
51 * v0.2, 2013-10-24, support time jitter detect and correct algorithm(SrsConsumer::jitter_correct). 52 * v0.2, 2013-10-24, support time jitter detect and correct algorithm(SrsConsumer::jitter_correct).
@@ -145,7 +145,9 @@ int SrsClient::do_cycle() @@ -145,7 +145,9 @@ int SrsClient::do_cycle()
145 return ret; 145 return ret;
146 } 146 }
147 srs_info("start to publish stream %s success", req->stream.c_str()); 147 srs_info("start to publish stream %s success", req->stream.c_str());
148 - return streaming_publish(source, true); 148 + ret = streaming_publish(source, true);
  149 + source->on_unpublish();
  150 + return ret;
149 } 151 }
150 case SrsClientFlashPublish: { 152 case SrsClientFlashPublish: {
151 srs_verbose("flash start to publish stream %s.", req->stream.c_str()); 153 srs_verbose("flash start to publish stream %s.", req->stream.c_str());
@@ -155,7 +157,9 @@ int SrsClient::do_cycle() @@ -155,7 +157,9 @@ int SrsClient::do_cycle()
155 return ret; 157 return ret;
156 } 158 }
157 srs_info("flash start to publish stream %s success", req->stream.c_str()); 159 srs_info("flash start to publish stream %s success", req->stream.c_str());
158 - return streaming_publish(source, false); 160 + ret = streaming_publish(source, false);
  161 + source->on_unpublish();
  162 + return ret;
159 } 163 }
160 default: { 164 default: {
161 ret = ERROR_SYSTEM_CLIENT_INVALID; 165 ret = ERROR_SYSTEM_CLIENT_INVALID;
@@ -31,6 +31,35 @@ SrsCodec::~SrsCodec() @@ -31,6 +31,35 @@ SrsCodec::~SrsCodec()
31 { 31 {
32 } 32 }
33 33
  34 +bool SrsCodec::video_is_keyframe(int8_t* data, int size)
  35 +{
  36 + // E.4.3.1 VIDEODATA
  37 + // Frame Type UB [4]
  38 + // Type of video frame. The following values are defined:
  39 + // 1 = key frame (for AVC, a seekable frame)
  40 + // 2 = inter frame (for AVC, a non-seekable frame)
  41 + // 3 = disposable inter frame (H.263 only)
  42 + // 4 = generated key frame (reserved for server use only)
  43 + // 5 = video info/command frame
  44 + //
  45 + // AVCPacketType IF CodecID == 7 UI8
  46 + // The following values are defined:
  47 + // 0 = AVC sequence header
  48 + // 1 = AVC NALU
  49 + // 2 = AVC end of sequence (lower level NALU sequence ender is
  50 + // not required or supported)
  51 +
  52 + // 2bytes required.
  53 + if (size < 1) {
  54 + return false;
  55 + }
  56 +
  57 + char frame_type = *(char*)data;
  58 + frame_type = (frame_type >> 4) & 0x0F;
  59 +
  60 + return frame_type == 1;
  61 +}
  62 +
34 bool SrsCodec::video_is_sequence_header(int8_t* data, int size) 63 bool SrsCodec::video_is_sequence_header(int8_t* data, int size)
35 { 64 {
36 // E.4.3.1 VIDEODATA 65 // E.4.3.1 VIDEODATA
@@ -40,10 +40,26 @@ public: @@ -40,10 +40,26 @@ public:
40 SrsCodec(); 40 SrsCodec();
41 virtual ~SrsCodec(); 41 virtual ~SrsCodec();
42 public: 42 public:
  43 + /**
  44 + * only check the frame_type, not check the codec type.
  45 + */
  46 + virtual bool video_is_keyframe(int8_t* data, int size);
  47 + /**
  48 + * check codec h264, keyframe, sequence header
  49 + */
43 virtual bool video_is_sequence_header(int8_t* data, int size); 50 virtual bool video_is_sequence_header(int8_t* data, int size);
  51 + /**
  52 + * check codec aac, sequence header
  53 + */
44 virtual bool audio_is_sequence_header(int8_t* data, int size); 54 virtual bool audio_is_sequence_header(int8_t* data, int size);
45 -private: 55 + /**
  56 + * check codec h264.
  57 + */
46 virtual bool video_is_h264(int8_t* data, int size); 58 virtual bool video_is_h264(int8_t* data, int size);
  59 +private:
  60 + /**
  61 + * check codec aac.
  62 + */
47 virtual bool audio_is_aac(int8_t* data, int size); 63 virtual bool audio_is_aac(int8_t* data, int size);
48 }; 64 };
49 65
@@ -64,6 +64,11 @@ SrsConsumer::~SrsConsumer() @@ -64,6 +64,11 @@ SrsConsumer::~SrsConsumer()
64 source->on_consumer_destroy(this); 64 source->on_consumer_destroy(this);
65 } 65 }
66 66
  67 +int SrsConsumer::get_time()
  68 +{
  69 + return (int)last_pkt_correct_time;
  70 +}
  71 +
67 int SrsConsumer::enqueue(SrsSharedPtrMessage* msg) 72 int SrsConsumer::enqueue(SrsSharedPtrMessage* msg)
68 { 73 {
69 int ret = ERROR_SUCCESS; 74 int ret = ERROR_SUCCESS;
@@ -144,10 +149,12 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg) @@ -144,10 +149,12 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg)
144 SrsSource::SrsSource(std::string _stream_url) 149 SrsSource::SrsSource(std::string _stream_url)
145 { 150 {
146 stream_url = _stream_url; 151 stream_url = _stream_url;
147 - cache_metadata = NULL;  
148 - cache_sh_video = NULL;  
149 - cache_sh_audio = NULL;  
150 codec = new SrsCodec(); 152 codec = new SrsCodec();
  153 +
  154 + cache_metadata = cache_sh_video = cache_sh_audio = NULL;
  155 +
  156 + cached_video_count = 0;
  157 + enable_gop_cache = true;
151 } 158 }
152 159
153 SrsSource::~SrsSource() 160 SrsSource::~SrsSource()
@@ -159,6 +166,8 @@ SrsSource::~SrsSource() @@ -159,6 +166,8 @@ SrsSource::~SrsSource()
159 } 166 }
160 consumers.clear(); 167 consumers.clear();
161 168
  169 + clear_gop_cache();
  170 +
162 srs_freep(cache_metadata); 171 srs_freep(cache_metadata);
163 srs_freep(cache_sh_video); 172 srs_freep(cache_sh_video);
164 srs_freep(cache_sh_audio); 173 srs_freep(cache_sh_audio);
@@ -246,8 +255,16 @@ int SrsSource::on_audio(SrsCommonMessage* audio) @@ -246,8 +255,16 @@ int SrsSource::on_audio(SrsCommonMessage* audio)
246 if (codec->audio_is_sequence_header(msg->payload, msg->size)) { 255 if (codec->audio_is_sequence_header(msg->payload, msg->size)) {
247 srs_freep(cache_sh_audio); 256 srs_freep(cache_sh_audio);
248 cache_sh_audio = msg->copy(); 257 cache_sh_audio = msg->copy();
  258 + return ret;
249 } 259 }
250 260
  261 + // cache the last gop packets
  262 + if ((ret = cache_last_gop(msg)) != ERROR_SUCCESS) {
  263 + srs_error("shrink gop cache failed. ret=%d", ret);
  264 + return ret;
  265 + }
  266 + srs_verbose("cache gop success.");
  267 +
251 return ret; 268 return ret;
252 } 269 }
253 270
@@ -282,7 +299,15 @@ int SrsSource::on_video(SrsCommonMessage* video) @@ -282,7 +299,15 @@ int SrsSource::on_video(SrsCommonMessage* video)
282 if (codec->video_is_sequence_header(msg->payload, msg->size)) { 299 if (codec->video_is_sequence_header(msg->payload, msg->size)) {
283 srs_freep(cache_sh_video); 300 srs_freep(cache_sh_video);
284 cache_sh_video = msg->copy(); 301 cache_sh_video = msg->copy();
  302 + return ret;
285 } 303 }
  304 +
  305 + // cache the last gop packets
  306 + if ((ret = cache_last_gop(msg)) != ERROR_SUCCESS) {
  307 + srs_error("shrink gop cache failed. ret=%d", ret);
  308 + return ret;
  309 + }
  310 + srs_verbose("cache gop success.");
286 311
287 return ret; 312 return ret;
288 } 313 }
@@ -312,6 +337,16 @@ int SrsSource::on_video(SrsCommonMessage* video) @@ -312,6 +337,16 @@ int SrsSource::on_video(SrsCommonMessage* video)
312 } 337 }
313 srs_info("dispatch audio sequence header success"); 338 srs_info("dispatch audio sequence header success");
314 339
  340 + std::vector<SrsSharedPtrMessage*>::iterator it;
  341 + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
  342 + SrsSharedPtrMessage* msg = *it;
  343 + if ((ret = consumer->enqueue(msg->copy())) != ERROR_SUCCESS) {
  344 + srs_error("dispatch cached gop failed. ret=%d", ret);
  345 + return ret;
  346 + }
  347 + }
  348 + srs_trace("dispatch cached gop success. count=%d, duration=%d", (int)gop_cache.size(), consumer->get_time());
  349 +
315 return ret; 350 return ret;
316 } 351 }
317 352
@@ -325,3 +360,58 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer) @@ -325,3 +360,58 @@ void SrsSource::on_consumer_destroy(SrsConsumer* consumer)
325 srs_info("handle consumer destroy success."); 360 srs_info("handle consumer destroy success.");
326 } 361 }
327 362
  363 +void SrsSource::on_unpublish()
  364 +{
  365 + clear_gop_cache();
  366 + srs_trace("clear cache when unpublish.");
  367 +}
  368 +
  369 +int SrsSource::cache_last_gop(SrsSharedPtrMessage* msg)
  370 +{
  371 + int ret = ERROR_SUCCESS;
  372 +
  373 + if (!enable_gop_cache) {
  374 + srs_verbose("gop cache is disabled.");
  375 + return ret;
  376 + }
  377 +
  378 + // got video, update the video count if acceptable
  379 + if (msg->header.is_video()) {
  380 + cached_video_count++;
  381 + }
  382 +
  383 + // no acceptable video or pure audio, disable the cache.
  384 + if (cached_video_count == 0) {
  385 + srs_verbose("ignore any frame util got a h264 video frame.");
  386 + return ret;
  387 + }
  388 +
  389 + // clear gop cache when got key frame
  390 + if (msg->header.is_video() && codec->video_is_keyframe(msg->payload, msg->size)) {
  391 + srs_info("clear gop cache when got keyframe. vcount=%d, count=%d",
  392 + cached_video_count, (int)gop_cache.size());
  393 +
  394 + clear_gop_cache();
  395 +
  396 + // curent msg is video frame, so we set to 1.
  397 + cached_video_count = 1;
  398 + }
  399 +
  400 + // cache the frame.
  401 + gop_cache.push_back(msg->copy());
  402 +
  403 + return ret;
  404 +}
  405 +
  406 +void SrsSource::clear_gop_cache()
  407 +{
  408 + std::vector<SrsSharedPtrMessage*>::iterator it;
  409 + for (it = gop_cache.begin(); it != gop_cache.end(); ++it) {
  410 + SrsSharedPtrMessage* msg = *it;
  411 + srs_freep(msg);
  412 + }
  413 + gop_cache.clear();
  414 +
  415 + cached_video_count = 0;
  416 +}
  417 +
@@ -55,6 +55,10 @@ public: @@ -55,6 +55,10 @@ public:
55 virtual ~SrsConsumer(); 55 virtual ~SrsConsumer();
56 public: 56 public:
57 /** 57 /**
  58 + * get current client time, the last packet time.
  59 + */
  60 + virtual int get_time();
  61 + /**
58 * enqueue an shared ptr message. 62 * enqueue an shared ptr message.
59 */ 63 */
60 virtual int enqueue(SrsSharedPtrMessage* msg); 64 virtual int enqueue(SrsSharedPtrMessage* msg);
@@ -92,6 +96,22 @@ private: @@ -92,6 +96,22 @@ private:
92 SrsCodec* codec; 96 SrsCodec* codec;
93 std::string stream_url; 97 std::string stream_url;
94 std::vector<SrsConsumer*> consumers; 98 std::vector<SrsConsumer*> consumers;
  99 +// gop cache for client fast startup.
  100 +private:
  101 + /**
  102 + * if disabled the gop cache,
  103 + * the client will wait for the next keyframe for h264,
  104 + * and will be black-screen.
  105 + */
  106 + bool enable_gop_cache;
  107 + /**
  108 + * the video frame count, avoid cache for pure audio stream.
  109 + */
  110 + int cached_video_count;
  111 + /**
  112 + * cached gop.
  113 + */
  114 + std::vector<SrsSharedPtrMessage*> gop_cache;
95 private: 115 private:
96 SrsSharedPtrMessage* cache_metadata; 116 SrsSharedPtrMessage* cache_metadata;
97 // the cached video sequence header. 117 // the cached video sequence header.
@@ -108,6 +128,15 @@ public: @@ -108,6 +128,15 @@ public:
108 public: 128 public:
109 virtual int create_consumer(SrsConsumer*& consumer); 129 virtual int create_consumer(SrsConsumer*& consumer);
110 virtual void on_consumer_destroy(SrsConsumer* consumer); 130 virtual void on_consumer_destroy(SrsConsumer* consumer);
  131 + virtual void on_unpublish();
  132 +private:
  133 + /**
  134 + * only for h264 codec
  135 + * 1. cache the gop when got h264 video packet.
  136 + * 2. clear gop when got keyframe.
  137 + */
  138 + virtual int cache_last_gop(SrsSharedPtrMessage* msg);
  139 + virtual void clear_gop_cache();
111 }; 140 };
112 141
113 #endif 142 #endif