winlin

support onStatus, RtmpSampleAccess, DataStart

@@ -195,7 +195,9 @@ messages. @@ -195,7 +195,9 @@ messages.
195 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" 195 #define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"
196 #define RTMP_AMF0_COMMAND_PLAY "play" 196 #define RTMP_AMF0_COMMAND_PLAY "play"
197 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" 197 #define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
  198 +#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus"
198 #define RTMP_AMF0_COMMAND_RESULT "_result" 199 #define RTMP_AMF0_COMMAND_RESULT "_result"
  200 +#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess"
199 201
200 /**************************************************************************** 202 /****************************************************************************
201 ***************************************************************************** 203 *****************************************************************************
@@ -483,7 +485,7 @@ int SrsProtocol::on_send_message(SrsMessage* msg) @@ -483,7 +485,7 @@ int SrsProtocol::on_send_message(SrsMessage* msg)
483 SrsSetChunkSizePacket* pkt = dynamic_cast<SrsSetChunkSizePacket*>(msg->get_packet()); 485 SrsSetChunkSizePacket* pkt = dynamic_cast<SrsSetChunkSizePacket*>(msg->get_packet());
484 srs_assert(pkt != NULL); 486 srs_assert(pkt != NULL);
485 487
486 - in_chunk_size = pkt->chunk_size; 488 + out_chunk_size = pkt->chunk_size;
487 489
488 srs_trace("set output chunk size to %d", pkt->chunk_size); 490 srs_trace("set output chunk size to %d", pkt->chunk_size);
489 break; 491 break;
@@ -1545,6 +1547,180 @@ int SrsOnBWDonePacket::encode_packet(SrsStream* stream) @@ -1545,6 +1547,180 @@ int SrsOnBWDonePacket::encode_packet(SrsStream* stream)
1545 return ret; 1547 return ret;
1546 } 1548 }
1547 1549
  1550 +SrsOnStatusCallPacket::SrsOnStatusCallPacket()
  1551 +{
  1552 + command_name = RTMP_AMF0_COMMAND_ON_STATUS;
  1553 + transaction_id = 0;
  1554 + args = new SrsAmf0Null();
  1555 + data = new SrsAmf0Object();
  1556 +}
  1557 +
  1558 +SrsOnStatusCallPacket::~SrsOnStatusCallPacket()
  1559 +{
  1560 + if (args) {
  1561 + delete args;
  1562 + args = NULL;
  1563 + }
  1564 +
  1565 + if (data) {
  1566 + delete data;
  1567 + data = NULL;
  1568 + }
  1569 +}
  1570 +
  1571 +int SrsOnStatusCallPacket::get_perfer_cid()
  1572 +{
  1573 + return RTMP_CID_OverStream;
  1574 +}
  1575 +
  1576 +int SrsOnStatusCallPacket::get_message_type()
  1577 +{
  1578 + return RTMP_MSG_AMF0CommandMessage;
  1579 +}
  1580 +
  1581 +int SrsOnStatusCallPacket::get_size()
  1582 +{
  1583 + return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()
  1584 + + srs_amf0_get_null_size() + srs_amf0_get_object_size(data);
  1585 +}
  1586 +
  1587 +int SrsOnStatusCallPacket::encode_packet(SrsStream* stream)
  1588 +{
  1589 + int ret = ERROR_SUCCESS;
  1590 +
  1591 + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
  1592 + srs_error("encode command_name failed. ret=%d", ret);
  1593 + return ret;
  1594 + }
  1595 + srs_verbose("encode command_name success.");
  1596 +
  1597 + if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) {
  1598 + srs_error("encode transaction_id failed. ret=%d", ret);
  1599 + return ret;
  1600 + }
  1601 + srs_verbose("encode transaction_id success.");
  1602 +
  1603 + if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) {
  1604 + srs_error("encode args failed. ret=%d", ret);
  1605 + return ret;
  1606 + }
  1607 + srs_verbose("encode args success.");;
  1608 +
  1609 + if ((ret = srs_amf0_write_object(stream, data)) != ERROR_SUCCESS) {
  1610 + srs_error("encode data failed. ret=%d", ret);
  1611 + return ret;
  1612 + }
  1613 + srs_verbose("encode data success.");
  1614 +
  1615 + srs_info("encode onStatus(Call) packet success.");
  1616 +
  1617 + return ret;
  1618 +}
  1619 +
  1620 +SrsOnStatusDataPacket::SrsOnStatusDataPacket()
  1621 +{
  1622 + command_name = RTMP_AMF0_COMMAND_ON_STATUS;
  1623 + data = new SrsAmf0Object();
  1624 +}
  1625 +
  1626 +SrsOnStatusDataPacket::~SrsOnStatusDataPacket()
  1627 +{
  1628 + if (data) {
  1629 + delete data;
  1630 + data = NULL;
  1631 + }
  1632 +}
  1633 +
  1634 +int SrsOnStatusDataPacket::get_perfer_cid()
  1635 +{
  1636 + return RTMP_CID_OverStream;
  1637 +}
  1638 +
  1639 +int SrsOnStatusDataPacket::get_message_type()
  1640 +{
  1641 + return RTMP_MSG_AMF0DataMessage;
  1642 +}
  1643 +
  1644 +int SrsOnStatusDataPacket::get_size()
  1645 +{
  1646 + return srs_amf0_get_string_size(command_name) + srs_amf0_get_object_size(data);
  1647 +}
  1648 +
  1649 +int SrsOnStatusDataPacket::encode_packet(SrsStream* stream)
  1650 +{
  1651 + int ret = ERROR_SUCCESS;
  1652 +
  1653 + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
  1654 + srs_error("encode command_name failed. ret=%d", ret);
  1655 + return ret;
  1656 + }
  1657 + srs_verbose("encode command_name success.");
  1658 +
  1659 + if ((ret = srs_amf0_write_object(stream, data)) != ERROR_SUCCESS) {
  1660 + srs_error("encode data failed. ret=%d", ret);
  1661 + return ret;
  1662 + }
  1663 + srs_verbose("encode data success.");
  1664 +
  1665 + srs_info("encode onStatus(Data) packet success.");
  1666 +
  1667 + return ret;
  1668 +}
  1669 +
  1670 +SrsSampleAccessPacket::SrsSampleAccessPacket()
  1671 +{
  1672 + command_name = RTMP_AMF0_DATA_SAMPLE_ACCESS;
  1673 + video_sample_access = false;
  1674 + audio_sample_access = false;
  1675 +}
  1676 +
  1677 +SrsSampleAccessPacket::~SrsSampleAccessPacket()
  1678 +{
  1679 +}
  1680 +
  1681 +int SrsSampleAccessPacket::get_perfer_cid()
  1682 +{
  1683 + return RTMP_CID_OverStream;
  1684 +}
  1685 +
  1686 +int SrsSampleAccessPacket::get_message_type()
  1687 +{
  1688 + return RTMP_MSG_AMF0DataMessage;
  1689 +}
  1690 +
  1691 +int SrsSampleAccessPacket::get_size()
  1692 +{
  1693 + return srs_amf0_get_string_size(command_name)
  1694 + + srs_amf0_get_boolean_size() + srs_amf0_get_boolean_size();
  1695 +}
  1696 +
  1697 +int SrsSampleAccessPacket::encode_packet(SrsStream* stream)
  1698 +{
  1699 + int ret = ERROR_SUCCESS;
  1700 +
  1701 + if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
  1702 + srs_error("encode command_name failed. ret=%d", ret);
  1703 + return ret;
  1704 + }
  1705 + srs_verbose("encode command_name success.");
  1706 +
  1707 + if ((ret = srs_amf0_write_boolean(stream, video_sample_access)) != ERROR_SUCCESS) {
  1708 + srs_error("encode video_sample_access failed. ret=%d", ret);
  1709 + return ret;
  1710 + }
  1711 + srs_verbose("encode video_sample_access success.");
  1712 +
  1713 + if ((ret = srs_amf0_write_boolean(stream, audio_sample_access)) != ERROR_SUCCESS) {
  1714 + srs_error("encode audio_sample_access failed. ret=%d", ret);
  1715 + return ret;
  1716 + }
  1717 + srs_verbose("encode audio_sample_access success.");;
  1718 +
  1719 + srs_info("encode |RtmpSampleAccess packet success.");
  1720 +
  1721 + return ret;
  1722 +}
  1723 +
1548 SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket() 1724 SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket()
1549 { 1725 {
1550 ackowledgement_window_size = 0; 1726 ackowledgement_window_size = 0;
@@ -280,12 +280,18 @@ protected: @@ -280,12 +280,18 @@ protected:
280 public: 280 public:
281 SrsPacket(); 281 SrsPacket();
282 virtual ~SrsPacket(); 282 virtual ~SrsPacket();
  283 +/**
  284 +* decode functions.
  285 +*/
283 public: 286 public:
284 /** 287 /**
285 * subpacket must override to decode packet from stream. 288 * subpacket must override to decode packet from stream.
286 * @remark never invoke the super.decode, it always failed. 289 * @remark never invoke the super.decode, it always failed.
287 */ 290 */
288 virtual int decode(SrsStream* stream); 291 virtual int decode(SrsStream* stream);
  292 +/**
  293 +* encode functions.
  294 +*/
289 public: 295 public:
290 virtual int get_perfer_cid(); 296 virtual int get_perfer_cid();
291 virtual int get_payload_length(); 297 virtual int get_payload_length();
@@ -507,6 +513,93 @@ protected: @@ -507,6 +513,93 @@ protected:
507 }; 513 };
508 514
509 /** 515 /**
  516 +* onStatus command, AMF0 Call
  517 +* @remark, user must set the stream_id in header.
  518 +*/
  519 +class SrsOnStatusCallPacket : public SrsPacket
  520 +{
  521 +private:
  522 + typedef SrsPacket super;
  523 +protected:
  524 + virtual const char* get_class_name()
  525 + {
  526 + return CLASS_NAME_STRING(SrsOnStatusCallPacket);
  527 + }
  528 +public:
  529 + std::string command_name;
  530 + double transaction_id;
  531 + SrsAmf0Null* args;
  532 + SrsAmf0Object* data;
  533 +public:
  534 + SrsOnStatusCallPacket();
  535 + virtual ~SrsOnStatusCallPacket();
  536 +public:
  537 + virtual int get_perfer_cid();
  538 +public:
  539 + virtual int get_message_type();
  540 +protected:
  541 + virtual int get_size();
  542 + virtual int encode_packet(SrsStream* stream);
  543 +};
  544 +
  545 +/**
  546 +* onStatus data, AMF0 Data
  547 +* @remark, user must set the stream_id in header.
  548 +*/
  549 +class SrsOnStatusDataPacket : public SrsPacket
  550 +{
  551 +private:
  552 + typedef SrsPacket super;
  553 +protected:
  554 + virtual const char* get_class_name()
  555 + {
  556 + return CLASS_NAME_STRING(SrsOnStatusDataPacket);
  557 + }
  558 +public:
  559 + std::string command_name;
  560 + SrsAmf0Object* data;
  561 +public:
  562 + SrsOnStatusDataPacket();
  563 + virtual ~SrsOnStatusDataPacket();
  564 +public:
  565 + virtual int get_perfer_cid();
  566 +public:
  567 + virtual int get_message_type();
  568 +protected:
  569 + virtual int get_size();
  570 + virtual int encode_packet(SrsStream* stream);
  571 +};
  572 +
  573 +/**
  574 +* AMF0Data RtmpSampleAccess
  575 +* @remark, user must set the stream_id in header.
  576 +*/
  577 +class SrsSampleAccessPacket : public SrsPacket
  578 +{
  579 +private:
  580 + typedef SrsPacket super;
  581 +protected:
  582 + virtual const char* get_class_name()
  583 + {
  584 + return CLASS_NAME_STRING(SrsSampleAccessPacket);
  585 + }
  586 +public:
  587 + std::string command_name;
  588 + bool video_sample_access;
  589 + bool audio_sample_access;
  590 +public:
  591 + SrsSampleAccessPacket();
  592 + virtual ~SrsSampleAccessPacket();
  593 +public:
  594 + virtual int get_perfer_cid();
  595 +public:
  596 + virtual int get_message_type();
  597 +protected:
  598 + virtual int get_size();
  599 + virtual int encode_packet(SrsStream* stream);
  600 +};
  601 +
  602 +/**
510 * 5.5. Window Acknowledgement Size (5) 603 * 5.5. Window Acknowledgement Size (5)
511 * The client or the server sends this message to inform the peer which 604 * The client or the server sends this message to inform the peer which
512 * window size to use when sending acknowledgment. 605 * window size to use when sending acknowledgment.
@@ -595,6 +688,7 @@ protected: @@ -595,6 +688,7 @@ protected:
595 virtual int encode_packet(SrsStream* stream); 688 virtual int encode_packet(SrsStream* stream);
596 }; 689 };
597 690
  691 +// 3.7. User Control message
598 enum SrcPCUCEventType 692 enum SrcPCUCEventType
599 { 693 {
600 // generally, 4bytes event-data 694 // generally, 4bytes event-data
@@ -38,6 +38,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -38,6 +38,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #define RTMP_SIG_SRS_NAME "srs(simple rtmp server)" 38 #define RTMP_SIG_SRS_NAME "srs(simple rtmp server)"
39 #define RTMP_SIG_SRS_URL "https://github.com/winlinvip/simple-rtmp-server" 39 #define RTMP_SIG_SRS_URL "https://github.com/winlinvip/simple-rtmp-server"
40 #define RTMP_SIG_SRS_VERSION "0.1" 40 #define RTMP_SIG_SRS_VERSION "0.1"
  41 +#define RTMP_SIG_CLIENT_ID "ASAICiss"
  42 +
  43 +#define StatusLevel "level"
  44 +#define StatusCode "code"
  45 +#define StatusDescription "description"
  46 +#define StatusDetails "details"
  47 +#define StatusClientId "clientid"
  48 +// status value
  49 +#define StatusLevelStatus "status"
  50 +// code value
  51 +#define StatusCodeConnectSuccess "NetConnection.Connect.Success"
  52 +#define StatusCodeStreamReset "NetStream.Play.Reset"
  53 +#define StatusCodeStreamStart "NetStream.Play.Start"
  54 +#define StatusCodeDataStart "NetStream.Data.Start"
41 55
42 int SrsRequest::discovery_app() 56 int SrsRequest::discovery_app()
43 { 57 {
@@ -225,9 +239,9 @@ int SrsRtmp::response_connect_app() @@ -225,9 +239,9 @@ int SrsRtmp::response_connect_app()
225 pkt->props->properties["capabilities"] = new SrsAmf0Number(123); 239 pkt->props->properties["capabilities"] = new SrsAmf0Number(123);
226 pkt->props->properties["mode"] = new SrsAmf0Number(1); 240 pkt->props->properties["mode"] = new SrsAmf0Number(1);
227 241
228 - pkt->info->properties["level"] = new SrsAmf0String("status");  
229 - pkt->info->properties["code"] = new SrsAmf0String("NetConnection.Connect.Success");  
230 - pkt->info->properties["description"] = new SrsAmf0String("Connection succeeded"); 242 + pkt->info->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus);
  243 + pkt->info->properties[StatusCode] = new SrsAmf0String(StatusCodeConnectSuccess);
  244 + pkt->info->properties[StatusDescription] = new SrsAmf0String("Connection succeeded");
231 pkt->info->properties["objectEncoding"] = new SrsAmf0Number(RTMP_SIG_AMF0_VER); 245 pkt->info->properties["objectEncoding"] = new SrsAmf0Number(RTMP_SIG_AMF0_VER);
232 SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); 246 SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray();
233 pkt->info->properties["data"] = data; 247 pkt->info->properties["data"] = data;
@@ -342,6 +356,80 @@ int SrsRtmp::start_play(int stream_id) @@ -342,6 +356,80 @@ int SrsRtmp::start_play(int stream_id)
342 srs_info("send PCUC(StreamBegin) message success."); 356 srs_info("send PCUC(StreamBegin) message success.");
343 } 357 }
344 358
  359 + // onStatus(NetStream.Play.Reset)
  360 + if (true) {
  361 + SrsMessage* msg = new SrsMessage();
  362 + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
  363 +
  364 + pkt->data->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus);
  365 + pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeStreamReset);
  366 + pkt->data->properties[StatusDescription] = new SrsAmf0String("Playing and resetting stream.");
  367 + pkt->data->properties[StatusDetails] = new SrsAmf0String("stream");
  368 + pkt->data->properties[StatusClientId] = new SrsAmf0String(RTMP_SIG_CLIENT_ID);
  369 +
  370 + msg->header.stream_id = stream_id;
  371 + msg->set_packet(pkt);
  372 +
  373 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  374 + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret);
  375 + return ret;
  376 + }
  377 + srs_info("send onStatus(NetStream.Play.Reset) message success.");
  378 + }
  379 +
  380 + // onStatus(NetStream.Play.Start)
  381 + if (true) {
  382 + SrsMessage* msg = new SrsMessage();
  383 + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
  384 +
  385 + pkt->data->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus);
  386 + pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeStreamStart);
  387 + pkt->data->properties[StatusDescription] = new SrsAmf0String("Started playing stream.");
  388 + pkt->data->properties[StatusDetails] = new SrsAmf0String("stream");
  389 + pkt->data->properties[StatusClientId] = new SrsAmf0String(RTMP_SIG_CLIENT_ID);
  390 +
  391 + msg->header.stream_id = stream_id;
  392 + msg->set_packet(pkt);
  393 +
  394 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  395 + srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret);
  396 + return ret;
  397 + }
  398 + srs_info("send onStatus(NetStream.Play.Reset) message success.");
  399 + }
  400 +
  401 + // |RtmpSampleAccess(false, false)
  402 + if (true) {
  403 + SrsMessage* msg = new SrsMessage();
  404 + SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket();
  405 +
  406 + msg->header.stream_id = stream_id;
  407 + msg->set_packet(pkt);
  408 +
  409 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  410 + srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret);
  411 + return ret;
  412 + }
  413 + srs_info("send |RtmpSampleAccess(false, false) message success.");
  414 + }
  415 +
  416 + // onStatus(NetStream.Data.Start)
  417 + if (true) {
  418 + SrsMessage* msg = new SrsMessage();
  419 + SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket();
  420 +
  421 + pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeDataStart);
  422 +
  423 + msg->header.stream_id = stream_id;
  424 + msg->set_packet(pkt);
  425 +
  426 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  427 + srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret);
  428 + return ret;
  429 + }
  430 + srs_info("send onStatus(NetStream.Data.Start) message success.");
  431 + }
  432 +
345 srs_info("start play success."); 433 srs_info("start play success.");
346 434
347 return ret; 435 return ret;
@@ -104,8 +104,11 @@ public: @@ -104,8 +104,11 @@ public:
104 */ 104 */
105 virtual int set_chunk_size(int chunk_size); 105 virtual int set_chunk_size(int chunk_size);
106 /** 106 /**
107 - * when client type is play, response with  
108 - * StreamBegin, onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start). 107 + * when client type is play, response with packets:
  108 + * StreamBegin,
  109 + * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
  110 + * |RtmpSampleAccess(false, false),
  111 + * onStatus(NetStream.Data.Start).
109 */ 112 */
110 virtual int start_play(int stream_id); 113 virtual int start_play(int stream_id);
111 private: 114 private: