support amf0 StrictArray(0x0a). 0.9.111.

pull/133/head
winlin 11 years ago
parent c8f80414ef
commit 7f48590239

@ -230,6 +230,7 @@ Supported operating systems and hardware:
* 2013-10-17, Created.<br/>
## History
* v1.0, 2014-05-22, support amf0 StrictArray(0x0a). 0.9.111.
* v1.0, 2014-05-22, support flv parser, add amf0 to librtmp. 0.9.110
* v1.0, 2014-05-22, fix [#74](https://github.com/winlinvip/simple-rtmp-server/issues/74), add tcUrl for http callback on_connect, 0.9.109
* v1.0, 2014-05-19, support http heartbeat, 0.9.107

@ -484,6 +484,12 @@ amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0)
return any->is_ecma_array();
}
amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0)
{
SrsAmf0Any* any = (SrsAmf0Any*)amf0;
return any->is_strict_array();
}
const char* srs_amf0_to_string(srs_amf0_t amf0)
{
SrsAmf0Any* any = (SrsAmf0Any*)amf0;
@ -520,32 +526,44 @@ srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index)
return (srs_amf0_t)obj->value_at(index);
}
int srs_amf0_array_property_count(srs_amf0_t amf0)
int srs_amf0_ecma_array_property_count(srs_amf0_t amf0)
{
SrsAmf0EcmaArray * obj = (SrsAmf0EcmaArray*)amf0;
return obj->count();
}
const char* srs_amf0_array_property_name_at(srs_amf0_t amf0, int index)
const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index)
{
SrsAmf0EcmaArray* obj = (SrsAmf0EcmaArray*)amf0;
return obj->key_raw_at(index);
}
srs_amf0_t srs_amf0_array_property_value_at(srs_amf0_t amf0, int index)
srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index)
{
SrsAmf0EcmaArray* obj = (SrsAmf0EcmaArray*)amf0;
return (srs_amf0_t)obj->value_at(index);
}
void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int& level)
int srs_amf0_strict_array_property_count(srs_amf0_t amf0)
{
if (true) {
for (int i = 0; i < level; i++) {
ss << " ";
}
SrsAmf0EcmaArray * obj = (SrsAmf0EcmaArray*)amf0;
return obj->count();
}
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index)
{
SrsAmf0EcmaArray* obj = (SrsAmf0EcmaArray*)amf0;
return (srs_amf0_t)obj->value_at(index);
}
void __srs_fill_level_spaces(stringstream& ss, int level)
{
for (int i = 0; i < level; i++) {
ss << " ";
}
}
void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level)
{
if (any->is_boolean()) {
ss << "Boolean " << (any->to_boolean()? "true":"false") << endl;
} else if (any->is_number()) {
@ -558,26 +576,36 @@ void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int& level)
SrsAmf0EcmaArray* obj = any->to_ecma_array();
ss << "EcmaArray " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
ss << " Property '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_object() || obj->value_at(i)->is_ecma_array()) {
int next_level = level + 1;
__srs_amf0_do_print(obj->value_at(i), ss, next_level);
__srs_fill_level_spaces(ss, level + 1);
ss << "Elem '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_complex_object()) {
__srs_amf0_do_print(obj->value_at(i), ss, level + 1);
} else {
int next_level = 0;
__srs_amf0_do_print(obj->value_at(i), ss, next_level);
__srs_amf0_do_print(obj->value_at(i), ss, 0);
}
}
} else if (any->is_strict_array()) {
SrsAmf0StrictArray* obj = any->to_strict_array();
ss << "StrictArray " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
__srs_fill_level_spaces(ss, level + 1);
ss << "Elem ";
if (obj->at(i)->is_complex_object()) {
__srs_amf0_do_print(obj->at(i), ss, level + 1);
} else {
__srs_amf0_do_print(obj->at(i), ss, 0);
}
}
} else if (any->is_object()) {
SrsAmf0Object* obj = any->to_object();
ss << "Object " << "(" << obj->count() << " items)" << endl;
for (int i = 0; i < obj->count(); i++) {
ss << " Property '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_object() || obj->value_at(i)->is_ecma_array()) {
int next_level = level + 1;
__srs_amf0_do_print(obj->value_at(i), ss, next_level);
__srs_fill_level_spaces(ss, level + 1);
ss << "Property '" << obj->key_at(i) << "' ";
if (obj->value_at(i)->is_complex_object()) {
__srs_amf0_do_print(obj->value_at(i), ss, level + 1);
} else {
int next_level = 0;
__srs_amf0_do_print(obj->value_at(i), ss, next_level);
__srs_amf0_do_print(obj->value_at(i), ss, 0);
}
}
} else {
@ -587,23 +615,29 @@ void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int& level)
char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize)
{
if (!amf0) {
return NULL;
}
stringstream ss;
ss.precision(1);
SrsAmf0Any* any = (SrsAmf0Any*)amf0;
int level = 0;
__srs_amf0_do_print(any, ss, level);
__srs_amf0_do_print(any, ss, 0);
string str = ss.str();
if (str.empty()) {
return NULL;
}
*pdata = new char[str.length()];
char* data = new char[str.length() + 1];
memcpy(data, str.data(), str.length());
data[str.length()] = 0;
*pdata = data;
*psize = str.length();
memcpy(*pdata, str.data(), str.length());
return *pdata;
}

@ -176,6 +176,7 @@ amf0_bool srs_amf0_is_number(srs_amf0_t amf0);
amf0_bool srs_amf0_is_null(srs_amf0_t amf0);
amf0_bool srs_amf0_is_object(srs_amf0_t amf0);
amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);
amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
/* value converter */
const char* srs_amf0_to_string(srs_amf0_t amf0);
amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
@ -184,10 +185,13 @@ amf0_number srs_amf0_to_number(srs_amf0_t amf0);
int srs_amf0_object_property_count(srs_amf0_t amf0);
const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_object_property_value_at(srs_amf0_t amf0, int index);
/* array value converter */
int srs_amf0_array_property_count(srs_amf0_t amf0);
const char* srs_amf0_array_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_array_property_value_at(srs_amf0_t amf0, int index);
/* ecma array value converter */
int srs_amf0_ecma_array_property_count(srs_amf0_t amf0);
const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
/* strict array value converter */
int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
/* human readable print */
char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize);

@ -251,6 +251,16 @@ bool SrsAmf0Any::is_ecma_array()
return marker == RTMP_AMF0_EcmaArray;
}
bool SrsAmf0Any::is_strict_array()
{
return marker == RTMP_AMF0_StrictArray;
}
bool SrsAmf0Any::is_complex_object()
{
return is_object() || is_object_eof() || is_ecma_array() || is_strict_array();
}
string SrsAmf0Any::to_str()
{
__SrsAmf0String* p = dynamic_cast<__SrsAmf0String*>(this);
@ -293,6 +303,13 @@ SrsAmf0EcmaArray* SrsAmf0Any::to_ecma_array()
return p;
}
SrsAmf0StrictArray* SrsAmf0Any::to_strict_array()
{
SrsAmf0StrictArray* p = dynamic_cast<SrsAmf0StrictArray*>(this);
srs_assert(p != NULL);
return p;
}
bool SrsAmf0Any::is_object_eof()
{
return marker == RTMP_AMF0_ObjectEnd;
@ -338,6 +355,11 @@ SrsAmf0EcmaArray* SrsAmf0Any::ecma_array()
return new SrsAmf0EcmaArray();
}
SrsAmf0StrictArray* SrsAmf0Any::strict_array()
{
return new SrsAmf0StrictArray();
}
int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
{
int ret = ERROR_SUCCESS;
@ -390,6 +412,10 @@ int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
*ppvalue = SrsAmf0Any::ecma_array();
return ret;
}
case RTMP_AMF0_StrictArray: {
*ppvalue = SrsAmf0Any::strict_array();
return ret;
}
case RTMP_AMF0_Invalid:
default: {
ret = ERROR_RTMP_AMF0_INVALID;
@ -956,6 +982,137 @@ SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_number(string name)
return properties->ensure_property_number(name);
}
SrsAmf0StrictArray::SrsAmf0StrictArray()
{
marker = RTMP_AMF0_StrictArray;
}
SrsAmf0StrictArray::~SrsAmf0StrictArray()
{
std::vector<SrsAmf0Any*>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = *it;
srs_freep(any);
}
properties.clear();
}
int SrsAmf0StrictArray::total_size()
{
int size = 1 + 4;
for (int i = 0; i < (int)properties.size(); i++){
SrsAmf0Any* any = properties[i];
size += any->total_size();
}
return size;
}
int SrsAmf0StrictArray::read(SrsStream* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read strict_array marker failed. ret=%d", ret);
return ret;
}
char marker = stream->read_1bytes();
if (marker != RTMP_AMF0_StrictArray) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 check strict_array marker failed. "
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
return ret;
}
srs_verbose("amf0 read strict_array marker success");
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 read strict_array count failed. ret=%d", ret);
return ret;
}
int32_t count = stream->read_4bytes();
srs_verbose("amf0 read strict_array count success. count=%d", count);
// value
this->_count = count;
for (int i = 0; i < count && !stream->empty(); i++) {
// property-value: any
SrsAmf0Any* elem = NULL;
if ((ret = srs_amf0_read_any(stream, &elem)) != ERROR_SUCCESS) {
srs_error("amf0 strict_array read value failed. ret=%d", ret);
return ret;
}
// add property
properties.push_back(elem);
}
return ret;
}
int SrsAmf0StrictArray::write(SrsStream* stream)
{
int ret = ERROR_SUCCESS;
// marker
if (!stream->require(1)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write strict_array marker failed. ret=%d", ret);
return ret;
}
stream->write_1bytes(RTMP_AMF0_StrictArray);
srs_verbose("amf0 write strict_array marker success");
// count
if (!stream->require(4)) {
ret = ERROR_RTMP_AMF0_ENCODE;
srs_error("amf0 write strict_array count failed. ret=%d", ret);
return ret;
}
stream->write_4bytes(this->_count);
srs_verbose("amf0 write strict_array count success. count=%d", _count);
// value
for (int i = 0; i < (int)properties.size(); i++) {
SrsAmf0Any* any = properties[i];
if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) {
srs_error("write strict_array property value failed. ret=%d", ret);
return ret;
}
srs_verbose("write amf0 property success. name=%s", name.c_str());
}
srs_verbose("write strict_array object success.");
return ret;
}
void SrsAmf0StrictArray::clear()
{
properties.clear();
}
int SrsAmf0StrictArray::count()
{
return properties.size();
}
SrsAmf0Any* SrsAmf0StrictArray::at(int index)
{
srs_assert(index < (int)properties.size());
return properties.at(index);
}
int SrsAmf0Size::utf8(string value)
{
return 2 + value.length();
@ -1009,6 +1166,15 @@ int SrsAmf0Size::ecma_array(SrsAmf0EcmaArray* arr)
return arr->total_size();
}
int SrsAmf0Size::strict_array(SrsAmf0StrictArray* arr)
{
if (!arr) {
return 0;
}
return arr->total_size();
}
int SrsAmf0Size::any(SrsAmf0Any* o)
{
if (!o) {

@ -31,10 +31,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#include <string>
#include <vector>
class SrsStream;
class SrsAmf0Object;
class SrsAmf0EcmaArray;
class SrsAmf0StrictArray;
class __SrsUnSortedHashtable;
class __SrsAmf0ObjectEOF;
@ -96,6 +98,9 @@ public:
virtual bool is_object();
virtual bool is_object_eof();
virtual bool is_ecma_array();
virtual bool is_strict_array();
public:
virtual bool is_complex_object();
public:
/**
* get the string of any when is_string() indicates true.
@ -123,6 +128,7 @@ public:
* user must ensure the type is a ecma array, or assert failed.
*/
virtual SrsAmf0EcmaArray* to_ecma_array();
virtual SrsAmf0StrictArray* to_strict_array();
public:
/**
* get the size of amf0 any, including the marker size.
@ -142,6 +148,7 @@ public:
static SrsAmf0Object* object();
static SrsAmf0Any* object_eof();
static SrsAmf0EcmaArray* ecma_array();
static SrsAmf0StrictArray* strict_array();
public:
static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue);
};
@ -225,6 +232,36 @@ public:
virtual SrsAmf0Any* ensure_property_number(std::string name);
};
/**
* 2.12 Strict Array Type
* array-count = U32
* strict-array-type = array-count *(value-type)
*/
class SrsAmf0StrictArray : public SrsAmf0Any
{
private:
std::vector<SrsAmf0Any*> properties;
int32_t _count;
private:
// use SrsAmf0Any::strict_array() to create it.
friend class SrsAmf0Any;
SrsAmf0StrictArray();
public:
virtual ~SrsAmf0StrictArray();
public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
public:
virtual void clear();
virtual int count();
// @remark: max index is count().
virtual SrsAmf0Any* at(int index);
};
/**
* the class to get amf0 object size
*/
@ -240,6 +277,7 @@ public:
static int object(SrsAmf0Object* obj);
static int object_eof();
static int ecma_array(SrsAmf0EcmaArray* arr);
static int strict_array(SrsAmf0StrictArray* arr);
static int any(SrsAmf0Any* o);
};

Loading…
Cancel
Save