diff --git a/trunk/src/rtmp/srs_protocol_amf0.cpp b/trunk/src/rtmp/srs_protocol_amf0.cpp index 9f1efcd83..55766b8ee 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.cpp +++ b/trunk/src/rtmp/srs_protocol_amf0.cpp @@ -57,18 +57,139 @@ using namespace std; #define RTMP_AMF0_Invalid 0x3F /** -* convert the any to specified object. -* @return T, the converted object. never NULL. -* @remark, user must ensure the current object type, -* or the covert will cause assert failed. +* read amf0 string from stream. +* 2.4 String Type +* string-type = string-marker UTF-8 +* @return default value is empty string. +* @remark: use SrsAmf0Any::str() to create it. */ -template -T srs_amf0_convert(SrsAmf0Any* any) +class __SrsAmf0String : public SrsAmf0Any { - T p = dynamic_cast(any); - srs_assert(p != NULL); - return p; -} +public: + std::string value; + + __SrsAmf0String(const char* _value); + virtual ~__SrsAmf0String(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; + +/** +* read amf0 boolean from stream. +* 2.4 String Type +* boolean-type = boolean-marker U8 +* 0 is false, <> 0 is true +* @return default value is false. +*/ +class __SrsAmf0Boolean : public SrsAmf0Any +{ +public: + bool value; + + __SrsAmf0Boolean(bool _value); + virtual ~__SrsAmf0Boolean(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; + +/** +* read amf0 number from stream. +* 2.2 Number Type +* number-type = number-marker DOUBLE +* @return default value is 0. +*/ +class __SrsAmf0Number : public SrsAmf0Any +{ +public: + double value; + + __SrsAmf0Number(double _value); + virtual ~__SrsAmf0Number(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; + +/** +* read amf0 null from stream. +* 2.7 null Type +* null-type = null-marker +*/ +class __SrsAmf0Null : public SrsAmf0Any +{ +public: + __SrsAmf0Null(); + virtual ~__SrsAmf0Null(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; + +/** +* read amf0 undefined from stream. +* 2.8 undefined Type +* undefined-type = undefined-marker +*/ +class __SrsAmf0Undefined : public SrsAmf0Any +{ +public: + __SrsAmf0Undefined(); + virtual ~__SrsAmf0Undefined(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; + +/** +* 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. +*/ +class __SrsUnSortedHashtable +{ +private: + typedef std::pair SrsObjectPropertyType; + std::vector properties; +public: + __SrsUnSortedHashtable(); + virtual ~__SrsUnSortedHashtable(); + + virtual int size(); + virtual void clear(); + 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); + virtual SrsAmf0Any* ensure_property_number(std::string name); +}; + +/** +* 2.11 Object End Type +* object-end-type = UTF-8-empty object-end-marker +* 0x00 0x00 0x09 +*/ +class __SrsAmf0ObjectEOF : public SrsAmf0Any +{ +public: + int16_t utf8_empty; + + __SrsAmf0ObjectEOF(); + virtual ~__SrsAmf0ObjectEOF(); + + virtual int size(); + virtual int read(SrsStream* stream); + virtual int write(SrsStream* stream); +}; /** * read amf0 utf8 string from stream. @@ -130,20 +251,37 @@ bool SrsAmf0Any::is_ecma_array() string SrsAmf0Any::to_str() { - __SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String*>(this); - return o->value; + __SrsAmf0String* p = dynamic_cast<__SrsAmf0String*>(this); + srs_assert(p != NULL); + return p->value; } bool SrsAmf0Any::to_boolean() { - __SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean*>(this); - return o->value; + __SrsAmf0Boolean* p = dynamic_cast<__SrsAmf0Boolean*>(this); + srs_assert(p != NULL); + return p->value; } double SrsAmf0Any::to_number() { - __SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number*>(this); - return o->value; + __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this); + srs_assert(p != NULL); + return p->value; +} + +SrsAmf0Object* SrsAmf0Any::to_object() +{ + SrsAmf0Object* p = dynamic_cast(this); + srs_assert(p != NULL); + return p; +} + +SrsAmf0EcmaArray* SrsAmf0Any::to_array() +{ + SrsAmf0EcmaArray* p = dynamic_cast(this); + srs_assert(p != NULL); + return p; } bool SrsAmf0Any::is_object_eof() @@ -216,31 +354,31 @@ int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue) switch (marker) { case RTMP_AMF0_String: { - *ppvalue = new __SrsAmf0String(); + *ppvalue = SrsAmf0Any::str(); return ret; } case RTMP_AMF0_Boolean: { - *ppvalue = new __SrsAmf0Boolean(); + *ppvalue = SrsAmf0Any::boolean(); return ret; } case RTMP_AMF0_Number: { - *ppvalue = new __SrsAmf0Number(); + *ppvalue = SrsAmf0Any::number(); return ret; } case RTMP_AMF0_Null: { - *ppvalue = new __SrsAmf0Null(); + *ppvalue = SrsAmf0Any::null(); return ret; } case RTMP_AMF0_Undefined: { - *ppvalue = new __SrsAmf0Undefined(); + *ppvalue = SrsAmf0Any::undefined(); return ret; } case RTMP_AMF0_Object: { - *ppvalue = new SrsAmf0Object(); + *ppvalue = SrsAmf0Any::object(); return ret; } case RTMP_AMF0_EcmaArray: { - *ppvalue = new SrsAmf0EcmaArray(); + *ppvalue = SrsAmf0Any::array(); return ret; } case RTMP_AMF0_Invalid: @@ -445,11 +583,15 @@ int __SrsAmf0ObjectEOF::write(SrsStream* stream) SrsAmf0Object::SrsAmf0Object() { + properties = new __SrsUnSortedHashtable(); + eof = new __SrsAmf0ObjectEOF(); marker = RTMP_AMF0_Object; } SrsAmf0Object::~SrsAmf0Object() { + srs_freep(properties); + srs_freep(eof); } int SrsAmf0Object::read(SrsStream* stream) @@ -476,8 +618,8 @@ int SrsAmf0Object::read(SrsStream* stream) while (!stream->empty()) { // detect whether is eof. if (srs_amf0_is_object_eof(stream)) { - __SrsAmf0ObjectEOF eof; - if ((ret = eof.read(stream)) != ERROR_SUCCESS) { + __SrsAmf0ObjectEOF pbj_eof; + if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { srs_error("amf0 object read eof failed. ret=%d", ret); return ret; } @@ -522,7 +664,7 @@ int SrsAmf0Object::write(SrsStream* stream) srs_verbose("amf0 write object marker success"); // value - for (int i = 0; i < properties.size(); i++) { + for (int i = 0; i < properties->size(); i++) { std::string name = this->key_at(i); SrsAmf0Any* any = this->value_at(i); @@ -539,7 +681,7 @@ int SrsAmf0Object::write(SrsStream* stream) srs_verbose("write amf0 property success. name=%s", name.c_str()); } - if ((ret = eof.write(stream)) != ERROR_SUCCESS) { + if ((ret = eof->write(stream)) != ERROR_SUCCESS) { srs_error("write object eof failed. ret=%d", ret); return ret; } @@ -553,7 +695,7 @@ int SrsAmf0Object::size() { int size = 1; - for (int i = 0; i < properties.size(); i++){ + for (int i = 0; i < properties->size(); i++){ std::string name = key_at(i); SrsAmf0Any* value = value_at(i); @@ -568,41 +710,45 @@ int SrsAmf0Object::size() std::string SrsAmf0Object::key_at(int index) { - return properties.key_at(index); + return properties->key_at(index); } SrsAmf0Any* SrsAmf0Object::value_at(int index) { - return properties.value_at(index); + return properties->value_at(index); } void SrsAmf0Object::set(std::string key, SrsAmf0Any* value) { - properties.set(key, value); + properties->set(key, value); } SrsAmf0Any* SrsAmf0Object::get_property(std::string name) { - return properties.get_property(name); + return properties->get_property(name); } SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name) { - return properties.ensure_property_string(name); + return properties->ensure_property_string(name); } SrsAmf0Any* SrsAmf0Object::ensure_property_number(std::string name) { - return properties.ensure_property_number(name); + return properties->ensure_property_number(name); } SrsAmf0EcmaArray::SrsAmf0EcmaArray() { + properties = new __SrsUnSortedHashtable(); + eof = new __SrsAmf0ObjectEOF(); marker = RTMP_AMF0_EcmaArray; } SrsAmf0EcmaArray::~SrsAmf0EcmaArray() { + srs_freep(properties); + srs_freep(eof); } int SrsAmf0EcmaArray::read(SrsStream* stream) @@ -641,8 +787,8 @@ int SrsAmf0EcmaArray::read(SrsStream* stream) while (!stream->empty()) { // detect whether is eof. if (srs_amf0_is_object_eof(stream)) { - __SrsAmf0ObjectEOF eof; - if ((ret = eof.read(stream)) != ERROR_SUCCESS) { + __SrsAmf0ObjectEOF pbj_eof; + if ((ret = pbj_eof.read(stream)) != ERROR_SUCCESS) { srs_error("amf0 ecma_array read eof failed. ret=%d", ret); return ret; } @@ -695,7 +841,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream) srs_verbose("amf0 write ecma_array count success. count=%d", value->count); // value - for (int i = 0; i < properties.size(); i++) { + for (int i = 0; i < properties->size(); i++) { std::string name = this->key_at(i); SrsAmf0Any* any = this->value_at(i); @@ -712,7 +858,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream) srs_verbose("write amf0 property success. name=%s", name.c_str()); } - if ((ret = eof.write(stream)) != ERROR_SUCCESS) { + if ((ret = eof->write(stream)) != ERROR_SUCCESS) { srs_error("write ecma_array eof failed. ret=%d", ret); return ret; } @@ -726,7 +872,7 @@ int SrsAmf0EcmaArray::size() { int size = 1 + 4; - for (int i = 0; i < properties.size(); i++){ + for (int i = 0; i < properties->size(); i++){ std::string name = key_at(i); SrsAmf0Any* value = value_at(i); @@ -741,32 +887,32 @@ int SrsAmf0EcmaArray::size() void SrsAmf0EcmaArray::clear() { - properties.clear(); + properties->clear(); } std::string SrsAmf0EcmaArray::key_at(int index) { - return properties.key_at(index); + return properties->key_at(index); } SrsAmf0Any* SrsAmf0EcmaArray::value_at(int index) { - return properties.value_at(index); + return properties->value_at(index); } void SrsAmf0EcmaArray::set(std::string key, SrsAmf0Any* value) { - properties.set(key, value); + properties->set(key, value); } SrsAmf0Any* SrsAmf0EcmaArray::get_property(std::string name) { - return properties.get_property(name); + return properties->get_property(name); } SrsAmf0Any* SrsAmf0EcmaArray::ensure_property_string(std::string name) { - return properties.ensure_property_string(name); + return properties->ensure_property_string(name); } int SrsAmf0Size::utf8(string value) @@ -1353,7 +1499,7 @@ int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value) { int ret = ERROR_SUCCESS; - value = new SrsAmf0Object(); + value = SrsAmf0Any::object(); if ((ret = value->read(stream)) != ERROR_SUCCESS) { srs_freep(value); @@ -1371,7 +1517,7 @@ int srs_amf0_read_ecma_array(SrsStream* stream, SrsAmf0EcmaArray*& value) { int ret = ERROR_SUCCESS; - value = new SrsAmf0EcmaArray(); + value = SrsAmf0Any::array(); if ((ret = value->read(stream)) != ERROR_SUCCESS) { srs_freep(value); diff --git a/trunk/src/rtmp/srs_protocol_amf0.hpp b/trunk/src/rtmp/srs_protocol_amf0.hpp index 90c5d8154..38294b6a2 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.hpp +++ b/trunk/src/rtmp/srs_protocol_amf0.hpp @@ -36,6 +36,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsStream; class SrsAmf0Object; class SrsAmf0EcmaArray; +class __SrsUnSortedHashtable; +class __SrsAmf0ObjectEOF; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -46,21 +48,20 @@ class SrsAmf0EcmaArray; // if ((ret = srs_amf0_read_any(stream, &pany)) != ERROR_SUCCESS) { // return ret; // } +// srs_assert(pany); // if success, always valid object. // 2. SrsAmf0Any: convert to specifid type, for instance, string // SrsAmf0Any* pany = ... -// if (pany && pany->is_string()) { +// if (pany->is_string()) { // string v = pany->to_str(); // } // 3. SrsAmf0Any: parse specified type to any, for instance, string // SrsAmf0Any* pany = SrsAmf0Any::str("winlin"); // 4. SrsAmf0Size: get amf0 instance size // int size = SrsAmf0Size::str("winlin"); -// 5. SrsAmf0Object: the amf0 object, directly new is ok. +// 5. SrsAmf0Object: the amf0 object. // SrsAmf0Object* obj = SrsAmf0Any::object(); -// SrsAmf0Object* obj = new SrsAmf0Object(); -// 5. SrsAmf0EcmaArray: the amf0 ecma array, directly new is ok. +// 5. SrsAmf0EcmaArray: the amf0 ecma array. // SrsAmf0EcmaArray* arr = SrsAmf0Any::array(); -// SrsAmf0EcmaArray* arr = new SrsAmf0EcmaArray(); // for detail usage, see interfaces of each object. //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// @@ -106,6 +107,16 @@ public: * user must ensure the type is a number, or assert failed. */ virtual double to_number(); + /** + * get the object of any when is_object() indicates true. + * user must ensure the type is a object, or assert failed. + */ + virtual SrsAmf0Object* to_object(); + /** + * get the ecma array of any when is_ecma_array() indicates true. + * user must ensure the type is a ecma array, or assert failed. + */ + virtual SrsAmf0EcmaArray* to_array(); public: /** * get the size of amf0 any, including the marker size. @@ -129,50 +140,6 @@ public: static int discovery(SrsStream* stream, SrsAmf0Any** ppvalue); }; -/** -* 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. -*/ -class __SrsUnSortedHashtable -{ -private: - typedef std::pair SrsObjectPropertyType; - std::vector properties; -public: - __SrsUnSortedHashtable(); - virtual ~__SrsUnSortedHashtable(); - - virtual int size(); - virtual void clear(); - 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); - virtual SrsAmf0Any* ensure_property_number(std::string name); -}; - -/** -* 2.11 Object End Type -* object-end-type = UTF-8-empty object-end-marker -* 0x00 0x00 0x09 -*/ -class __SrsAmf0ObjectEOF : public SrsAmf0Any -{ -public: - int16_t utf8_empty; - - __SrsAmf0ObjectEOF(); - virtual ~__SrsAmf0ObjectEOF(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - /** * 2.5 Object Type * anonymous-object-type = object-marker *(object-property) @@ -181,11 +148,14 @@ public: class SrsAmf0Object : public SrsAmf0Any { private: - __SrsUnSortedHashtable properties; -public: - __SrsAmf0ObjectEOF eof; + __SrsUnSortedHashtable* properties; + __SrsAmf0ObjectEOF* eof; +private: + // use SrsAmf0Any::object() to create it. + friend class SrsAmf0Any; SrsAmf0Object(); +public: virtual ~SrsAmf0Object(); virtual int read(SrsStream* stream); @@ -210,12 +180,15 @@ public: class SrsAmf0EcmaArray : public SrsAmf0Any { private: - __SrsUnSortedHashtable properties; -public: + __SrsUnSortedHashtable* properties; + __SrsAmf0ObjectEOF* eof; int32_t count; - __SrsAmf0ObjectEOF eof; +private: + // use SrsAmf0Any::array() to create it. + friend class SrsAmf0Any; SrsAmf0EcmaArray(); +public: virtual ~SrsAmf0EcmaArray(); virtual int read(SrsStream* stream); @@ -249,99 +222,10 @@ public: static int any(SrsAmf0Any* o); }; -/** -* read amf0 string from stream. -* 2.4 String Type -* string-type = string-marker UTF-8 -* @return default value is empty string. -* @remark: use SrsAmf0Any::str() to create it. -*/ -class __SrsAmf0String : public SrsAmf0Any -{ -public: - std::string value; - - __SrsAmf0String(const char* _value = NULL); - virtual ~__SrsAmf0String(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - -/** -* read amf0 boolean from stream. -* 2.4 String Type -* boolean-type = boolean-marker U8 -* 0 is false, <> 0 is true -* @return default value is false. -*/ -class __SrsAmf0Boolean : public SrsAmf0Any -{ -public: - bool value; - - __SrsAmf0Boolean(bool _value = false); - virtual ~__SrsAmf0Boolean(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - -/** -* read amf0 number from stream. -* 2.2 Number Type -* number-type = number-marker DOUBLE -* @return default value is 0. -*/ -class __SrsAmf0Number : public SrsAmf0Any -{ -public: - double value; - - __SrsAmf0Number(double _value = 0.0); - virtual ~__SrsAmf0Number(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - -/** -* read amf0 null from stream. -* 2.7 null Type -* null-type = null-marker -*/ -class __SrsAmf0Null : public SrsAmf0Any -{ -public: - __SrsAmf0Null(); - virtual ~__SrsAmf0Null(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - -/** -* read amf0 undefined from stream. -* 2.8 undefined Type -* undefined-type = undefined-marker -*/ -class __SrsAmf0Undefined : public SrsAmf0Any -{ -public: - __SrsAmf0Undefined(); - virtual ~__SrsAmf0Undefined(); - - virtual int size(); - virtual int read(SrsStream* stream); - virtual int write(SrsStream* stream); -}; - /** * read anything from stream. +* @param ppvalue, the output amf0 any elem. +* NULL if error; otherwise, never NULL and user must free it. */ extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue); diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp index 5c194826e..c238bd0b2 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp @@ -279,7 +279,7 @@ int SrsRtmpClient::connect_app(string app, string tc_url) SrsConnectAppPacket* pkt = new SrsConnectAppPacket(); msg->set_packet(pkt, 0); - pkt->command_object = new SrsAmf0Object(); + pkt->command_object = SrsAmf0Any::object(); pkt->command_object->set("app", SrsAmf0Any::str(app.c_str())); pkt->command_object->set("swfUrl", SrsAmf0Any::str()); pkt->command_object->set("tcUrl", SrsAmf0Any::str(tc_url.c_str())); @@ -706,7 +706,7 @@ int SrsRtmpServer::response_connect_app(SrsRequest *req, const char* server_ip) pkt->info->set(StatusCode, SrsAmf0Any::str(StatusCodeConnectSuccess)); pkt->info->set(StatusDescription, SrsAmf0Any::str("Connection succeeded")); pkt->info->set("objectEncoding", SrsAmf0Any::number(req->objectEncoding)); - SrsAmf0EcmaArray* data = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* data = SrsAmf0Any::array(); pkt->info->set("data", data); data->set("version", SrsAmf0Any::str(RTMP_SIG_FMS_VER)); diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp index ddb3455c5..49398ead8 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp @@ -1828,8 +1828,8 @@ SrsConnectAppResPacket::SrsConnectAppResPacket() transaction_id = 1; // TODO: FIXME: memory leak for decode will set the props and info. // TODO: FIXME: bug#22, refine the amf0. - props = new SrsAmf0Object(); - info = new SrsAmf0Object(); + props = SrsAmf0Any::object(); + info = SrsAmf0Any::object(); } SrsConnectAppResPacket::~SrsConnectAppResPacket() @@ -2718,7 +2718,7 @@ SrsPlayResPacket::SrsPlayResPacket() command_name = RTMP_AMF0_COMMAND_RESULT; transaction_id = 0; command_object = SrsAmf0Any::null(); - desc = new SrsAmf0Object(); + desc = SrsAmf0Any::object(); } SrsPlayResPacket::~SrsPlayResPacket() @@ -2837,7 +2837,7 @@ SrsOnStatusCallPacket::SrsOnStatusCallPacket() command_name = RTMP_AMF0_COMMAND_ON_STATUS; transaction_id = 0; args = SrsAmf0Any::null(); - data = new SrsAmf0Object(); + data = SrsAmf0Any::object(); } SrsOnStatusCallPacket::~SrsOnStatusCallPacket() @@ -2900,7 +2900,7 @@ SrsBandwidthPacket::SrsBandwidthPacket() command_name = RTMP_AMF0_COMMAND_ON_STATUS; transaction_id = 0; args = SrsAmf0Any::null(); - data = new SrsAmf0Object(); + data = SrsAmf0Any::object(); } SrsBandwidthPacket::~SrsBandwidthPacket() @@ -3055,7 +3055,7 @@ SrsBandwidthPacket* SrsBandwidthPacket::set_command(string command) SrsOnStatusDataPacket::SrsOnStatusDataPacket() { command_name = RTMP_AMF0_COMMAND_ON_STATUS; - data = new SrsAmf0Object(); + data = SrsAmf0Any::object(); } SrsOnStatusDataPacket::~SrsOnStatusDataPacket() @@ -3156,7 +3156,7 @@ int SrsSampleAccessPacket::encode_packet(SrsStream* stream) SrsOnMetaDataPacket::SrsOnMetaDataPacket() { name = RTMP_AMF0_DATA_ON_METADATA; - metadata = new SrsAmf0Object(); + metadata = SrsAmf0Any::object(); } SrsOnMetaDataPacket::~SrsOnMetaDataPacket() @@ -3190,27 +3190,27 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream) return ret; } - if (any && any->is_object()) { + srs_assert(any); + if (any->is_object()) { srs_freep(metadata); - metadata = dynamic_cast(any); + metadata = any->to_object(); srs_info("decode metadata object success"); return ret; } - SrsAmf0EcmaArray* arr = dynamic_cast(any); - if (!arr) { - ret = ERROR_RTMP_AMF0_DECODE; - srs_error("decode metadata array failed. ret=%d", ret); - return ret; - } + SrsAutoFree(SrsAmf0Any, any, false); - // if ecma array, copy to object. - SrsAutoFree(SrsAmf0EcmaArray, arr, false); - for (int i = 0; i < arr->size(); i++) { - metadata->set(arr->key_at(i), arr->value_at(i)); + if (any->is_ecma_array()) { + SrsAmf0EcmaArray* arr = any->to_array(); + + // if ecma array, copy to object. + for (int i = 0; i < arr->size(); i++) { + metadata->set(arr->key_at(i), arr->value_at(i)); + } + + arr->clear(); + srs_info("decode metadata array success"); } - arr->clear(); - srs_info("decode metadata array success"); return ret; } diff --git a/trunk/src/utest/srs_utest_amf0.cpp b/trunk/src/utest/srs_utest_amf0.cpp index 584796f58..02354f75b 100644 --- a/trunk/src/utest/srs_utest_amf0.cpp +++ b/trunk/src/utest/srs_utest_amf0.cpp @@ -46,221 +46,239 @@ VOID TEST(AMF0Test, Size) // object: empty if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } // object: elem if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number(); - o.set("age", SrsAmf0Any::number(9)); + o->set("age", SrsAmf0Any::number(9)); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null(); - o.set("email", SrsAmf0Any::null()); + o->set("email", SrsAmf0Any::null()); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined(); - o.set("email", SrsAmf0Any::undefined()); + o->set("email", SrsAmf0Any::undefined()); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean(); - o.set("sex", SrsAmf0Any::boolean(true)); + o->set("sex", SrsAmf0Any::boolean(true)); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } // array: empty if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } // array: elem if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("age")+SrsAmf0Size::number(); - o.set("age", SrsAmf0Any::number(9)); + o->set("age", SrsAmf0Any::number(9)); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::null(); - o.set("email", SrsAmf0Any::null()); + o->set("email", SrsAmf0Any::null()); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("email")+SrsAmf0Size::undefined(); - o.set("email", SrsAmf0Any::undefined()); + o->set("email", SrsAmf0Any::undefined()); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("sex")+SrsAmf0Size::boolean(); - o.set("sex", SrsAmf0Any::boolean(true)); + o->set("sex", SrsAmf0Any::boolean(true)); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } // object: array if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* args = SrsAmf0Any::array(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); - o.set("args", args); + o->set("args", args); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* args = SrsAmf0Any::array(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); - o.set("args", args); + o->set("args", args); - SrsAmf0EcmaArray* params = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* params = SrsAmf0Any::array(); params->set("p1", SrsAmf0Any::number(10)); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params); - o.set("params", params); + o->set("params", params); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } // array: object if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0Object* args = new SrsAmf0Object(); + SrsAmf0Object* args = SrsAmf0Any::object(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); - o.set("args", args); + o->set("args", args); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0Object* args = new SrsAmf0Object(); + SrsAmf0Object* args = SrsAmf0Any::object(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); - o.set("args", args); + o->set("args", args); - SrsAmf0Object* params = new SrsAmf0Object(); + SrsAmf0Object* params = SrsAmf0Any::object(); params->set("p1", SrsAmf0Any::number(10)); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params); - o.set("params", params); + o->set("params", params); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } // object: object if (true) { int size = 1+3; - SrsAmf0Object o; + SrsAmf0Object* o = SrsAmf0Any::object(); + SrsAutoFree(SrsAmf0Object, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0Object* args = new SrsAmf0Object(); + SrsAmf0Object* args = SrsAmf0Any::object(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::object(args); - o.set("args", args); + o->set("args", args); - SrsAmf0Object* params = new SrsAmf0Object(); + SrsAmf0Object* params = SrsAmf0Any::object(); params->set("p1", SrsAmf0Any::number(10)); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::object(params); - o.set("params", params); + o->set("params", params); - EXPECT_EQ(size, SrsAmf0Size::object(&o)); + EXPECT_EQ(size, SrsAmf0Size::object(o)); } // array: array if (true) { int size = 1+4+3; - SrsAmf0EcmaArray o; + SrsAmf0EcmaArray* o = SrsAmf0Any::array(); + SrsAutoFree(SrsAmf0EcmaArray, o, false); size += SrsAmf0Size::utf8("name")+SrsAmf0Size::str("winlin"); - o.set("name", SrsAmf0Any::str("winlin")); + o->set("name", SrsAmf0Any::str("winlin")); - SrsAmf0EcmaArray* args = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* args = SrsAmf0Any::array(); args->set("p0", SrsAmf0Any::str("function")); size += SrsAmf0Size::utf8("args")+SrsAmf0Size::array(args); - o.set("args", args); + o->set("args", args); - SrsAmf0EcmaArray* params = new SrsAmf0EcmaArray(); + SrsAmf0EcmaArray* params = SrsAmf0Any::array(); params->set("p1", SrsAmf0Any::number(10)); size += SrsAmf0Size::utf8("params")+SrsAmf0Size::array(params); - o.set("params", params); + o->set("params", params); - EXPECT_EQ(size, SrsAmf0Size::array(&o)); + EXPECT_EQ(size, SrsAmf0Size::array(o)); } } @@ -656,3 +674,24 @@ VOID TEST(AMF0Test, AnyIO) srs_freep(po); } } + +VOID TEST(AMF0Test, AnyAssert) +{ + SrsStream s; + SrsAmf0Any* o = NULL; + + char buf[1024]; + memset(buf, 0, sizeof(buf)); + EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); + + // read any + if (true) { + s.reset(); + s.current()[0] = 0x12; + EXPECT_NE(ERROR_SUCCESS, srs_amf0_read_any(&s, &o)); + EXPECT_TRUE(NULL == o); + srs_freep(o); + } + + // +}