mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
support createStream and play, identity the play client
This commit is contained in:
parent
0818677637
commit
af5961432d
7 changed files with 740 additions and 16 deletions
|
@ -84,6 +84,11 @@ bool SrsAmf0Any::is_number()
|
||||||
return marker == RTMP_AMF0_Number;
|
return marker == RTMP_AMF0_Number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsAmf0Any::is_null()
|
||||||
|
{
|
||||||
|
return marker == RTMP_AMF0_Null;
|
||||||
|
}
|
||||||
|
|
||||||
bool SrsAmf0Any::is_object()
|
bool SrsAmf0Any::is_object()
|
||||||
{
|
{
|
||||||
return marker == RTMP_AMF0_Object;
|
return marker == RTMP_AMF0_Object;
|
||||||
|
@ -131,6 +136,15 @@ SrsAmf0Number::~SrsAmf0Number()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsAmf0Null::SrsAmf0Null()
|
||||||
|
{
|
||||||
|
marker = RTMP_AMF0_Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAmf0Null::~SrsAmf0Null()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
|
SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
|
||||||
{
|
{
|
||||||
marker = RTMP_AMF0_ObjectEnd;
|
marker = RTMP_AMF0_ObjectEnd;
|
||||||
|
@ -470,6 +484,45 @@ int srs_amf0_write_number(SrsStream* stream, double value)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int srs_amf0_read_null(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// marker
|
||||||
|
if (!stream->require(1)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 read null marker failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char marker = stream->read_1bytes();
|
||||||
|
if (marker != RTMP_AMF0_Null) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 check null marker failed. "
|
||||||
|
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Null, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("amf0 read null success");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int srs_amf0_write_null(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// marker
|
||||||
|
if (!stream->require(1)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||||
|
srs_error("amf0 write null marker failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->write_1bytes(RTMP_AMF0_Null);
|
||||||
|
srs_verbose("amf0 write null marker success");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
@ -515,6 +568,10 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
||||||
srs_amf0_convert<SrsAmf0Number>(value)->value = data;
|
srs_amf0_convert<SrsAmf0Number>(value)->value = data;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
case RTMP_AMF0_Null: {
|
||||||
|
value = new SrsAmf0Null();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
case RTMP_AMF0_ObjectEnd: {
|
case RTMP_AMF0_ObjectEnd: {
|
||||||
SrsAmf0ObjectEOF* p = NULL;
|
SrsAmf0ObjectEOF* p = NULL;
|
||||||
if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) {
|
if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) {
|
||||||
|
@ -568,6 +625,9 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
|
||||||
double data = srs_amf0_convert<SrsAmf0Number>(value)->value;
|
double data = srs_amf0_convert<SrsAmf0Number>(value)->value;
|
||||||
return srs_amf0_write_number(stream, data);
|
return srs_amf0_write_number(stream, data);
|
||||||
}
|
}
|
||||||
|
case RTMP_AMF0_Null: {
|
||||||
|
return srs_amf0_write_null(stream);
|
||||||
|
}
|
||||||
case RTMP_AMF0_ObjectEnd: {
|
case RTMP_AMF0_ObjectEnd: {
|
||||||
SrsAmf0ObjectEOF* p = srs_amf0_convert<SrsAmf0ObjectEOF>(value);
|
SrsAmf0ObjectEOF* p = srs_amf0_convert<SrsAmf0ObjectEOF>(value);
|
||||||
return srs_amf0_write_object_eof(stream, p);
|
return srs_amf0_write_object_eof(stream, p);
|
||||||
|
@ -590,7 +650,6 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_amf0_get_any_size(SrsAmf0Any* value)
|
int srs_amf0_get_any_size(SrsAmf0Any* value)
|
||||||
{
|
{
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
@ -613,6 +672,10 @@ int srs_amf0_get_any_size(SrsAmf0Any* value)
|
||||||
size += srs_amf0_get_number_size();
|
size += srs_amf0_get_number_size();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RTMP_AMF0_Null: {
|
||||||
|
size += srs_amf0_get_null_size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RTMP_AMF0_ObjectEnd: {
|
case RTMP_AMF0_ObjectEnd: {
|
||||||
size += srs_amf0_get_object_eof_size();
|
size += srs_amf0_get_object_eof_size();
|
||||||
break;
|
break;
|
||||||
|
@ -941,6 +1004,11 @@ int srs_amf0_get_number_size()
|
||||||
return 1 + 8;
|
return 1 + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int srs_amf0_get_null_size()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int srs_amf0_get_boolean_size()
|
int srs_amf0_get_boolean_size()
|
||||||
{
|
{
|
||||||
return 1 + 1;
|
return 1 + 1;
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct SrsAmf0Any
|
||||||
virtual bool is_string();
|
virtual bool is_string();
|
||||||
virtual bool is_boolean();
|
virtual bool is_boolean();
|
||||||
virtual bool is_number();
|
virtual bool is_number();
|
||||||
|
virtual bool is_null();
|
||||||
virtual bool is_object();
|
virtual bool is_object();
|
||||||
virtual bool is_object_eof();
|
virtual bool is_object_eof();
|
||||||
virtual bool is_ecma_array();
|
virtual bool is_ecma_array();
|
||||||
|
@ -102,6 +103,17 @@ struct SrsAmf0Number : public SrsAmf0Any
|
||||||
virtual ~SrsAmf0Number();
|
virtual ~SrsAmf0Number();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read amf0 null from stream.
|
||||||
|
* 2.7 null Type
|
||||||
|
* null-type = null-marker
|
||||||
|
*/
|
||||||
|
struct SrsAmf0Null : public SrsAmf0Any
|
||||||
|
{
|
||||||
|
SrsAmf0Null();
|
||||||
|
virtual ~SrsAmf0Null();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 2.11 Object End Type
|
* 2.11 Object End Type
|
||||||
* object-end-type = UTF-8-empty object-end-marker
|
* object-end-type = UTF-8-empty object-end-marker
|
||||||
|
@ -187,6 +199,14 @@ extern int srs_amf0_write_boolean(SrsStream* stream, bool value);
|
||||||
extern int srs_amf0_read_number(SrsStream* stream, double& value);
|
extern int srs_amf0_read_number(SrsStream* stream, double& value);
|
||||||
extern int srs_amf0_write_number(SrsStream* stream, double value);
|
extern int srs_amf0_write_number(SrsStream* stream, double value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read amf0 null from stream.
|
||||||
|
* 2.7 null Type
|
||||||
|
* null-type = null-marker
|
||||||
|
*/
|
||||||
|
extern int srs_amf0_read_null(SrsStream* stream);
|
||||||
|
extern int srs_amf0_write_null(SrsStream* stream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read amf0 object from stream.
|
* read amf0 object from stream.
|
||||||
* 2.5 Object Type
|
* 2.5 Object Type
|
||||||
|
@ -212,6 +232,7 @@ extern int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* va
|
||||||
extern int srs_amf0_get_utf8_size(std::string value);
|
extern int srs_amf0_get_utf8_size(std::string value);
|
||||||
extern int srs_amf0_get_string_size(std::string value);
|
extern int srs_amf0_get_string_size(std::string value);
|
||||||
extern int srs_amf0_get_number_size();
|
extern int srs_amf0_get_number_size();
|
||||||
|
extern int srs_amf0_get_null_size();
|
||||||
extern int srs_amf0_get_boolean_size();
|
extern int srs_amf0_get_boolean_size();
|
||||||
extern int srs_amf0_get_object_size(SrsAmf0Object* obj);
|
extern int srs_amf0_get_object_size(SrsAmf0Object* obj);
|
||||||
extern int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr);
|
extern int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr);
|
||||||
|
|
|
@ -29,6 +29,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_core_log.hpp>
|
#include <srs_core_log.hpp>
|
||||||
#include <srs_core_rtmp.hpp>
|
#include <srs_core_rtmp.hpp>
|
||||||
|
|
||||||
|
// default stream id for response the createStream request.
|
||||||
|
#define SRS_DEFAULT_SID 1
|
||||||
|
|
||||||
SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
|
SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
|
||||||
: SrsConnection(srs_server, client_stfd)
|
: SrsConnection(srs_server, client_stfd)
|
||||||
{
|
{
|
||||||
|
@ -98,6 +101,20 @@ int SrsClient::do_cycle()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("response connect app success");
|
srs_verbose("response connect app success");
|
||||||
|
|
||||||
|
if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("on_bw_done failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("on_bw_done success");
|
||||||
|
|
||||||
|
SrsClientType type;
|
||||||
|
std::string stream_name;
|
||||||
|
if ((ret = rtmp->identify_client(SRS_DEFAULT_SID, type, stream_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("identify client failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("identify client success. type=%d", type);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,9 +202,13 @@ messages.
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
/**
|
/**
|
||||||
* amf0 command message, command name: "connect"
|
* amf0 command message, command name macros
|
||||||
*/
|
*/
|
||||||
#define RTMP_AMF0_COMMAND_CONNECT "connect"
|
#define RTMP_AMF0_COMMAND_CONNECT "connect"
|
||||||
|
#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"
|
||||||
|
#define RTMP_AMF0_COMMAND_PLAY "play"
|
||||||
|
#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
|
||||||
|
#define RTMP_AMF0_COMMAND_RESULT "_result"
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
|
@ -585,11 +589,12 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// when not exists cached msg, means get an new message,
|
// when not exists cached msg, means get an new message,
|
||||||
// the fmt must be type0 which means new message.
|
// the fmt must be type0/type1 which means new message.
|
||||||
if (!chunk->msg && fmt != RTMP_FMT_TYPE0) {
|
if (!chunk->msg && fmt != RTMP_FMT_TYPE0 && fmt != RTMP_FMT_TYPE1) {
|
||||||
ret = ERROR_RTMP_CHUNK_START;
|
ret = ERROR_RTMP_CHUNK_START;
|
||||||
srs_error("chunk stream start, "
|
srs_error("chunk stream start, "
|
||||||
"fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret);
|
"fmt must be %d or %d, actual is %d. ret=%d",
|
||||||
|
RTMP_FMT_TYPE0, RTMP_FMT_TYPE1, fmt, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +609,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
|
||||||
|
|
||||||
// create msg when new chunk stream start
|
// create msg when new chunk stream start
|
||||||
if (!chunk->msg) {
|
if (!chunk->msg) {
|
||||||
srs_assert(fmt == RTMP_FMT_TYPE0);
|
srs_assert(fmt == RTMP_FMT_TYPE0 || fmt == RTMP_FMT_TYPE1);
|
||||||
chunk->msg = new SrsMessage();
|
chunk->msg = new SrsMessage();
|
||||||
srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid);
|
srs_verbose("create message for new chunk, fmt=%d, cid=%d", fmt, chunk->cid);
|
||||||
}
|
}
|
||||||
|
@ -802,6 +807,21 @@ SrsMessageHeader::~SrsMessageHeader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsMessageHeader::is_amf0_command()
|
||||||
|
{
|
||||||
|
return message_type == RTMP_MSG_AMF0CommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsMessageHeader::is_amf3_command()
|
||||||
|
{
|
||||||
|
return message_type == RTMP_MSG_AMF3CommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsMessageHeader::is_window_ackledgement_size()
|
||||||
|
{
|
||||||
|
return message_type == RTMP_MSG_WindowAcknowledgementSize;
|
||||||
|
}
|
||||||
|
|
||||||
SrsChunkStream::SrsChunkStream(int _cid)
|
SrsChunkStream::SrsChunkStream(int _cid)
|
||||||
{
|
{
|
||||||
fmt = 0;
|
fmt = 0;
|
||||||
|
@ -870,30 +890,50 @@ int SrsMessage::decode_packet()
|
||||||
srs_verbose("decode stream initialized success");
|
srs_verbose("decode stream initialized success");
|
||||||
|
|
||||||
// decode specified packet type
|
// decode specified packet type
|
||||||
if (header.message_type == RTMP_MSG_AMF0CommandMessage) {
|
if (header.is_amf0_command() || header.is_amf3_command()) {
|
||||||
srs_verbose("start to decode AMF0 command message.");
|
srs_verbose("start to decode AMF0/AMF3 command message.");
|
||||||
|
|
||||||
|
// skip 1bytes to decode the amf3 command.
|
||||||
|
if (header.is_amf3_command() && stream->require(1)) {
|
||||||
|
srs_verbose("skip 1bytes to decode AMF3 command");
|
||||||
|
stream->skip(1);
|
||||||
|
}
|
||||||
|
|
||||||
// amf0 command message.
|
// amf0 command message.
|
||||||
// need to read the command name.
|
// need to read the command name.
|
||||||
std::string command;
|
std::string command;
|
||||||
if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) {
|
if ((ret = srs_amf0_read_string(stream, command)) != ERROR_SUCCESS) {
|
||||||
srs_error("decode AMF0 command name failed. ret=%d", ret);
|
srs_error("decode AMF0/AMF3 command name failed. ret=%d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("AMF0 command message, command_name=%s", command.c_str());
|
srs_verbose("AMF0/AMF3 command message, command_name=%s", command.c_str());
|
||||||
|
|
||||||
|
// reset to zero(amf3 to 1) to restart decode.
|
||||||
stream->reset();
|
stream->reset();
|
||||||
|
if (header.is_amf3_command()) {
|
||||||
|
stream->skip(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode command object.
|
||||||
if (command == RTMP_AMF0_COMMAND_CONNECT) {
|
if (command == RTMP_AMF0_COMMAND_CONNECT) {
|
||||||
srs_info("decode the AMF0 command(connect vhost/app message).");
|
srs_info("decode the AMF0/AMF3 command(connect vhost/app message).");
|
||||||
packet = new SrsConnectAppPacket();
|
packet = new SrsConnectAppPacket();
|
||||||
return packet->decode(stream);
|
return packet->decode(stream);
|
||||||
|
} else if(command == RTMP_AMF0_COMMAND_CREATE_STREAM) {
|
||||||
|
srs_info("decode the AMF0/AMF3 command(createStream message).");
|
||||||
|
packet = new SrsCreateStreamPacket();
|
||||||
|
return packet->decode(stream);
|
||||||
|
} else if(command == RTMP_AMF0_COMMAND_PLAY) {
|
||||||
|
srs_info("decode the AMF0/AMF3 command(paly message).");
|
||||||
|
packet = new SrsPlayPacket();
|
||||||
|
return packet->decode(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default packet to drop message.
|
// default packet to drop message.
|
||||||
srs_trace("drop the AMF0 command message, command_name=%s", command.c_str());
|
srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str());
|
||||||
packet = new SrsPacket();
|
packet = new SrsPacket();
|
||||||
return ret;
|
return ret;
|
||||||
} else if(header.message_type == RTMP_MSG_WindowAcknowledgementSize) {
|
} else if(header.is_window_ackledgement_size()) {
|
||||||
srs_verbose("start to decode set ack window size message.");
|
srs_verbose("start to decode set ack window size message.");
|
||||||
packet = new SrsSetWindowAckSizePacket();
|
packet = new SrsSetWindowAckSizePacket();
|
||||||
return packet->decode(stream);
|
return packet->decode(stream);
|
||||||
|
@ -1106,7 +1146,7 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
|
||||||
|
|
||||||
SrsConnectAppResPacket::SrsConnectAppResPacket()
|
SrsConnectAppResPacket::SrsConnectAppResPacket()
|
||||||
{
|
{
|
||||||
command_name = RTMP_AMF0_COMMAND_CONNECT;
|
command_name = RTMP_AMF0_COMMAND_RESULT;
|
||||||
transaction_id = 1;
|
transaction_id = 1;
|
||||||
props = new SrsAmf0Object();
|
props = new SrsAmf0Object();
|
||||||
info = new SrsAmf0Object();
|
info = new SrsAmf0Object();
|
||||||
|
@ -1175,6 +1215,313 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsCreateStreamPacket::SrsCreateStreamPacket()
|
||||||
|
{
|
||||||
|
command_name = RTMP_AMF0_COMMAND_CREATE_STREAM;
|
||||||
|
transaction_id = 2;
|
||||||
|
command_object = new SrsAmf0Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsCreateStreamPacket::~SrsCreateStreamPacket()
|
||||||
|
{
|
||||||
|
if (command_object) {
|
||||||
|
delete command_object;
|
||||||
|
command_object = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsCreateStreamPacket::decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode createStream command_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CREATE_STREAM) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 decode createStream command_name failed. "
|
||||||
|
"command_name=%s, ret=%d", command_name.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode createStream transaction_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode createStream command_object failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_info("amf0 decode createStream packet success");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsCreateStreamResPacket::SrsCreateStreamResPacket(double _transaction_id, double _stream_id)
|
||||||
|
{
|
||||||
|
command_name = RTMP_AMF0_COMMAND_RESULT;
|
||||||
|
transaction_id = _transaction_id;
|
||||||
|
command_object = new SrsAmf0Null();
|
||||||
|
stream_id = _stream_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsCreateStreamResPacket::~SrsCreateStreamResPacket()
|
||||||
|
{
|
||||||
|
if (command_object) {
|
||||||
|
delete command_object;
|
||||||
|
command_object = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsCreateStreamResPacket::get_perfer_cid()
|
||||||
|
{
|
||||||
|
return RTMP_CID_OverConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsCreateStreamResPacket::get_message_type()
|
||||||
|
{
|
||||||
|
return RTMP_MSG_AMF0CommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsCreateStreamResPacket::get_size()
|
||||||
|
{
|
||||||
|
return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()
|
||||||
|
+ srs_amf0_get_null_size() + srs_amf0_get_number_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsCreateStreamResPacket::encode_packet(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode command_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode command_name success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode transaction_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode transaction_id success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode command_object failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode command_object success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_number(stream, stream_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode stream_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode stream_id success.");
|
||||||
|
|
||||||
|
|
||||||
|
srs_info("encode createStream response packet success.");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPlayPacket::SrsPlayPacket()
|
||||||
|
{
|
||||||
|
command_name = RTMP_AMF0_COMMAND_PLAY;
|
||||||
|
transaction_id = 0;
|
||||||
|
command_object = new SrsAmf0Null();
|
||||||
|
|
||||||
|
start = -2;
|
||||||
|
duration = -1;
|
||||||
|
reset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPlayPacket::~SrsPlayPacket()
|
||||||
|
{
|
||||||
|
if (command_object) {
|
||||||
|
delete command_object;
|
||||||
|
command_object = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsPlayPacket::decode(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play command_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PLAY) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 decode play command_name failed. "
|
||||||
|
"command_name=%s, ret=%d", command_name.c_str(), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play transaction_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play command_object failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play stream_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream->empty() && (ret = srs_amf0_read_number(stream, start)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play start failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (!stream->empty() && (ret = srs_amf0_read_number(stream, duration)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play duration failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (!stream->empty() && (ret = srs_amf0_read_boolean(stream, reset)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("amf0 decode play reset failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_info("amf0 decode play packet success");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPlayResPacket::SrsPlayResPacket()
|
||||||
|
{
|
||||||
|
command_name = RTMP_AMF0_COMMAND_RESULT;
|
||||||
|
transaction_id = 0;
|
||||||
|
command_object = new SrsAmf0Null();
|
||||||
|
desc = new SrsAmf0Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPlayResPacket::~SrsPlayResPacket()
|
||||||
|
{
|
||||||
|
if (command_object) {
|
||||||
|
delete command_object;
|
||||||
|
command_object = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc) {
|
||||||
|
delete desc;
|
||||||
|
desc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsPlayResPacket::get_perfer_cid()
|
||||||
|
{
|
||||||
|
return RTMP_CID_OverStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsPlayResPacket::get_message_type()
|
||||||
|
{
|
||||||
|
return RTMP_MSG_AMF0CommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsPlayResPacket::get_size()
|
||||||
|
{
|
||||||
|
return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()
|
||||||
|
+ srs_amf0_get_null_size() + srs_amf0_get_object_size(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsPlayResPacket::encode_packet(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode command_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode command_name success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode transaction_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode transaction_id success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode command_object failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode command_object success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_object(stream, desc)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode desc failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode desc success.");
|
||||||
|
|
||||||
|
|
||||||
|
srs_info("encode play response packet success.");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsOnBWDonePacket::SrsOnBWDonePacket()
|
||||||
|
{
|
||||||
|
command_name = RTMP_AMF0_COMMAND_ON_BW_DONE;
|
||||||
|
transaction_id = 0;
|
||||||
|
args = new SrsAmf0Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsOnBWDonePacket::~SrsOnBWDonePacket()
|
||||||
|
{
|
||||||
|
if (args) {
|
||||||
|
delete args;
|
||||||
|
args = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsOnBWDonePacket::get_perfer_cid()
|
||||||
|
{
|
||||||
|
return RTMP_CID_OverConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsOnBWDonePacket::get_message_type()
|
||||||
|
{
|
||||||
|
return RTMP_MSG_AMF0CommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsOnBWDonePacket::get_size()
|
||||||
|
{
|
||||||
|
return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()
|
||||||
|
+ srs_amf0_get_null_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsOnBWDonePacket::encode_packet(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_string(stream, command_name)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode command_name failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode command_name success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_number(stream, transaction_id)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode transaction_id failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode transaction_id success.");
|
||||||
|
|
||||||
|
if ((ret = srs_amf0_write_null(stream)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("encode args failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("encode args success.");
|
||||||
|
|
||||||
|
srs_info("encode onBWDone packet success.");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket()
|
SrsSetWindowAckSizePacket::SrsSetWindowAckSizePacket()
|
||||||
{
|
{
|
||||||
ackowledgement_window_size = 0;
|
ackowledgement_window_size = 0;
|
||||||
|
|
|
@ -45,6 +45,7 @@ class SrsStream;
|
||||||
class SrsMessage;
|
class SrsMessage;
|
||||||
class SrsChunkStream;
|
class SrsChunkStream;
|
||||||
class SrsAmf0Object;
|
class SrsAmf0Object;
|
||||||
|
class SrsAmf0Null;
|
||||||
|
|
||||||
// convert class name to string.
|
// convert class name to string.
|
||||||
#define CLASS_NAME_STRING(className) #className
|
#define CLASS_NAME_STRING(className) #className
|
||||||
|
@ -166,6 +167,10 @@ struct SrsMessageHeader
|
||||||
|
|
||||||
SrsMessageHeader();
|
SrsMessageHeader();
|
||||||
virtual ~SrsMessageHeader();
|
virtual ~SrsMessageHeader();
|
||||||
|
|
||||||
|
bool is_amf0_command();
|
||||||
|
bool is_amf3_command();
|
||||||
|
bool is_window_ackledgement_size();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -357,6 +362,146 @@ protected:
|
||||||
virtual int encode_packet(SrsStream* stream);
|
virtual int encode_packet(SrsStream* stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4.1.3. createStream
|
||||||
|
* The client sends this command to the server to create a logical
|
||||||
|
* channel for message communication The publishing of audio, video, and
|
||||||
|
* metadata is carried out over stream channel created using the
|
||||||
|
* createStream command.
|
||||||
|
*/
|
||||||
|
class SrsCreateStreamPacket : public SrsPacket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef SrsPacket super;
|
||||||
|
protected:
|
||||||
|
virtual const char* get_class_name()
|
||||||
|
{
|
||||||
|
return CLASS_NAME_STRING(SrsCreateStreamPacket);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string command_name;
|
||||||
|
double transaction_id;
|
||||||
|
SrsAmf0Null* command_object;
|
||||||
|
public:
|
||||||
|
SrsCreateStreamPacket();
|
||||||
|
virtual ~SrsCreateStreamPacket();
|
||||||
|
public:
|
||||||
|
virtual int decode(SrsStream* stream);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* response for SrsCreateStreamPacket.
|
||||||
|
*/
|
||||||
|
class SrsCreateStreamResPacket : public SrsPacket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef SrsPacket super;
|
||||||
|
protected:
|
||||||
|
virtual const char* get_class_name()
|
||||||
|
{
|
||||||
|
return CLASS_NAME_STRING(SrsCreateStreamResPacket);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string command_name;
|
||||||
|
double transaction_id;
|
||||||
|
SrsAmf0Null* command_object;
|
||||||
|
double stream_id;
|
||||||
|
public:
|
||||||
|
SrsCreateStreamResPacket(double _transaction_id, double _stream_id);
|
||||||
|
virtual ~SrsCreateStreamResPacket();
|
||||||
|
public:
|
||||||
|
virtual int get_perfer_cid();
|
||||||
|
public:
|
||||||
|
virtual int get_message_type();
|
||||||
|
protected:
|
||||||
|
virtual int get_size();
|
||||||
|
virtual int encode_packet(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 4.2.1. play
|
||||||
|
* The client sends this command to the server to play a stream.
|
||||||
|
*/
|
||||||
|
class SrsPlayPacket : public SrsPacket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef SrsPacket super;
|
||||||
|
protected:
|
||||||
|
virtual const char* get_class_name()
|
||||||
|
{
|
||||||
|
return CLASS_NAME_STRING(SrsPlayPacket);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string command_name;
|
||||||
|
double transaction_id;
|
||||||
|
SrsAmf0Null* command_object;
|
||||||
|
std::string stream_name;
|
||||||
|
double start;
|
||||||
|
double duration;
|
||||||
|
bool reset;
|
||||||
|
public:
|
||||||
|
SrsPlayPacket();
|
||||||
|
virtual ~SrsPlayPacket();
|
||||||
|
public:
|
||||||
|
virtual int decode(SrsStream* stream);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* response for SrsPlayPacket.
|
||||||
|
* @remark, user must set the stream_id in header.
|
||||||
|
*/
|
||||||
|
class SrsPlayResPacket : public SrsPacket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef SrsPacket super;
|
||||||
|
protected:
|
||||||
|
virtual const char* get_class_name()
|
||||||
|
{
|
||||||
|
return CLASS_NAME_STRING(SrsPlayResPacket);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string command_name;
|
||||||
|
double transaction_id;
|
||||||
|
SrsAmf0Null* command_object;
|
||||||
|
SrsAmf0Object* desc;
|
||||||
|
public:
|
||||||
|
SrsPlayResPacket();
|
||||||
|
virtual ~SrsPlayResPacket();
|
||||||
|
public:
|
||||||
|
virtual int get_perfer_cid();
|
||||||
|
public:
|
||||||
|
virtual int get_message_type();
|
||||||
|
protected:
|
||||||
|
virtual int get_size();
|
||||||
|
virtual int encode_packet(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when bandwidth test done, notice client.
|
||||||
|
*/
|
||||||
|
class SrsOnBWDonePacket : public SrsPacket
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef SrsPacket super;
|
||||||
|
protected:
|
||||||
|
virtual const char* get_class_name()
|
||||||
|
{
|
||||||
|
return CLASS_NAME_STRING(SrsOnBWDonePacket);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
std::string command_name;
|
||||||
|
double transaction_id;
|
||||||
|
SrsAmf0Null* args;
|
||||||
|
public:
|
||||||
|
SrsOnBWDonePacket();
|
||||||
|
virtual ~SrsOnBWDonePacket();
|
||||||
|
public:
|
||||||
|
virtual int get_perfer_cid();
|
||||||
|
public:
|
||||||
|
virtual int get_message_type();
|
||||||
|
protected:
|
||||||
|
virtual int get_size();
|
||||||
|
virtual int encode_packet(SrsStream* stream);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 5.5. Window Acknowledgement Size (5)
|
* 5.5. Window Acknowledgement Size (5)
|
||||||
* The client or the server sends this message to inform the peer which
|
* The client or the server sends this message to inform the peer which
|
||||||
|
|
|
@ -221,8 +221,6 @@ int SrsRtmp::response_connect_app()
|
||||||
SrsMessage* msg = new SrsMessage();
|
SrsMessage* msg = new SrsMessage();
|
||||||
SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket();
|
SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket();
|
||||||
|
|
||||||
pkt->command_name = "_result";
|
|
||||||
|
|
||||||
pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER);
|
pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER);
|
||||||
pkt->props->properties["capabilities"] = new SrsAmf0Number(123);
|
pkt->props->properties["capabilities"] = new SrsAmf0Number(123);
|
||||||
pkt->props->properties["mode"] = new SrsAmf0Number(1);
|
pkt->props->properties["mode"] = new SrsAmf0Number(1);
|
||||||
|
@ -250,3 +248,110 @@ int SrsRtmp::response_connect_app()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsRtmp::on_bw_done()
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
SrsMessage* msg = new SrsMessage();
|
||||||
|
SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket();
|
||||||
|
|
||||||
|
msg->set_packet(pkt);
|
||||||
|
|
||||||
|
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("send onBWDone message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_info("send onBWDone message success.");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRtmp::identify_client(int stream_id, SrsClientType& type, std::string& stream_name)
|
||||||
|
{
|
||||||
|
type = SrsClientUnknown;
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
SrsMessage* msg = NULL;
|
||||||
|
if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("recv identify client message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAutoFree(SrsMessage, msg, false);
|
||||||
|
|
||||||
|
if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) {
|
||||||
|
srs_trace("identify ignore messages except "
|
||||||
|
"AMF0/AMF3 command message. type=%#x", msg->header.message_type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = msg->decode_packet()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("identify decode message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPacket* pkt = msg->get_packet();
|
||||||
|
if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
|
||||||
|
return identify_create_stream_client(
|
||||||
|
dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_trace("ignore AMF0/AMF3 command message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
SrsMessage* msg = new SrsMessage();
|
||||||
|
SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id);
|
||||||
|
|
||||||
|
msg->set_packet(pkt);
|
||||||
|
|
||||||
|
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("send createStream response message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_info("send createStream response message success.");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
SrsMessage* msg = NULL;
|
||||||
|
if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("recv identify client message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAutoFree(SrsMessage, msg, false);
|
||||||
|
|
||||||
|
if (!msg->header.is_amf0_command() && !msg->header.is_amf3_command()) {
|
||||||
|
srs_trace("identify ignore messages except "
|
||||||
|
"AMF0/AMF3 command message. type=%#x", msg->header.message_type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = msg->decode_packet()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("identify decode message failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPacket* pkt = msg->get_packet();
|
||||||
|
if (dynamic_cast<SrsPlayPacket*>(pkt)) {
|
||||||
|
SrsPlayPacket* play = dynamic_cast<SrsPlayPacket*>(pkt);
|
||||||
|
type = SrsClientPublish;
|
||||||
|
stream_name = play->stream_name;
|
||||||
|
srs_trace("identity client type=play, stream_name=%s", stream_name.c_str());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_trace("ignore AMF0/AMF3 command message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <st.h>
|
#include <st.h>
|
||||||
|
|
||||||
class SrsProtocol;
|
class SrsProtocol;
|
||||||
|
class SrsCreateStreamPacket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the original request from client.
|
* the original request from client.
|
||||||
|
@ -57,6 +58,16 @@ struct SrsRequest
|
||||||
virtual int discovery_app();
|
virtual int discovery_app();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the rtmp client type.
|
||||||
|
*/
|
||||||
|
enum SrsClientType
|
||||||
|
{
|
||||||
|
SrsClientUnknown,
|
||||||
|
SrsClientPlay,
|
||||||
|
SrsClientPublish,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the rtmp provices rtmp-command-protocol services,
|
* the rtmp provices rtmp-command-protocol services,
|
||||||
* a high level protocol, media stream oriented services,
|
* a high level protocol, media stream oriented services,
|
||||||
|
@ -80,6 +91,16 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual int set_peer_bandwidth(int bandwidth, int type);
|
virtual int set_peer_bandwidth(int bandwidth, int type);
|
||||||
virtual int response_connect_app();
|
virtual int response_connect_app();
|
||||||
|
virtual int on_bw_done();
|
||||||
|
/**
|
||||||
|
* recv some message to identify the client.
|
||||||
|
* @stream_id, client will createStream to play or publish by flash,
|
||||||
|
* the stream_id used to response the createStream request.
|
||||||
|
* @type, output the client type.
|
||||||
|
*/
|
||||||
|
virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
|
||||||
|
private:
|
||||||
|
virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue