1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

support fmle publish. fix bug of rtmp chunk stream.

This commit is contained in:
winlin 2013-10-22 15:48:33 +08:00
parent e598616e14
commit 33c586181d
9 changed files with 497 additions and 249 deletions

View file

@ -45,4 +45,20 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stddef.h> #include <stddef.h>
#include <sys/types.h> #include <sys/types.h>
// free the p and set to NULL.
// p must be a T*.
#define srs_freep(p) \
if (p) { \
delete p; \
p = NULL; \
} \
(void)0
// free the p which represents a array
#define srs_freepa(p) \
if (p) { \
delete[] p; \
p = NULL; \
} \
(void)0
#endif #endif

View file

@ -23,6 +23,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core_amf0.hpp> #include <srs_core_amf0.hpp>
#include <utility>
#include <srs_core_log.hpp> #include <srs_core_log.hpp>
#include <srs_core_error.hpp> #include <srs_core_error.hpp>
#include <srs_core_stream.hpp> #include <srs_core_stream.hpp>
@ -169,33 +171,76 @@ SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF()
{ {
} }
SrsAmf0Object::SrsAmf0Object() SrsUnSortedHashtable::SrsUnSortedHashtable()
{ {
marker = RTMP_AMF0_Object;
} }
SrsAmf0Object::~SrsAmf0Object() SrsUnSortedHashtable::~SrsUnSortedHashtable()
{ {
std::map<std::string, SrsAmf0Any*>::iterator it; std::vector<SrsObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) { for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = it->second; SrsObjectPropertyType& elem = *it;
delete any; SrsAmf0Any* any = elem.second;
srs_freep(any);
} }
properties.clear(); properties.clear();
} }
SrsAmf0Any* SrsAmf0Object::get_property(std::string name) int SrsUnSortedHashtable::size()
{ {
std::map<std::string, SrsAmf0Any*>::iterator it; return (int)properties.size();
if ((it = properties.find(name)) == properties.end()) {
return NULL;
}
return it->second;
} }
SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name) std::string SrsUnSortedHashtable::key_at(int index)
{
srs_assert(index < size());
SrsObjectPropertyType& elem = properties[index];
return elem.first;
}
SrsAmf0Any* SrsUnSortedHashtable::value_at(int index)
{
srs_assert(index < size());
SrsObjectPropertyType& elem = properties[index];
return elem.second;
}
void SrsUnSortedHashtable::set(std::string key, SrsAmf0Any* value)
{
std::vector<SrsObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsObjectPropertyType& elem = *it;
std::string name = elem.first;
SrsAmf0Any* any = elem.second;
if (key == name) {
srs_freep(any);
properties.erase(it);
break;
}
}
properties.push_back(std::make_pair(key, value));
}
SrsAmf0Any* SrsUnSortedHashtable::get_property(std::string name)
{
std::vector<SrsObjectPropertyType>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsObjectPropertyType& elem = *it;
std::string key = elem.first;
SrsAmf0Any* any = elem.second;
if (key == name) {
return any;
}
}
return NULL;
}
SrsAmf0Any* SrsUnSortedHashtable::ensure_property_string(std::string name)
{ {
SrsAmf0Any* prop = get_property(name); SrsAmf0Any* prop = get_property(name);
@ -210,6 +255,45 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name)
return prop; return prop;
} }
SrsAmf0Object::SrsAmf0Object()
{
marker = RTMP_AMF0_Object;
}
SrsAmf0Object::~SrsAmf0Object()
{
}
int SrsAmf0Object::size()
{
return properties.size();
}
std::string SrsAmf0Object::key_at(int index)
{
return properties.key_at(index);
}
SrsAmf0Any* SrsAmf0Object::value_at(int index)
{
return properties.value_at(index);
}
void SrsAmf0Object::set(std::string key, SrsAmf0Any* value)
{
properties.set(key, value);
}
SrsAmf0Any* SrsAmf0Object::get_property(std::string name)
{
return properties.get_property(name);
}
SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name)
{
return properties.ensure_property_string(name);
}
SrsASrsAmf0EcmaArray::SrsASrsAmf0EcmaArray() SrsASrsAmf0EcmaArray::SrsASrsAmf0EcmaArray()
{ {
marker = RTMP_AMF0_EcmaArray; marker = RTMP_AMF0_EcmaArray;
@ -217,38 +301,36 @@ SrsASrsAmf0EcmaArray::SrsASrsAmf0EcmaArray()
SrsASrsAmf0EcmaArray::~SrsASrsAmf0EcmaArray() SrsASrsAmf0EcmaArray::~SrsASrsAmf0EcmaArray()
{ {
std::map<std::string, SrsAmf0Any*>::iterator it; }
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = it->second; int SrsASrsAmf0EcmaArray::size()
delete any; {
} return properties.size();
properties.clear(); }
std::string SrsASrsAmf0EcmaArray::key_at(int index)
{
return properties.key_at(index);
}
SrsAmf0Any* SrsASrsAmf0EcmaArray::value_at(int index)
{
return properties.value_at(index);
}
void SrsASrsAmf0EcmaArray::set(std::string key, SrsAmf0Any* value)
{
properties.set(key, value);
} }
SrsAmf0Any* SrsASrsAmf0EcmaArray::get_property(std::string name) SrsAmf0Any* SrsASrsAmf0EcmaArray::get_property(std::string name)
{ {
std::map<std::string, SrsAmf0Any*>::iterator it; return properties.get_property(name);
if ((it = properties.find(name)) == properties.end()) {
return NULL;
}
return it->second;
} }
SrsAmf0Any* SrsASrsAmf0EcmaArray::ensure_property_string(std::string name) SrsAmf0Any* SrsASrsAmf0EcmaArray::ensure_property_string(std::string name)
{ {
SrsAmf0Any* prop = get_property(name); return properties.ensure_property_string(name);
if (!prop) {
return NULL;
}
if (!prop->is_string()) {
return NULL;
}
return prop;
} }
int srs_amf0_read_utf8(SrsStream* stream, std::string& value) int srs_amf0_read_utf8(SrsStream* stream, std::string& value)
@ -877,14 +959,14 @@ int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value)
// AMF0 Object EOF. // AMF0 Object EOF.
if (property_name.empty() || !property_value || property_value->is_object_eof()) { if (property_name.empty() || !property_value || property_value->is_object_eof()) {
if (property_value) { if (property_value) {
delete property_value; srs_freep(property_value);
} }
srs_info("amf0 read object EOF."); srs_info("amf0 read object EOF.");
break; break;
} }
// add property // add property
value->properties[property_name] = property_value; value->set(property_name, property_value);
} }
return ret; return ret;
@ -906,10 +988,9 @@ int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value)
srs_verbose("amf0 write object marker success"); srs_verbose("amf0 write object marker success");
// value // value
std::map<std::string, SrsAmf0Any*>::iterator it; for (int i = 0; i < value->size(); i++) {
for (it = value->properties.begin(); it != value->properties.end(); ++it) { std::string name = value->key_at(i);
std::string name = it->first; SrsAmf0Any* any = value->value_at(i);
SrsAmf0Any* any = it->second;
if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) {
srs_error("write object property name failed. ret=%d", ret); srs_error("write object property name failed. ret=%d", ret);
@ -986,14 +1067,14 @@ int srs_amf0_read_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray*& value)
// AMF0 Object EOF. // AMF0 Object EOF.
if (property_name.empty() || !property_value || property_value->is_object_eof()) { if (property_name.empty() || !property_value || property_value->is_object_eof()) {
if (property_value) { if (property_value) {
delete property_value; srs_freep(property_value);
} }
srs_info("amf0 read ecma_array EOF."); srs_info("amf0 read ecma_array EOF.");
break; break;
} }
// add property // add property
value->properties[property_name] = property_value; value->set(property_name, property_value);
} }
return ret; return ret;
@ -1025,10 +1106,9 @@ int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* value)
srs_verbose("amf0 write ecma_array count success. count=%d", value->count); srs_verbose("amf0 write ecma_array count success. count=%d", value->count);
// value // value
std::map<std::string, SrsAmf0Any*>::iterator it; for (int i = 0; i < value->size(); i++) {
for (it = value->properties.begin(); it != value->properties.end(); ++it) { std::string name = value->key_at(i);
std::string name = it->first; SrsAmf0Any* any = value->value_at(i);
SrsAmf0Any* any = it->second;
if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) {
srs_error("write ecma_array property name failed. ret=%d", ret); srs_error("write ecma_array property name failed. ret=%d", ret);
@ -1091,10 +1171,9 @@ int srs_amf0_get_object_size(SrsAmf0Object* obj)
int size = 1; int size = 1;
std::map<std::string, SrsAmf0Any*>::iterator it; for (int i = 0; i < obj->size(); i++){
for (it = obj->properties.begin(); it != obj->properties.end(); ++it) { std::string name = obj->key_at(i);
std::string name = it->first; SrsAmf0Any* value = obj->value_at(i);
SrsAmf0Any* value = it->second;
size += srs_amf0_get_utf8_size(name); size += srs_amf0_get_utf8_size(name);
size += srs_amf0_get_any_size(value); size += srs_amf0_get_any_size(value);
@ -1113,10 +1192,9 @@ int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr)
int size = 1 + 4; int size = 1 + 4;
std::map<std::string, SrsAmf0Any*>::iterator it; for (int i = 0; i < arr->size(); i++){
for (it = arr->properties.begin(); it != arr->properties.end(); ++it) { std::string name = arr->key_at(i);
std::string name = it->first; SrsAmf0Any* value = arr->value_at(i);
SrsAmf0Any* value = it->second;
size += srs_amf0_get_utf8_size(name); size += srs_amf0_get_utf8_size(name);
size += srs_amf0_get_any_size(value); size += srs_amf0_get_any_size(value);

View file

@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp> #include <srs_core.hpp>
#include <string> #include <string>
#include <map> #include <vector>
class SrsStream; class SrsStream;
class SrsAmf0Object; class SrsAmf0Object;
@ -139,6 +139,30 @@ struct SrsAmf0ObjectEOF : public SrsAmf0Any
virtual ~SrsAmf0ObjectEOF(); virtual ~SrsAmf0ObjectEOF();
}; };
/**
* to ensure in inserted order.
* for the FMLE will crash when AMF0Object is not ordered by inserted,
* if ordered in map, the string compare order, the FMLE will creash when
* get the response of connect app.
*/
struct SrsUnSortedHashtable
{
private:
typedef std::pair<std::string, SrsAmf0Any*> SrsObjectPropertyType;
std::vector<SrsObjectPropertyType> properties;
public:
SrsUnSortedHashtable();
virtual ~SrsUnSortedHashtable();
virtual int size();
virtual std::string key_at(int index);
virtual SrsAmf0Any* value_at(int index);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
};
/** /**
* 2.5 Object Type * 2.5 Object Type
* anonymous-object-type = object-marker *(object-property) * anonymous-object-type = object-marker *(object-property)
@ -146,11 +170,18 @@ struct SrsAmf0ObjectEOF : public SrsAmf0Any
*/ */
struct SrsAmf0Object : public SrsAmf0Any struct SrsAmf0Object : public SrsAmf0Any
{ {
std::map<std::string, SrsAmf0Any*> properties; private:
SrsUnSortedHashtable properties;
public:
SrsAmf0ObjectEOF eof; SrsAmf0ObjectEOF eof;
SrsAmf0Object(); SrsAmf0Object();
virtual ~SrsAmf0Object(); virtual ~SrsAmf0Object();
virtual int size();
virtual std::string key_at(int index);
virtual SrsAmf0Any* value_at(int index);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name); virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name); virtual SrsAmf0Any* ensure_property_string(std::string name);
@ -164,12 +195,19 @@ struct SrsAmf0Object : public SrsAmf0Any
*/ */
struct SrsASrsAmf0EcmaArray : public SrsAmf0Any struct SrsASrsAmf0EcmaArray : public SrsAmf0Any
{ {
private:
SrsUnSortedHashtable properties;
public:
int32_t count; int32_t count;
std::map<std::string, SrsAmf0Any*> properties;
SrsAmf0ObjectEOF eof; SrsAmf0ObjectEOF eof;
SrsASrsAmf0EcmaArray(); SrsASrsAmf0EcmaArray();
virtual ~SrsASrsAmf0EcmaArray(); virtual ~SrsASrsAmf0EcmaArray();
virtual int size();
virtual std::string key_at(int index);
virtual SrsAmf0Any* value_at(int index);
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name); virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name); virtual SrsAmf0Any* ensure_property_string(std::string name);

View file

@ -55,7 +55,7 @@ void SrsBuffer::append(char* bytes, int size)
{ {
std::vector<char> vec(bytes, bytes + size); std::vector<char> vec(bytes, bytes + size);
data.insert(data.begin(), vec.begin(), vec.end()); data.insert(data.end(), vec.begin(), vec.end());
} }
int SrsBuffer::ensure_buffer_bytes(SrsSocket* skt, int required_size) int SrsBuffer::ensure_buffer_bytes(SrsSocket* skt, int required_size)

View file

@ -42,20 +42,9 @@ SrsClient::SrsClient(SrsServer* srs_server, st_netfd_t client_stfd)
SrsClient::~SrsClient() SrsClient::~SrsClient()
{ {
if (ip) { srs_freepa(ip);
delete[] ip; srs_freep(req);
ip = NULL; srs_freep(rtmp);
}
if (req) {
delete req;
req = NULL;
}
if (rtmp) {
delete rtmp;
rtmp = NULL;
}
} }
int SrsClient::do_cycle() int SrsClient::do_cycle()

View file

@ -199,6 +199,7 @@ messages.
#define RTMP_AMF0_COMMAND_RESULT "_result" #define RTMP_AMF0_COMMAND_RESULT "_result"
#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" #define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream"
#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" #define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish"
#define RTMP_AMF0_COMMAND_PUBLISH "publish"
#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" #define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess"
/**************************************************************************** /****************************************************************************
@ -260,23 +261,13 @@ SrsProtocol::~SrsProtocol()
for (it = chunk_streams.begin(); it != chunk_streams.end(); ++it) { for (it = chunk_streams.begin(); it != chunk_streams.end(); ++it) {
SrsChunkStream* stream = it->second; SrsChunkStream* stream = it->second;
srs_freep(stream);
if (stream) {
delete stream;
}
} }
chunk_streams.clear(); chunk_streams.clear();
if (buffer) { srs_freep(buffer);
delete buffer; srs_freep(skt);
buffer = NULL;
}
if (skt) {
delete skt;
skt = NULL;
}
} }
int SrsProtocol::recv_message(SrsMessage** pmsg) int SrsProtocol::recv_message(SrsMessage** pmsg)
@ -302,13 +293,13 @@ int SrsProtocol::recv_message(SrsMessage** pmsg)
srs_trace("ignore empty message(type=%d, size=%d, time=%d, sid=%d).", srs_trace("ignore empty message(type=%d, size=%d, time=%d, sid=%d).",
msg->header.message_type, msg->header.payload_length, msg->header.message_type, msg->header.payload_length,
msg->header.timestamp, msg->header.stream_id); msg->header.timestamp, msg->header.stream_id);
delete msg; srs_freep(msg);
continue; continue;
} }
if ((ret = on_recv_message(msg)) != ERROR_SUCCESS) { if ((ret = on_recv_message(msg)) != ERROR_SUCCESS) {
srs_error("hook the received msg failed. ret=%d", ret); srs_error("hook the received msg failed. ret=%d", ret);
delete msg; srs_freep(msg);
return ret; return ret;
} }
@ -615,13 +606,36 @@ 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, /**
// the fmt must be type0/type1 which means new message. * we should not assert anything about fmt, for the first packet.
if (!chunk->msg && fmt != RTMP_FMT_TYPE0 && fmt != RTMP_FMT_TYPE1) { * (when first packet, the chunk->msg is NULL).
* the fmt maybe 0/1/2/3, the FMLE will send a 0xC4 for some audio packet.
* the previous packet is:
* 04 // fmt=0, cid=4
* 00 00 1a // timestamp=26
* 00 00 9d // payload_length=157
* 08 // message_type=8(audio)
* 01 00 00 00 // stream_id=1
* the current packet maybe:
* c4 // fmt=3, cid=4
* it's ok, for the packet is audio, and timestamp delta is 26.
* the current packet must be parsed as:
* fmt=0, cid=4
* timestamp=26+26=52
* payload_length=157
* message_type=8(audio)
* stream_id=1
* so we must update the timestamp even fmt=3 for first packet.
*/
// fresh packet used to update the timestamp even fmt=3 for first packet.
bool is_fresh_packet = !chunk->msg;
// but, we can ensure that when a chunk stream is fresh,
// the fmt must be 0, a new stream.
if (chunk->msg_count == 0 && fmt != RTMP_FMT_TYPE0) {
ret = ERROR_RTMP_CHUNK_START; ret = ERROR_RTMP_CHUNK_START;
srs_error("chunk stream start, " srs_error("chunk stream is fresh, "
"fmt must be %d or %d, actual is %d. ret=%d", "fmt must be %d, actual is %d. ret=%d", RTMP_FMT_TYPE0, fmt, ret);
RTMP_FMT_TYPE0, RTMP_FMT_TYPE1, fmt, ret);
return ret; return ret;
} }
@ -636,13 +650,12 @@ 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 || 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);
} }
// read message header from socket to buffer. // read message header from socket to buffer.
static char mh_sizes[] = {11, 7, 1, 0}; static char mh_sizes[] = {11, 7, 3, 0};
mh_size = mh_sizes[(int)fmt]; mh_size = mh_sizes[(int)fmt];
srs_verbose("calc chunk message header size. fmt=%d, mh_size=%d", fmt, mh_size); srs_verbose("calc chunk message header size. fmt=%d, mh_size=%d", fmt, mh_size);
@ -656,8 +669,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
// parse the message header. // parse the message header.
// see also: ngx_rtmp_recv // see also: ngx_rtmp_recv
if (fmt <= RTMP_FMT_TYPE2) { if (fmt <= RTMP_FMT_TYPE2) {
int32_t timestamp_delta; char* pp = (char*)&chunk->header.timestamp_delta;
char* pp = (char*)&timestamp_delta;
pp[2] = *p++; pp[2] = *p++;
pp[1] = *p++; pp[1] = *p++;
pp[0] = *p++; pp[0] = *p++;
@ -667,13 +679,13 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
// 6.1.2.1. Type 0 // 6.1.2.1. Type 0
// For a type-0 chunk, the absolute timestamp of the message is sent // For a type-0 chunk, the absolute timestamp of the message is sent
// here. // here.
chunk->header.timestamp = timestamp_delta; chunk->header.timestamp = chunk->header.timestamp_delta;
} else { } else {
// 6.1.2.2. Type 1 // 6.1.2.2. Type 1
// 6.1.2.3. Type 2 // 6.1.2.3. Type 2
// For a type-1 or type-2 chunk, the difference between the previous // For a type-1 or type-2 chunk, the difference between the previous
// chunk's timestamp and the current chunk's timestamp is sent here. // chunk's timestamp and the current chunk's timestamp is sent here.
chunk->header.timestamp += timestamp_delta; chunk->header.timestamp += chunk->header.timestamp_delta;
} }
// fmt: 0 // fmt: 0
@ -689,7 +701,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
// 0x00ffffff), this value MUST be 16777215, and the extended // 0x00ffffff), this value MUST be 16777215, and the extended
// timestamp header MUST be present. Otherwise, this value SHOULD be // timestamp header MUST be present. Otherwise, this value SHOULD be
// the entire delta. // the entire delta.
chunk->extended_timestamp = (timestamp_delta >= RTMP_EXTENDED_TIMESTAMP); chunk->extended_timestamp = (chunk->header.timestamp_delta >= RTMP_EXTENDED_TIMESTAMP);
if (chunk->extended_timestamp) { if (chunk->extended_timestamp) {
chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP; chunk->header.timestamp = RTMP_EXTENDED_TIMESTAMP;
} }
@ -722,6 +734,10 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp); fmt, mh_size, chunk->extended_timestamp, chunk->header.timestamp);
} }
} else { } else {
// update the timestamp even fmt=3 for first stream
if (is_fresh_packet && !chunk->extended_timestamp) {
chunk->header.timestamp += chunk->header.timestamp_delta;
}
srs_verbose("header read completed. fmt=%d, size=%d, ext_time=%d", srs_verbose("header read completed. fmt=%d, size=%d, ext_time=%d",
fmt, mh_size, chunk->extended_timestamp); fmt, mh_size, chunk->extended_timestamp);
} }
@ -754,6 +770,9 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
// copy header to msg // copy header to msg
chunk->msg->header = chunk->header; chunk->msg->header = chunk->header;
// increase the msg count, the chunk stream can accept fmt=1/2/3 message now.
chunk->msg_count++;
return ret; return ret;
} }
@ -802,7 +821,7 @@ int SrsProtocol::read_message_payload(SrsChunkStream* chunk, int bh_size, int mh
buffer->erase(bh_size + mh_size + payload_size); buffer->erase(bh_size + mh_size + payload_size);
chunk->msg->size += payload_size; chunk->msg->size += payload_size;
srs_verbose("chunk payload read complted. bh_size=%d, mh_size=%d, payload_size=%d", bh_size, mh_size, payload_size); srs_verbose("chunk payload read completed. bh_size=%d, mh_size=%d, payload_size=%d", bh_size, mh_size, payload_size);
// got entire RTMP message? // got entire RTMP message?
if (chunk->header.payload_length == chunk->msg->size) { if (chunk->header.payload_length == chunk->msg->size) {
@ -826,8 +845,10 @@ SrsMessageHeader::SrsMessageHeader()
{ {
message_type = 0; message_type = 0;
payload_length = 0; payload_length = 0;
timestamp = 0; timestamp_delta = 0;
stream_id = 0; stream_id = 0;
timestamp = 0;
} }
SrsMessageHeader::~SrsMessageHeader() SrsMessageHeader::~SrsMessageHeader()
@ -849,20 +870,23 @@ bool SrsMessageHeader::is_window_ackledgement_size()
return message_type == RTMP_MSG_WindowAcknowledgementSize; return message_type == RTMP_MSG_WindowAcknowledgementSize;
} }
bool SrsMessageHeader::is_set_chunk_size()
{
return message_type == RTMP_MSG_SetChunkSize;
}
SrsChunkStream::SrsChunkStream(int _cid) SrsChunkStream::SrsChunkStream(int _cid)
{ {
fmt = 0; fmt = 0;
cid = _cid; cid = _cid;
extended_timestamp = false; extended_timestamp = false;
msg = NULL; msg = NULL;
msg_count = 0;
} }
SrsChunkStream::~SrsChunkStream() SrsChunkStream::~SrsChunkStream()
{ {
if (msg) { srs_freep(msg);
delete msg;
msg = NULL;
}
} }
SrsMessage::SrsMessage() SrsMessage::SrsMessage()
@ -875,20 +899,9 @@ SrsMessage::SrsMessage()
SrsMessage::~SrsMessage() SrsMessage::~SrsMessage()
{ {
if (payload) { srs_freep(payload);
delete[] payload; srs_freep(packet);
payload = NULL; srs_freep(stream);
}
if (packet) {
delete packet;
packet = NULL;
}
if (stream) {
delete stream;
stream = NULL;
}
} }
int SrsMessage::decode_packet() int SrsMessage::decode_packet()
@ -962,6 +975,10 @@ int SrsMessage::decode_packet()
srs_info("decode the AMF0/AMF3 command(FMLE FCPublish message)."); srs_info("decode the AMF0/AMF3 command(FMLE FCPublish message).");
packet = new SrsFMLEStartPacket(); packet = new SrsFMLEStartPacket();
return packet->decode(stream); return packet->decode(stream);
} else if(command == RTMP_AMF0_COMMAND_PUBLISH) {
srs_info("decode the AMF0/AMF3 command(publish message).");
packet = new SrsPublishPacket();
return packet->decode(stream);
} }
// default packet to drop message. // default packet to drop message.
@ -972,6 +989,10 @@ int SrsMessage::decode_packet()
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);
} else if(header.is_set_chunk_size()) {
srs_verbose("start to decode set chunk size message.");
packet = new SrsSetChunkSizePacket();
return packet->decode(stream);
} else { } else {
// default packet to drop message. // default packet to drop message.
srs_trace("drop the unknown message, type=%d", header.message_type); srs_trace("drop the unknown message, type=%d", header.message_type);
@ -1008,9 +1029,7 @@ int SrsMessage::get_perfer_cid()
void SrsMessage::set_packet(SrsPacket* pkt, int stream_id) void SrsMessage::set_packet(SrsPacket* pkt, int stream_id)
{ {
if (packet) { srs_freep(packet);
delete packet;
}
packet = pkt; packet = pkt;
@ -1029,10 +1048,7 @@ int SrsMessage::encode_packet()
} }
// realloc the payload. // realloc the payload.
size = 0; size = 0;
if (payload) { srs_freepa(payload);
delete[] payload;
payload = NULL;
}
return packet->encode(size, (char*&)payload); return packet->encode(size, (char*&)payload);
} }
@ -1087,14 +1103,14 @@ int SrsPacket::encode(int& psize, char*& ppayload)
if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) {
srs_error("initialize the stream failed. ret=%d", ret); srs_error("initialize the stream failed. ret=%d", ret);
delete[] payload; srs_freepa(payload);
return ret; return ret;
} }
} }
if ((ret = encode_packet(&stream)) != ERROR_SUCCESS) { if ((ret = encode_packet(&stream)) != ERROR_SUCCESS) {
srs_error("encode the packet failed. ret=%d", ret); srs_error("encode the packet failed. ret=%d", ret);
delete[] payload; srs_freepa(payload);
return ret; return ret;
} }
@ -1132,10 +1148,7 @@ SrsConnectAppPacket::SrsConnectAppPacket()
SrsConnectAppPacket::~SrsConnectAppPacket() SrsConnectAppPacket::~SrsConnectAppPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object;
command_object = NULL;
}
} }
int SrsConnectAppPacket::decode(SrsStream* stream) int SrsConnectAppPacket::decode(SrsStream* stream)
@ -1189,15 +1202,8 @@ SrsConnectAppResPacket::SrsConnectAppResPacket()
SrsConnectAppResPacket::~SrsConnectAppResPacket() SrsConnectAppResPacket::~SrsConnectAppResPacket()
{ {
if (props) { srs_freep(props);
delete props; srs_freep(info);
props = NULL;
}
if (info) {
delete info;
info = NULL;
}
} }
int SrsConnectAppResPacket::get_perfer_cid() int SrsConnectAppResPacket::get_perfer_cid()
@ -1259,10 +1265,7 @@ SrsCreateStreamPacket::SrsCreateStreamPacket()
SrsCreateStreamPacket::~SrsCreateStreamPacket() SrsCreateStreamPacket::~SrsCreateStreamPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object;
command_object = NULL;
}
} }
int SrsCreateStreamPacket::decode(SrsStream* stream) int SrsCreateStreamPacket::decode(SrsStream* stream)
@ -1305,10 +1308,7 @@ SrsCreateStreamResPacket::SrsCreateStreamResPacket(double _transaction_id, doubl
SrsCreateStreamResPacket::~SrsCreateStreamResPacket() SrsCreateStreamResPacket::~SrsCreateStreamResPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object;
command_object = NULL;
}
} }
int SrsCreateStreamResPacket::get_perfer_cid() int SrsCreateStreamResPacket::get_perfer_cid()
@ -1365,10 +1365,12 @@ SrsFMLEStartPacket::SrsFMLEStartPacket()
{ {
command_name = RTMP_AMF0_COMMAND_CREATE_STREAM; command_name = RTMP_AMF0_COMMAND_CREATE_STREAM;
transaction_id = 0; transaction_id = 0;
command_object = new SrsAmf0Null();
} }
SrsFMLEStartPacket::~SrsFMLEStartPacket() SrsFMLEStartPacket::~SrsFMLEStartPacket()
{ {
srs_freep(command_object);
} }
int SrsFMLEStartPacket::decode(SrsStream* stream) int SrsFMLEStartPacket::decode(SrsStream* stream)
@ -1380,8 +1382,8 @@ int SrsFMLEStartPacket::decode(SrsStream* stream)
return ret; return ret;
} }
if (command_name.empty() if (command_name.empty()
|| command_name != RTMP_AMF0_COMMAND_RELEASE_STREAM || (command_name != RTMP_AMF0_COMMAND_RELEASE_STREAM
|| command_name != RTMP_AMF0_COMMAND_FC_PUBLISH && command_name != RTMP_AMF0_COMMAND_FC_PUBLISH)
) { ) {
ret = ERROR_RTMP_AMF0_DECODE; ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode FMLE start command_name failed. " srs_error("amf0 decode FMLE start command_name failed. "
@ -1394,6 +1396,11 @@ int SrsFMLEStartPacket::decode(SrsStream* stream)
return ret; return ret;
} }
if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
srs_error("amf0 decode FMLE start command_object failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) { if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) {
srs_error("amf0 decode FMLE start stream_name failed. ret=%d", ret); srs_error("amf0 decode FMLE start stream_name failed. ret=%d", ret);
return ret; return ret;
@ -1414,14 +1421,8 @@ SrsFMLEStartResPacket::SrsFMLEStartResPacket(double _transaction_id)
SrsFMLEStartResPacket::~SrsFMLEStartResPacket() SrsFMLEStartResPacket::~SrsFMLEStartResPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object; srs_freep(args);
command_object = NULL;
}
if (args) {
delete args;
args = NULL;
}
} }
int SrsFMLEStartResPacket::get_perfer_cid() int SrsFMLEStartResPacket::get_perfer_cid()
@ -1474,6 +1475,59 @@ int SrsFMLEStartResPacket::encode_packet(SrsStream* stream)
return ret; return ret;
} }
SrsPublishPacket::SrsPublishPacket()
{
command_name = RTMP_AMF0_COMMAND_PUBLISH;
transaction_id = 0;
command_object = new SrsAmf0Null();
type = "live";
}
SrsPublishPacket::~SrsPublishPacket()
{
srs_freep(command_object);
}
int SrsPublishPacket::decode(SrsStream* stream)
{
int ret = ERROR_SUCCESS;
if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
srs_error("amf0 decode publish command_name failed. ret=%d", ret);
return ret;
}
if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_PUBLISH) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode publish 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 publish transaction_id failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
srs_error("amf0 decode publish command_object failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_read_string(stream, stream_name)) != ERROR_SUCCESS) {
srs_error("amf0 decode publish stream_name failed. ret=%d", ret);
return ret;
}
if ((ret = srs_amf0_read_string(stream, type)) != ERROR_SUCCESS) {
srs_error("amf0 decode publish type failed. ret=%d", ret);
return ret;
}
srs_info("amf0 decode publish packet success");
return ret;
}
SrsPlayPacket::SrsPlayPacket() SrsPlayPacket::SrsPlayPacket()
{ {
command_name = RTMP_AMF0_COMMAND_PLAY; command_name = RTMP_AMF0_COMMAND_PLAY;
@ -1487,10 +1541,7 @@ SrsPlayPacket::SrsPlayPacket()
SrsPlayPacket::~SrsPlayPacket() SrsPlayPacket::~SrsPlayPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object;
command_object = NULL;
}
} }
int SrsPlayPacket::decode(SrsStream* stream) int SrsPlayPacket::decode(SrsStream* stream)
@ -1551,15 +1602,8 @@ SrsPlayResPacket::SrsPlayResPacket()
SrsPlayResPacket::~SrsPlayResPacket() SrsPlayResPacket::~SrsPlayResPacket()
{ {
if (command_object) { srs_freep(command_object);
delete command_object; srs_freep(desc);
command_object = NULL;
}
if (desc) {
delete desc;
desc = NULL;
}
} }
int SrsPlayResPacket::get_perfer_cid() int SrsPlayResPacket::get_perfer_cid()
@ -1621,10 +1665,7 @@ SrsOnBWDonePacket::SrsOnBWDonePacket()
SrsOnBWDonePacket::~SrsOnBWDonePacket() SrsOnBWDonePacket::~SrsOnBWDonePacket()
{ {
if (args) { srs_freep(args);
delete args;
args = NULL;
}
} }
int SrsOnBWDonePacket::get_perfer_cid() int SrsOnBWDonePacket::get_perfer_cid()
@ -1680,15 +1721,8 @@ SrsOnStatusCallPacket::SrsOnStatusCallPacket()
SrsOnStatusCallPacket::~SrsOnStatusCallPacket() SrsOnStatusCallPacket::~SrsOnStatusCallPacket()
{ {
if (args) { srs_freep(args);
delete args; srs_freep(data);
args = NULL;
}
if (data) {
delete data;
data = NULL;
}
} }
int SrsOnStatusCallPacket::get_perfer_cid() int SrsOnStatusCallPacket::get_perfer_cid()
@ -1748,10 +1782,7 @@ SrsOnStatusDataPacket::SrsOnStatusDataPacket()
SrsOnStatusDataPacket::~SrsOnStatusDataPacket() SrsOnStatusDataPacket::~SrsOnStatusDataPacket()
{ {
if (data) { srs_freep(data);
delete data;
data = NULL;
}
} }
int SrsOnStatusDataPacket::get_perfer_cid() int SrsOnStatusDataPacket::get_perfer_cid()

View file

@ -160,22 +160,29 @@ struct SrsMessageHeader
*/ */
int32_t payload_length; int32_t payload_length;
/** /**
* Four-byte field that contains a timestamp of the message. * Three-byte field that contains a timestamp delta of the message.
* The 4 bytes are packed in the big-endian order. * The 4 bytes are packed in the big-endian order.
*/ */
int32_t timestamp; int32_t timestamp_delta;
/** /**
* Three-byte field that identifies the stream of the message. These * Three-byte field that identifies the stream of the message. These
* bytes are set in big-endian format. * bytes are set in big-endian format.
*/ */
int32_t stream_id; int32_t stream_id;
/**
* Four-byte field that contains a timestamp of the message.
* The 4 bytes are packed in the big-endian order.
*/
int32_t timestamp;
SrsMessageHeader(); SrsMessageHeader();
virtual ~SrsMessageHeader(); virtual ~SrsMessageHeader();
bool is_amf0_command(); bool is_amf0_command();
bool is_amf3_command(); bool is_amf3_command();
bool is_window_ackledgement_size(); bool is_window_ackledgement_size();
bool is_set_chunk_size();
}; };
/** /**
@ -207,6 +214,10 @@ public:
* partially read message. * partially read message.
*/ */
SrsMessage* msg; SrsMessage* msg;
/**
* decoded msg count, to identify whether the chunk stream is fresh.
*/
int64_t msg_count;
public: public:
SrsChunkStream(int _cid); SrsChunkStream(int _cid);
virtual ~SrsChunkStream(); virtual ~SrsChunkStream();
@ -257,7 +268,7 @@ public:
* @stream_id, the id of stream which is created by createStream. * @stream_id, the id of stream which is created by createStream.
* @remark, user never free the pkt, the message will auto free it. * @remark, user never free the pkt, the message will auto free it.
*/ */
virtual void set_packet(SrsPacket* pkt, int stream_id = 0); virtual void set_packet(SrsPacket* pkt, int stream_id);
/** /**
* encode the packet to message payload bytes. * encode the packet to message payload bytes.
* @remark there exists empty packet, so maybe the payload is NULL. * @remark there exists empty packet, so maybe the payload is NULL.
@ -443,6 +454,7 @@ protected:
public: public:
std::string command_name; std::string command_name;
double transaction_id; double transaction_id;
SrsAmf0Null* command_object;
std::string stream_name; std::string stream_name;
public: public:
SrsFMLEStartPacket(); SrsFMLEStartPacket();
@ -479,6 +491,35 @@ protected:
virtual int encode_packet(SrsStream* stream); virtual int encode_packet(SrsStream* stream);
}; };
/**
* FMLE/flash publish
* 4.2.6. Publish
* The client sends the publish command to publish a named stream to the
* server. Using this name, any client can play this stream and receive
* the published audio, video, and data messages.
*/
class SrsPublishPacket : public SrsPacket
{
private:
typedef SrsPacket super;
protected:
virtual const char* get_class_name()
{
return CLASS_NAME_STRING(SrsPublishPacket);
}
public:
std::string command_name;
double transaction_id;
SrsAmf0Null* command_object;
std::string stream_name;
std::string type;
public:
SrsPublishPacket();
virtual ~SrsPublishPacket();
public:
virtual int decode(SrsStream* stream);
};
/** /**
* 4.2.1. play * 4.2.1. play
* The client sends this command to the server to play a stream. * The client sends this command to the server to play a stream.
@ -566,7 +607,7 @@ protected:
/** /**
* onStatus command, AMF0 Call * onStatus command, AMF0 Call
* @remark, user must set the stream_id in header. * @remark, user must set the stream_id by SrsMessage.set_packet().
*/ */
class SrsOnStatusCallPacket : public SrsPacket class SrsOnStatusCallPacket : public SrsPacket
{ {
@ -596,7 +637,7 @@ protected:
/** /**
* onStatus data, AMF0 Data * onStatus data, AMF0 Data
* @remark, user must set the stream_id in header. * @remark, user must set the stream_id by SrsMessage.set_packet().
*/ */
class SrsOnStatusDataPacket : public SrsPacket class SrsOnStatusDataPacket : public SrsPacket
{ {
@ -624,7 +665,7 @@ protected:
/** /**
* AMF0Data RtmpSampleAccess * AMF0Data RtmpSampleAccess
* @remark, user must set the stream_id in header. * @remark, user must set the stream_id by SrsMessage.set_packet().
*/ */
class SrsSampleAccessPacket : public SrsPacket class SrsSampleAccessPacket : public SrsPacket
{ {

View file

@ -51,8 +51,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define StatusCodeConnectSuccess "NetConnection.Connect.Success" #define StatusCodeConnectSuccess "NetConnection.Connect.Success"
#define StatusCodeStreamReset "NetStream.Play.Reset" #define StatusCodeStreamReset "NetStream.Play.Reset"
#define StatusCodeStreamStart "NetStream.Play.Start" #define StatusCodeStreamStart "NetStream.Play.Start"
#define StatusCodePublishStart "NetStream.Publish.Start"
#define StatusCodeDataStart "NetStream.Data.Start" #define StatusCodeDataStart "NetStream.Data.Start"
// FMLE
#define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish"
SrsRequest::SrsRequest() SrsRequest::SrsRequest()
{ {
objectEncoding = RTMP_SIG_AMF0_VER; objectEncoding = RTMP_SIG_AMF0_VER;
@ -111,10 +115,7 @@ SrsRtmp::SrsRtmp(st_netfd_t client_stfd)
SrsRtmp::~SrsRtmp() SrsRtmp::~SrsRtmp()
{ {
if (protocol) { srs_freep(protocol);
delete protocol;
protocol = NULL;
}
} }
int SrsRtmp::handshake() int SrsRtmp::handshake()
@ -210,7 +211,7 @@ int SrsRtmp::set_window_ack_size(int ack_size)
SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket(); SrsSetWindowAckSizePacket* pkt = new SrsSetWindowAckSizePacket();
pkt->ackowledgement_window_size = ack_size; pkt->ackowledgement_window_size = ack_size;
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send ack size message failed. ret=%d", ret); srs_error("send ack size message failed. ret=%d", ret);
@ -230,7 +231,7 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type)
pkt->bandwidth = bandwidth; pkt->bandwidth = bandwidth;
pkt->type = type; pkt->type = type;
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send set bandwidth message failed. ret=%d", ret); srs_error("send set bandwidth message failed. ret=%d", ret);
@ -249,23 +250,23 @@ int SrsRtmp::response_connect_app(SrsRequest* req)
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket();
pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER); pkt->props->set("fmsVer", new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER));
pkt->props->properties["capabilities"] = new SrsAmf0Number(123); pkt->props->set("capabilities", new SrsAmf0Number(127));
pkt->props->properties["mode"] = new SrsAmf0Number(1); pkt->props->set("mode", new SrsAmf0Number(1));
pkt->info->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus); pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
pkt->info->properties[StatusCode] = new SrsAmf0String(StatusCodeConnectSuccess); pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess));
pkt->info->properties[StatusDescription] = new SrsAmf0String("Connection succeeded"); pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded"));
pkt->info->properties["objectEncoding"] = new SrsAmf0Number(req->objectEncoding); pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding));
SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray();
pkt->info->properties["data"] = data; pkt->info->set("data", data);
data->properties["version"] = new SrsAmf0String(RTMP_SIG_FMS_VER); data->set("version", new SrsAmf0String(RTMP_SIG_FMS_VER));
data->properties["server"] = new SrsAmf0String(RTMP_SIG_SRS_NAME); data->set("server", new SrsAmf0String(RTMP_SIG_SRS_NAME));
data->properties["srs_url"] = new SrsAmf0String(RTMP_SIG_SRS_URL); data->set("srs_url", new SrsAmf0String(RTMP_SIG_SRS_URL));
data->properties["srs_version"] = new SrsAmf0String(RTMP_SIG_SRS_VERSION); data->set("srs_version", new SrsAmf0String(RTMP_SIG_SRS_VERSION));
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send connect app response message failed. ret=%d", ret); srs_error("send connect app response message failed. ret=%d", ret);
@ -283,7 +284,7 @@ int SrsRtmp::on_bw_done()
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket(); SrsOnBWDonePacket* pkt = new SrsOnBWDonePacket();
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onBWDone message failed. ret=%d", ret); srs_error("send onBWDone message failed. ret=%d", ret);
@ -345,7 +346,7 @@ int SrsRtmp::set_chunk_size(int chunk_size)
SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket(); SrsSetChunkSizePacket* pkt = new SrsSetChunkSizePacket();
pkt->chunk_size = chunk_size; pkt->chunk_size = chunk_size;
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send set chunk size message failed. ret=%d", ret); srs_error("send set chunk size message failed. ret=%d", ret);
@ -367,7 +368,7 @@ int SrsRtmp::start_play(int stream_id)
pkt->event_type = SrcPCUCStreamBegin; pkt->event_type = SrcPCUCStreamBegin;
pkt->event_data = stream_id; pkt->event_data = stream_id;
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret); srs_error("send PCUC(StreamBegin) message failed. ret=%d", ret);
@ -381,14 +382,13 @@ int SrsRtmp::start_play(int stream_id)
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
pkt->data->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus); pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeStreamReset); pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamReset));
pkt->data->properties[StatusDescription] = new SrsAmf0String("Playing and resetting stream."); pkt->data->set(StatusDescription, new SrsAmf0String("Playing and resetting stream."));
pkt->data->properties[StatusDetails] = new SrsAmf0String("stream"); pkt->data->set(StatusDetails, new SrsAmf0String("stream"));
pkt->data->properties[StatusClientId] = new SrsAmf0String(RTMP_SIG_CLIENT_ID); pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID));
msg->header.stream_id = stream_id; msg->set_packet(pkt, stream_id);
msg->set_packet(pkt);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret);
@ -402,14 +402,13 @@ int SrsRtmp::start_play(int stream_id)
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket(); SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
pkt->data->properties[StatusLevel] = new SrsAmf0String(StatusLevelStatus); pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeStreamStart); pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeStreamStart));
pkt->data->properties[StatusDescription] = new SrsAmf0String("Started playing stream."); pkt->data->set(StatusDescription, new SrsAmf0String("Started playing stream."));
pkt->data->properties[StatusDetails] = new SrsAmf0String("stream"); pkt->data->set(StatusDetails, new SrsAmf0String("stream"));
pkt->data->properties[StatusClientId] = new SrsAmf0String(RTMP_SIG_CLIENT_ID); pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID));
msg->header.stream_id = stream_id; msg->set_packet(pkt, stream_id);
msg->set_packet(pkt);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret); srs_error("send onStatus(NetStream.Play.Reset) message failed. ret=%d", ret);
@ -423,8 +422,7 @@ int SrsRtmp::start_play(int stream_id)
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket(); SrsSampleAccessPacket* pkt = new SrsSampleAccessPacket();
msg->header.stream_id = stream_id; msg->set_packet(pkt, stream_id);
msg->set_packet(pkt);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret); srs_error("send |RtmpSampleAccess(false, false) message failed. ret=%d", ret);
@ -438,10 +436,9 @@ int SrsRtmp::start_play(int stream_id)
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket(); SrsOnStatusDataPacket* pkt = new SrsOnStatusDataPacket();
pkt->data->properties[StatusCode] = new SrsAmf0String(StatusCodeDataStart); pkt->data->set(StatusCode, new SrsAmf0String(StatusCodeDataStart));
msg->header.stream_id = stream_id; msg->set_packet(pkt, stream_id);
msg->set_packet(pkt);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret); srs_error("send onStatus(NetStream.Data.Start) message failed. ret=%d", ret);
@ -463,7 +460,7 @@ int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int strea
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id); SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id);
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send createStream response message failed. ret=%d", ret); srs_error("send createStream response message failed. ret=%d", ret);
@ -519,7 +516,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, int stream_id
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id); SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(req->transaction_id);
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send releaseStream response message failed. ret=%d", ret); srs_error("send releaseStream response message failed. ret=%d", ret);
@ -547,7 +544,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, int stream_id
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid); SrsFMLEStartResPacket* pkt = new SrsFMLEStartResPacket(fc_publish_tid);
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send FCPublish response message failed. ret=%d", ret); srs_error("send FCPublish response message failed. ret=%d", ret);
@ -575,7 +572,7 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, int stream_id
SrsMessage* msg = new SrsMessage(); SrsMessage* msg = new SrsMessage();
SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id); SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(create_stream_tid, stream_id);
msg->set_packet(pkt); msg->set_packet(pkt, 0);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send createStream response message failed. ret=%d", ret); srs_error("send createStream response message failed. ret=%d", ret);
@ -584,6 +581,64 @@ int SrsRtmp::identify_fmle_publish_client(SrsFMLEStartPacket* req, int stream_id
srs_info("send createStream response message success."); srs_info("send createStream response message success.");
} }
// publish
if (true) {
SrsMessage* msg = NULL;
SrsPublishPacket* pkt = NULL;
if ((ret = srs_rtmp_expect_message<SrsPublishPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
srs_error("recv publish message failed. ret=%d", ret);
return ret;
}
srs_info("recv publish request message success.");
SrsAutoFree(SrsMessage, msg, false);
}
// publish response onFCPublish(NetStream.Publish.Start)
if (true) {
SrsMessage* msg = new SrsMessage();
SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
pkt->command_name = RTMP_AMF0_COMMAND_ON_FC_PUBLISH;
pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart));
pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream."));
msg->set_packet(pkt, stream_id);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onFCPublish(NetStream.Publish.Start) message failed. ret=%d", ret);
return ret;
}
srs_info("send onFCPublish(NetStream.Publish.Start) message success.");
}
// publish response onStatus(NetStream.Publish.Start)
if (true) {
SrsMessage* msg = new SrsMessage();
SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket();
pkt->data->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
pkt->data->set(StatusCode, new SrsAmf0String(StatusCodePublishStart));
pkt->data->set(StatusDescription, new SrsAmf0String("Started publishing stream."));
pkt->data->set(StatusClientId, new SrsAmf0String(RTMP_SIG_CLIENT_ID));
msg->set_packet(pkt, stream_id);
if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
srs_error("send onStatus(NetStream.Publish.Start) message failed. ret=%d", ret);
return ret;
}
srs_info("send onStatus(NetStream.Publish.Start) 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);
}
return ret; return ret;
} }

View file

@ -45,7 +45,7 @@ SrsServer::~SrsServer()
{ {
for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end(); ++it) { for (std::vector<SrsConnection*>::iterator it = conns.begin(); it != conns.end(); ++it) {
SrsConnection* conn = *it; SrsConnection* conn = *it;
delete conn; srs_freep(conn);
} }
conns.clear(); conns.clear();
} }
@ -151,8 +151,8 @@ void SrsServer::remove(SrsConnection* conn)
srs_info("conn removed. conns=%d", (int)conns.size()); srs_info("conn removed. conns=%d", (int)conns.size());
// all connections are created by server, // all connections are created by server,
// so we delete it here. // so we free it here.
delete conn; srs_freep(conn);
} }
int SrsServer::accept_client(st_netfd_t client_stfd) int SrsServer::accept_client(st_netfd_t client_stfd)