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:
parent
e598616e14
commit
33c586181d
9 changed files with 497 additions and 249 deletions
|
@ -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
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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*)×tamp_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()
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue