winlin

support pause for live stream.

@@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream @@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream
48 * nginx v1.5.0: 139524 lines <br/> 48 * nginx v1.5.0: 139524 lines <br/>
49 49
50 ### History 50 ### History
  51 +* v0.4, 2013-11-09, support pause for live stream.
51 * v0.3, 2013-11-04, v0.3 released. 11773 lines. 52 * v0.3, 2013-11-04, v0.3 released. 11773 lines.
52 * v0.3, 2013-11-04, support refer/play-refer/publish-refer. 53 * v0.3, 2013-11-04, support refer/play-refer/publish-refer.
53 * v0.3, 2013-11-04, support vhosts specified config. 54 * v0.3, 2013-11-04, support vhosts specified config.
@@ -63,7 +63,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -63,7 +63,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
63 (void)0 63 (void)0
64 64
65 // current release version 65 // current release version
66 -#define RTMP_SIG_SRS_VERSION "0.2.0" 66 +#define RTMP_SIG_SRS_VERSION "0.3.0"
67 // server info. 67 // server info.
68 #define RTMP_SIG_SRS_KEY "srs" 68 #define RTMP_SIG_SRS_KEY "srs"
69 #define RTMP_SIG_SRS_ROLE "origin server" 69 #define RTMP_SIG_SRS_ROLE "origin server"
@@ -270,10 +270,9 @@ int SrsClient::playing(SrsSource* source) @@ -270,10 +270,9 @@ int SrsClient::playing(SrsSource* source)
270 srs_error("recv client control message failed. ret=%d", ret); 270 srs_error("recv client control message failed. ret=%d", ret);
271 return ret; 271 return ret;
272 } 272 }
273 - if (ret == ERROR_SUCCESS && !msg) {  
274 - srs_info("play loop got a message.");  
275 - SrsAutoFree(SrsCommonMessage, msg, false);  
276 - // TODO: process it. 273 + if ((ret = process_play_control_msg(consumer, msg)) != ERROR_SUCCESS) {
  274 + srs_error("process play control message failed. ret=%d", ret);
  275 + return ret;
277 } 276 }
278 } 277 }
279 278
@@ -442,3 +441,44 @@ int SrsClient::get_peer_ip() @@ -442,3 +441,44 @@ int SrsClient::get_peer_ip()
442 return ret; 441 return ret;
443 } 442 }
444 443
  444 +int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg)
  445 +{
  446 + int ret = ERROR_SUCCESS;
  447 +
  448 + if (!msg) {
  449 + srs_verbose("ignore all empty message.");
  450 + return ret;
  451 + }
  452 + SrsAutoFree(SrsCommonMessage, msg, false);
  453 +
  454 + if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) {
  455 + srs_info("ignore all message except amf0/amf3 command.");
  456 + return ret;
  457 + }
  458 +
  459 + if ((ret = msg->decode_packet()) != ERROR_SUCCESS) {
  460 + srs_error("decode the amf0/amf3 command packet failed. ret=%d", ret);
  461 + return ret;
  462 + }
  463 + srs_info("decode the amf0/amf3 command packet success.");
  464 +
  465 + SrsPausePacket* pause = dynamic_cast<SrsPausePacket*>(msg->get_packet());
  466 + if (!pause) {
  467 + srs_info("ignore all amf0/amf3 command except pause.");
  468 + return ret;
  469 + }
  470 +
  471 + if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) {
  472 + srs_error("rtmp process play client pause failed. ret=%d", ret);
  473 + return ret;
  474 + }
  475 +
  476 + if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) {
  477 + srs_error("consumer process play client pause failed. ret=%d", ret);
  478 + return ret;
  479 + }
  480 + srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms);
  481 +
  482 + return ret;
  483 +}
  484 +
@@ -37,6 +37,8 @@ class SrsRequest; @@ -37,6 +37,8 @@ class SrsRequest;
37 class SrsResponse; 37 class SrsResponse;
38 class SrsSource; 38 class SrsSource;
39 class SrsRefer; 39 class SrsRefer;
  40 +class SrsConsumer;
  41 +class SrsCommonMessage;
40 42
41 /** 43 /**
42 * the client provides the main logic control for RTMP clients. 44 * the client provides the main logic control for RTMP clients.
@@ -59,6 +61,7 @@ private: @@ -59,6 +61,7 @@ private:
59 virtual int playing(SrsSource* source); 61 virtual int playing(SrsSource* source);
60 virtual int publish(SrsSource* source, bool is_fmle); 62 virtual int publish(SrsSource* source, bool is_fmle);
61 virtual int get_peer_ip(); 63 virtual int get_peer_ip();
  64 + virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
62 }; 65 };
63 66
64 #endif 67 #endif
@@ -195,6 +195,7 @@ messages. @@ -195,6 +195,7 @@ messages.
195 #define RTMP_AMF0_COMMAND_CONNECT "connect" 195 #define RTMP_AMF0_COMMAND_CONNECT "connect"
196 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" 196 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"
197 #define RTMP_AMF0_COMMAND_PLAY "play" 197 #define RTMP_AMF0_COMMAND_PLAY "play"
  198 +#define RTMP_AMF0_COMMAND_PAUSE "pause"
198 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" 199 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
199 #define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" 200 #define RTMP_AMF0_COMMAND_ON_STATUS "onStatus"
200 #define RTMP_AMF0_COMMAND_RESULT "_result" 201 #define RTMP_AMF0_COMMAND_RESULT "_result"
@@ -1219,6 +1220,10 @@ int SrsCommonMessage::decode_packet() @@ -1219,6 +1220,10 @@ int SrsCommonMessage::decode_packet()
1219 srs_info("decode the AMF0/AMF3 command(paly message)."); 1220 srs_info("decode the AMF0/AMF3 command(paly message).");
1220 packet = new SrsPlayPacket(); 1221 packet = new SrsPlayPacket();
1221 return packet->decode(stream); 1222 return packet->decode(stream);
  1223 + } else if(command == RTMP_AMF0_COMMAND_PAUSE) {
  1224 + srs_info("decode the AMF0/AMF3 command(pause message).");
  1225 + packet = new SrsPausePacket();
  1226 + return packet->decode(stream);
1222 } else if(command == RTMP_AMF0_COMMAND_RELEASE_STREAM) { 1227 } else if(command == RTMP_AMF0_COMMAND_RELEASE_STREAM) {
1223 srs_info("decode the AMF0/AMF3 command(FMLE releaseStream message)."); 1228 srs_info("decode the AMF0/AMF3 command(FMLE releaseStream message).");
1224 packet = new SrsFMLEStartPacket(); 1229 packet = new SrsFMLEStartPacket();
@@ -1896,6 +1901,61 @@ int SrsPublishPacket::decode(SrsStream* stream) @@ -1896,6 +1901,61 @@ int SrsPublishPacket::decode(SrsStream* stream)
1896 return ret; 1901 return ret;
1897 } 1902 }
1898 1903
  1904 +SrsPausePacket::SrsPausePacket()
  1905 +{
  1906 + command_name = RTMP_AMF0_COMMAND_PAUSE;
  1907 + transaction_id = 0;
  1908 + command_object = new SrsAmf0Null();
  1909 +
  1910 + time_ms = 0;
  1911 + is_pause = true;
  1912 +}
  1913 +
  1914 +SrsPausePacket::~SrsPausePacket()
  1915 +{
  1916 + srs_freep(command_object);
  1917 +}
  1918 +
  1919 +int SrsPausePacket::decode(SrsStream* stream)
  1920 +{
  1921 + int ret = ERROR_SUCCESS;
  1922 +
  1923 + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
  1924 + srs_error("amf0 decode pause command_name failed. ret=%d", ret);
  1925 + return ret;
  1926 + }
  1927 + if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PAUSE) {
  1928 + ret = ERROR_RTMP_AMF0_DECODE;
  1929 + srs_error("amf0 decode pause command_name failed. "
  1930 + "command_name=%s, ret=%d", command_name.c_str(), ret);
  1931 + return ret;
  1932 + }
  1933 +
  1934 + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
  1935 + srs_error("amf0 decode pause transaction_id failed. ret=%d", ret);
  1936 + return ret;
  1937 + }
  1938 +
  1939 + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
  1940 + srs_error("amf0 decode pause command_object failed. ret=%d", ret);
  1941 + return ret;
  1942 + }
  1943 +
  1944 + if ((ret = srs_amf0_read_boolean(stream, is_pause)) != ERROR_SUCCESS) {
  1945 + srs_error("amf0 decode pause is_pause failed. ret=%d", ret);
  1946 + return ret;
  1947 + }
  1948 +
  1949 + if ((ret = srs_amf0_read_number(stream, time_ms)) != ERROR_SUCCESS) {
  1950 + srs_error("amf0 decode pause time_ms failed. ret=%d", ret);
  1951 + return ret;
  1952 + }
  1953 +
  1954 + srs_info("amf0 decode pause packet success");
  1955 +
  1956 + return ret;
  1957 +}
  1958 +
1899 SrsPlayPacket::SrsPlayPacket() 1959 SrsPlayPacket::SrsPlayPacket()
1900 { 1960 {
1901 command_name = RTMP_AMF0_COMMAND_PLAY; 1961 command_name = RTMP_AMF0_COMMAND_PLAY;
@@ -637,6 +637,33 @@ public: @@ -637,6 +637,33 @@ public:
637 }; 637 };
638 638
639 /** 639 /**
  640 +* 4.2.8. pause
  641 +* The client sends the pause command to tell the server to pause or
  642 +* start playing.
  643 +*/
  644 +class SrsPausePacket : public SrsPacket
  645 +{
  646 +private:
  647 + typedef SrsPacket super;
  648 +protected:
  649 + virtual const char* get_class_name()
  650 + {
  651 + return CLASS_NAME_STRING(SrsPausePacket);
  652 + }
  653 +public:
  654 + std::string command_name;
  655 + double transaction_id;
  656 + SrsAmf0Null* command_object;
  657 + bool is_pause;
  658 + double time_ms;
  659 +public:
  660 + SrsPausePacket();
  661 + virtual ~SrsPausePacket();
  662 +public:
  663 + virtual int decode(SrsStream* stream);
  664 +};
  665 +
  666 +/**
640 * 4.2.1. play 667 * 4.2.1. play
641 * The client sends this command to the server to play a stream. 668 * The client sends this command to the server to play a stream.
642 */ 669 */
@@ -960,12 +987,12 @@ protected: @@ -960,12 +987,12 @@ protected:
960 enum SrcPCUCEventType 987 enum SrcPCUCEventType
961 { 988 {
962 // generally, 4bytes event-data 989 // generally, 4bytes event-data
963 - SrcPCUCStreamBegin = 0x00, 990 + SrcPCUCStreamBegin = 0x00,
964 SrcPCUCStreamEOF = 0x01, 991 SrcPCUCStreamEOF = 0x01,
965 SrcPCUCStreamDry = 0x02, 992 SrcPCUCStreamDry = 0x02,
966 - SrcPCUCSetBufferLength = 0x03, // 8bytes event-data 993 + SrcPCUCSetBufferLength = 0x03, // 8bytes event-data
967 SrcPCUCStreamIsRecorded = 0x04, 994 SrcPCUCStreamIsRecorded = 0x04,
968 - SrcPCUCPingRequest = 0x06, 995 + SrcPCUCPingRequest = 0x06,
969 SrcPCUCPingResponse = 0x07, 996 SrcPCUCPingResponse = 0x07,
970 }; 997 };
971 998
@@ -34,34 +34,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,34 +34,36 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 /** 34 /**
35 * the signature for packets to client. 35 * the signature for packets to client.
36 */ 36 */
37 -#define RTMP_SIG_FMS_VER "3,5,3,888"  
38 -#define RTMP_SIG_AMF0_VER 0  
39 -#define RTMP_SIG_CLIENT_ID "ASAICiss" 37 +#define RTMP_SIG_FMS_VER "3,5,3,888"
  38 +#define RTMP_SIG_AMF0_VER 0
  39 +#define RTMP_SIG_CLIENT_ID "ASAICiss"
40 40
41 /** 41 /**
42 * onStatus consts. 42 * onStatus consts.
43 */ 43 */
44 -#define StatusLevel "level"  
45 -#define StatusCode "code"  
46 -#define StatusDescription "description"  
47 -#define StatusDetails "details"  
48 -#define StatusClientId "clientid" 44 +#define StatusLevel "level"
  45 +#define StatusCode "code"
  46 +#define StatusDescription "description"
  47 +#define StatusDetails "details"
  48 +#define StatusClientId "clientid"
49 // status value 49 // status value
50 -#define StatusLevelStatus "status" 50 +#define StatusLevelStatus "status"
51 // code value 51 // code value
52 -#define StatusCodeConnectSuccess "NetConnection.Connect.Success"  
53 -#define StatusCodeStreamReset "NetStream.Play.Reset"  
54 -#define StatusCodeStreamStart "NetStream.Play.Start"  
55 -#define StatusCodePublishStart "NetStream.Publish.Start"  
56 -#define StatusCodeDataStart "NetStream.Data.Start"  
57 -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" 52 +#define StatusCodeConnectSuccess "NetConnection.Connect.Success"
  53 +#define StatusCodeStreamReset "NetStream.Play.Reset"
  54 +#define StatusCodeStreamStart "NetStream.Play.Start"
  55 +#define StatusCodeStreamPause "NetStream.Pause.Notify"
  56 +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify"
  57 +#define StatusCodePublishStart "NetStream.Publish.Start"
  58 +#define StatusCodeDataStart "NetStream.Data.Start"
  59 +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success"
58 60
59 // FMLE 61 // FMLE
60 #define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" 62 #define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish"
61 #define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" 63 #define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish"
62 64
63 // default stream id for response the createStream request. 65 // default stream id for response the createStream request.
64 -#define SRS_DEFAULT_SID 1 66 +#define SRS_DEFAULT_SID 1
65 67
66 SrsRequest::SrsRequest() 68 SrsRequest::SrsRequest()
67 { 69 {
@@ -570,6 +572,81 @@ int SrsRtmp::start_play(int stream_id) @@ -570,6 +572,81 @@ int SrsRtmp::start_play(int stream_id)
570 return ret; 572 return ret;
571 } 573 }
572 574
  575 +int SrsRtmp::on_play_client_pause(int stream_id, bool is_pause)
  576 +{
  577 + int ret = ERROR_SUCCESS;
  578 +
  579 + if (is_pause) {
  580 + // onStatus(NetStream.Pause.Notify)
  581 + if (true) {
  582 + SrsCommonMessage* msg = new SrsCommonMessage();
  583 + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
  584 +
  585 + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
  586 + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamPause));
  587 + pkt->data->set(StatusDescription, new SrsAmf0String("Paused stream."));
  588 +
  589 + msg->set_packet(pkt, stream_id);
  590 +
  591 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  592 + srs_error("send onStatus(NetStream.Pause.Notify) message failed. ret=%d", ret);
  593 + return ret;
  594 + }
  595 + srs_info("send onStatus(NetStream.Pause.Notify) message success.");
  596 + }
  597 + // StreamEOF
  598 + if (true) {
  599 + SrsCommonMessage* msg = new SrsCommonMessage();
  600 + SrsUserControlPacket* pkt = new SrsUserControlPacket();
  601 +
  602 + pkt->event_type = SrcPCUCStreamEOF;
  603 + pkt->event_data = stream_id;
  604 + msg->set_packet(pkt, 0);
  605 +
  606 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  607 + srs_error("send PCUC(StreamEOF) message failed. ret=%d", ret);
  608 + return ret;
  609 + }
  610 + srs_info("send PCUC(StreamEOF) message success.");
  611 + }
  612 + } else {
  613 + // onStatus(NetStream.Unpause.Notify)
  614 + if (true) {
  615 + SrsCommonMessage* msg = new SrsCommonMessage();
  616 + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
  617 +
  618 + pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
  619 + pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamUnpause));
  620 + pkt->data->set(StatusDescription, new SrsAmf0String("Unpaused stream."));
  621 +
  622 + msg->set_packet(pkt, stream_id);
  623 +
  624 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  625 + srs_error("send onStatus(NetStream.Unpause.Notify) message failed. ret=%d", ret);
  626 + return ret;
  627 + }
  628 + srs_info("send onStatus(NetStream.Unpause.Notify) message success.");
  629 + }
  630 + // StreanBegin
  631 + if (true) {
  632 + SrsCommonMessage* msg = new SrsCommonMessage();
  633 + SrsUserControlPacket* pkt = new SrsUserControlPacket();
  634 +
  635 + pkt->event_type = SrcPCUCStreamBegin;
  636 + pkt->event_data = stream_id;
  637 + msg->set_packet(pkt, 0);
  638 +
  639 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  640 + srs_error("send PCUC(StreanBegin) message failed. ret=%d", ret);
  641 + return ret;
  642 + }
  643 + srs_info("send PCUC(StreanBegin) message success.");
  644 + }
  645 + }
  646 +
  647 + return ret;
  648 +}
  649 +
573 int SrsRtmp::start_fmle_publish(int stream_id) 650 int SrsRtmp::start_fmle_publish(int stream_id)
574 { 651 {
575 int ret = ERROR_SUCCESS; 652 int ret = ERROR_SUCCESS;
@@ -148,6 +148,16 @@ public: @@ -148,6 +148,16 @@ public:
148 */ 148 */
149 virtual int start_play(int stream_id); 149 virtual int start_play(int stream_id);
150 /** 150 /**
  151 + * when client(type is play) send pause message,
  152 + * if is_pause, response the following packets:
  153 + * onStatus(NetStream.Pause.Notify)
  154 + * StreamEOF
  155 + * if not is_pause, response the following packets:
  156 + * onStatus(NetStream.Unpause.Notify)
  157 + * StreamBegin
  158 + */
  159 + virtual int on_play_client_pause(int stream_id, bool is_pause);
  160 + /**
151 * when client type is publish, response with packets: 161 * when client type is publish, response with packets:
152 * releaseStream response 162 * releaseStream response
153 * FCPublish 163 * FCPublish
@@ -31,8 +31,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,8 +31,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #include <srs_core_amf0.hpp> 31 #include <srs_core_amf0.hpp>
32 #include <srs_core_codec.hpp> 32 #include <srs_core_codec.hpp>
33 33
34 -#define CONST_MAX_JITTER_MS 500  
35 -#define DEFAULT_FRAME_TIME_MS 10 34 +#define CONST_MAX_JITTER_MS 500
  35 +#define DEFAULT_FRAME_TIME_MS 10
  36 +#define PAUSED_SHRINK_SIZE 250
36 37
37 std::map<std::string, SrsSource*> SrsSource::pool; 38 std::map<std::string, SrsSource*> SrsSource::pool;
38 39
@@ -50,16 +51,14 @@ SrsConsumer::SrsConsumer(SrsSource* _source) @@ -50,16 +51,14 @@ SrsConsumer::SrsConsumer(SrsSource* _source)
50 { 51 {
51 source = _source; 52 source = _source;
52 last_pkt_correct_time = last_pkt_time = 0; 53 last_pkt_correct_time = last_pkt_time = 0;
  54 + paused = false;
  55 + codec = new SrsCodec();
53 } 56 }
54 57
55 SrsConsumer::~SrsConsumer() 58 SrsConsumer::~SrsConsumer()
56 { 59 {
57 - std::vector<SrsSharedPtrMessage*>::iterator it;  
58 - for (it = msgs.begin(); it != msgs.end(); ++it) {  
59 - SrsSharedPtrMessage* msg = *it;  
60 - srs_freep(msg);  
61 - }  
62 - msgs.clear(); 60 + clear();
  61 + srs_freep(codec);
63 62
64 source->on_consumer_destroy(this); 63 source->on_consumer_destroy(this);
65 } 64 }
@@ -89,6 +88,13 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c @@ -89,6 +88,13 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c
89 if (msgs.empty()) { 88 if (msgs.empty()) {
90 return ret; 89 return ret;
91 } 90 }
  91 +
  92 + if (paused) {
  93 + if ((int)msgs.size() >= PAUSED_SHRINK_SIZE) {
  94 + shrink();
  95 + }
  96 + return ret;
  97 + }
92 98
93 if (max_count == 0) { 99 if (max_count == 0) {
94 count = (int)msgs.size(); 100 count = (int)msgs.size();
@@ -111,6 +117,68 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c @@ -111,6 +117,68 @@ int SrsConsumer::get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& c
111 return ret; 117 return ret;
112 } 118 }
113 119
  120 +int SrsConsumer::on_play_client_pause(bool is_pause)
  121 +{
  122 + int ret = ERROR_SUCCESS;
  123 +
  124 + srs_trace("stream consumer change pause state %d=>%d", paused, is_pause);
  125 + paused = is_pause;
  126 +
  127 + return ret;
  128 +}
  129 +
  130 +void SrsConsumer::shrink()
  131 +{
  132 + int i = 0;
  133 + std::vector<SrsSharedPtrMessage*>::iterator it;
  134 +
  135 + // issue the last video iframe.
  136 + bool has_video = false;
  137 + int frame_to_remove = 0;
  138 + std::vector<SrsSharedPtrMessage*>::iterator iframe = msgs.end();
  139 + for (i = 0, it = msgs.begin(); it != msgs.end(); ++it, i++) {
  140 + SrsSharedPtrMessage* msg = *it;
  141 + if (msg->header.is_video()) {
  142 + has_video = true;
  143 + if (codec->video_is_keyframe(msg->payload, msg->size)) {
  144 + iframe = it;
  145 + frame_to_remove = i + 1;
  146 + }
  147 + }
  148 + }
  149 +
  150 + // last iframe is the first elem, ignore it.
  151 + if (iframe == msgs.begin()) {
  152 + return;
  153 + }
  154 +
  155 + // recalc the frame to remove
  156 + if (iframe == msgs.end()) {
  157 + frame_to_remove = 0;
  158 + }
  159 + if (!has_video) {
  160 + frame_to_remove = (int)msgs.size();
  161 + }
  162 +
  163 + srs_trace("shrink the cache queue, has_video=%d, has_iframe=%d, size=%d, removed=%d",
  164 + has_video, iframe != msgs.end(), (int)msgs.size(), frame_to_remove);
  165 +
  166 + // if no video, remove all audio.
  167 + if (!has_video) {
  168 + clear();
  169 + return;
  170 + }
  171 +
  172 + // if exists video Iframe, remove the frames before it.
  173 + if (iframe != msgs.end()) {
  174 + for (it = msgs.begin(); it != iframe; ++it) {
  175 + SrsSharedPtrMessage* msg = *it;
  176 + srs_freep(msg);
  177 + }
  178 + msgs.erase(msgs.begin(), iframe);
  179 + }
  180 +}
  181 +
114 int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate) 182 int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate)
115 { 183 {
116 int ret = ERROR_SUCCESS; 184 int ret = ERROR_SUCCESS;
@@ -156,6 +224,16 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate) @@ -156,6 +224,16 @@ int SrsConsumer::jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate)
156 return ret; 224 return ret;
157 } 225 }
158 226
  227 +void SrsConsumer::clear()
  228 +{
  229 + std::vector<SrsSharedPtrMessage*>::iterator it;
  230 + for (it = msgs.begin(); it != msgs.end(); ++it) {
  231 + SrsSharedPtrMessage* msg = *it;
  232 + srs_freep(msg);
  233 + }
  234 + msgs.clear();
  235 +}
  236 +
159 SrsSource::SrsSource(std::string _stream_url) 237 SrsSource::SrsSource(std::string _stream_url)
160 { 238 {
161 stream_url = _stream_url; 239 stream_url = _stream_url;
@@ -50,6 +50,8 @@ private: @@ -50,6 +50,8 @@ private:
50 int32_t last_pkt_correct_time; 50 int32_t last_pkt_correct_time;
51 SrsSource* source; 51 SrsSource* source;
52 std::vector<SrsSharedPtrMessage*> msgs; 52 std::vector<SrsSharedPtrMessage*> msgs;
  53 + bool paused;
  54 + SrsCodec* codec;
53 public: 55 public:
54 SrsConsumer(SrsSource* _source); 56 SrsConsumer(SrsSource* _source);
55 virtual ~SrsConsumer(); 57 virtual ~SrsConsumer();
@@ -69,11 +71,21 @@ public: @@ -69,11 +71,21 @@ public:
69 * @max_count the max count to dequeue, 0 to dequeue all. 71 * @max_count the max count to dequeue, 0 to dequeue all.
70 */ 72 */
71 virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count); 73 virtual int get_packets(int max_count, SrsSharedPtrMessage**& pmsgs, int& count);
  74 + /**
  75 + * when client send the pause message.
  76 + */
  77 + virtual int on_play_client_pause(bool is_pause);
72 private: 78 private:
73 /** 79 /**
  80 + * when paused, shrink the cache queue,
  81 + * remove to cache only one gop.
  82 + */
  83 + virtual void shrink();
  84 + /**
74 * detect the time jitter and correct it. 85 * detect the time jitter and correct it.
75 */ 86 */
76 virtual int jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate); 87 virtual int jitter_correct(SrsSharedPtrMessage* msg, int audio_sample_rate);
  88 + virtual void clear();
77 }; 89 };
78 90
79 /** 91 /**