mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
amf0 utest: elem read/write refined
This commit is contained in:
parent
bfe771bbba
commit
4306db099d
6 changed files with 514 additions and 137 deletions
|
@ -80,10 +80,6 @@ void SrsStream::skip(int size)
|
|||
|
||||
int SrsStream::pos()
|
||||
{
|
||||
if (empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return p - bytes;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,9 +56,32 @@ using namespace std;
|
|||
// User defined
|
||||
#define RTMP_AMF0_Invalid 0x3F
|
||||
|
||||
int srs_amf0_read_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*&);
|
||||
int srs_amf0_write_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*);
|
||||
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value);
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<class T>
|
||||
T srs_amf0_convert(SrsAmf0Any* any)
|
||||
{
|
||||
T p = dynamic_cast<T>(any);
|
||||
srs_assert(p != NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* read amf0 utf8 string from stream.
|
||||
* 1.3.1 Strings and UTF-8
|
||||
* UTF-8 = U16 *(UTF8-char)
|
||||
* UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
|
||||
* UTF8-1 = %x00-7F
|
||||
* @remark only support UTF8-1 char.
|
||||
*/
|
||||
extern int srs_amf0_read_utf8(SrsStream* stream, std::string& value);
|
||||
extern int srs_amf0_write_utf8(SrsStream* stream, std::string value);
|
||||
|
||||
bool srs_amf0_is_object_eof(SrsStream* stream);
|
||||
int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value);
|
||||
|
||||
SrsAmf0Any::SrsAmf0Any()
|
||||
|
@ -107,19 +130,19 @@ bool SrsAmf0Any::is_ecma_array()
|
|||
|
||||
string SrsAmf0Any::to_str()
|
||||
{
|
||||
__SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String>(this);
|
||||
__SrsAmf0String* o = srs_amf0_convert<__SrsAmf0String*>(this);
|
||||
return o->value;
|
||||
}
|
||||
|
||||
bool SrsAmf0Any::to_boolean()
|
||||
{
|
||||
__SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean>(this);
|
||||
__SrsAmf0Boolean* o = srs_amf0_convert<__SrsAmf0Boolean*>(this);
|
||||
return o->value;
|
||||
}
|
||||
|
||||
double SrsAmf0Any::to_number()
|
||||
{
|
||||
__SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number>(this);
|
||||
__SrsAmf0Number* o = srs_amf0_convert<__SrsAmf0Number*>(this);
|
||||
return o->value;
|
||||
}
|
||||
|
||||
|
@ -153,6 +176,11 @@ SrsAmf0Any* SrsAmf0Any::undefined()
|
|||
return new __SrsAmf0Undefined();
|
||||
}
|
||||
|
||||
SrsAmf0Any* SrsAmf0Any::object_eof()
|
||||
{
|
||||
return new __SrsAmf0ObjectEOF();
|
||||
}
|
||||
|
||||
__SrsUnSortedHashtable::__SrsUnSortedHashtable()
|
||||
{
|
||||
}
|
||||
|
@ -194,6 +222,11 @@ SrsAmf0Any* __SrsUnSortedHashtable::value_at(int index)
|
|||
|
||||
void __SrsUnSortedHashtable::set(std::string key, SrsAmf0Any* value)
|
||||
{
|
||||
if (!value) {
|
||||
srs_warn("add a NULL propertity %s", key.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<SrsObjectPropertyType>::iterator it;
|
||||
|
||||
for (it = properties.begin(); it != properties.end(); ++it) {
|
||||
|
@ -272,6 +305,71 @@ int __SrsAmf0ObjectEOF::size()
|
|||
return SrsAmf0Size::object_eof();
|
||||
}
|
||||
|
||||
int __SrsAmf0ObjectEOF::read(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// value
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int16_t temp = stream->read_2bytes();
|
||||
if (temp != 0x00) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof value check failed. "
|
||||
"must be 0x00, actual is %#x, ret=%d", temp, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// marker
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof marker failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char marker = stream->read_1bytes();
|
||||
if (marker != RTMP_AMF0_ObjectEnd) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check object eof marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read object eof marker success");
|
||||
|
||||
srs_verbose("amf0 read object eof success");
|
||||
|
||||
return ret;
|
||||
}
|
||||
int __SrsAmf0ObjectEOF::write(SrsStream* stream)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// value
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
srs_error("amf0 write object eof value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
stream->write_2bytes(0x00);
|
||||
srs_verbose("amf0 write object eof value success");
|
||||
|
||||
// marker
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||
srs_error("amf0 write object eof marker failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
stream->write_1bytes(RTMP_AMF0_ObjectEnd);
|
||||
|
||||
srs_verbose("amf0 read object eof success");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SrsAmf0Object::SrsAmf0Object()
|
||||
{
|
||||
marker = RTMP_AMF0_Object;
|
||||
|
@ -303,6 +401,17 @@ int SrsAmf0Object::read(SrsStream* stream)
|
|||
|
||||
// value
|
||||
while (!stream->empty()) {
|
||||
// detect whether is eof.
|
||||
if (srs_amf0_is_object_eof(stream)) {
|
||||
__SrsAmf0ObjectEOF eof;
|
||||
if ((ret = eof.read(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 object read eof failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("amf0 read object EOF.");
|
||||
break;
|
||||
}
|
||||
|
||||
// property-name: utf8 string
|
||||
std::string property_name;
|
||||
if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) {
|
||||
|
@ -311,19 +420,11 @@ int SrsAmf0Object::read(SrsStream* stream)
|
|||
}
|
||||
// property-value: any
|
||||
SrsAmf0Any* property_value = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, property_value)) != ERROR_SUCCESS) {
|
||||
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 object read property_value failed. "
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// AMF0 Object EOF.
|
||||
if (property_name.empty() || !property_value || property_value->is_object_eof()) {
|
||||
if (property_value) {
|
||||
srs_freep(property_value);
|
||||
}
|
||||
srs_info("amf0 read object EOF.");
|
||||
break;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// add property
|
||||
|
@ -365,7 +466,7 @@ int SrsAmf0Object::write(SrsStream* stream)
|
|||
srs_verbose("write amf0 property success. name=%s", name.c_str());
|
||||
}
|
||||
|
||||
if ((ret = srs_amf0_write_object_eof(stream, &this->eof)) != ERROR_SUCCESS) {
|
||||
if ((ret = eof.write(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("write object eof failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -465,6 +566,17 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
|
|||
this->count = count;
|
||||
|
||||
while (!stream->empty()) {
|
||||
// detect whether is eof.
|
||||
if (srs_amf0_is_object_eof(stream)) {
|
||||
__SrsAmf0ObjectEOF eof;
|
||||
if ((ret = eof.read(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 ecma_array read eof failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("amf0 read ecma_array EOF.");
|
||||
break;
|
||||
}
|
||||
|
||||
// property-name: utf8 string
|
||||
std::string property_name;
|
||||
if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) {
|
||||
|
@ -473,21 +585,12 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
|
|||
}
|
||||
// property-value: any
|
||||
SrsAmf0Any* property_value = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, property_value)) != ERROR_SUCCESS) {
|
||||
if ((ret = srs_amf0_read_any(stream, &property_value)) != ERROR_SUCCESS) {
|
||||
srs_error("amf0 ecma_array read property_value failed. "
|
||||
"name=%s, ret=%d", property_name.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// AMF0 Object EOF.
|
||||
if (property_name.empty() || !property_value || property_value->is_object_eof()) {
|
||||
if (property_value) {
|
||||
srs_freep(property_value);
|
||||
}
|
||||
srs_info("amf0 read ecma_array EOF.");
|
||||
break;
|
||||
}
|
||||
|
||||
// add property
|
||||
this->set(property_name, property_value);
|
||||
}
|
||||
|
@ -536,7 +639,7 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
|
|||
srs_verbose("write amf0 property success. name=%s", name.c_str());
|
||||
}
|
||||
|
||||
if ((ret = srs_amf0_write_object_eof(stream, &this->eof)) != ERROR_SUCCESS) {
|
||||
if ((ret = eof.write(stream)) != ERROR_SUCCESS) {
|
||||
srs_error("write ecma_array eof failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -672,6 +775,16 @@ int __SrsAmf0String::size()
|
|||
return SrsAmf0Size::str(value);
|
||||
}
|
||||
|
||||
int __SrsAmf0String::read(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_read_string(stream, value);
|
||||
}
|
||||
|
||||
int __SrsAmf0String::write(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_write_string(stream, value);
|
||||
}
|
||||
|
||||
__SrsAmf0Boolean::__SrsAmf0Boolean(bool _value)
|
||||
{
|
||||
marker = RTMP_AMF0_Boolean;
|
||||
|
@ -687,6 +800,16 @@ int __SrsAmf0Boolean::size()
|
|||
return SrsAmf0Size::boolean();
|
||||
}
|
||||
|
||||
int __SrsAmf0Boolean::read(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_read_boolean(stream, value);
|
||||
}
|
||||
|
||||
int __SrsAmf0Boolean::write(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_write_boolean(stream, value);
|
||||
}
|
||||
|
||||
__SrsAmf0Number::__SrsAmf0Number(double _value)
|
||||
{
|
||||
marker = RTMP_AMF0_Number;
|
||||
|
@ -702,6 +825,16 @@ int __SrsAmf0Number::size()
|
|||
return SrsAmf0Size::number();
|
||||
}
|
||||
|
||||
int __SrsAmf0Number::read(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_read_number(stream, value);
|
||||
}
|
||||
|
||||
int __SrsAmf0Number::write(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_write_number(stream, value);
|
||||
}
|
||||
|
||||
__SrsAmf0Null::__SrsAmf0Null()
|
||||
{
|
||||
marker = RTMP_AMF0_Null;
|
||||
|
@ -716,6 +849,16 @@ int __SrsAmf0Null::size()
|
|||
return SrsAmf0Size::null();
|
||||
}
|
||||
|
||||
int __SrsAmf0Null::read(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_read_null(stream);
|
||||
}
|
||||
|
||||
int __SrsAmf0Null::write(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_write_null(stream);
|
||||
}
|
||||
|
||||
__SrsAmf0Undefined::__SrsAmf0Undefined()
|
||||
{
|
||||
marker = RTMP_AMF0_Undefined;
|
||||
|
@ -730,6 +873,16 @@ int __SrsAmf0Undefined::size()
|
|||
return SrsAmf0Size::undefined();
|
||||
}
|
||||
|
||||
int __SrsAmf0Undefined::read(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_read_undefined(stream);
|
||||
}
|
||||
|
||||
int __SrsAmf0Undefined::write(SrsStream* stream)
|
||||
{
|
||||
return srs_amf0_write_undefined(stream);
|
||||
}
|
||||
|
||||
int srs_amf0_read_utf8(SrsStream* stream, std::string& value)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
@ -1055,10 +1208,33 @@ int srs_amf0_write_undefined(SrsStream* stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
||||
bool srs_amf0_is_object_eof(SrsStream* stream)
|
||||
{
|
||||
// detect the object-eof specially
|
||||
if (stream->require(3)) {
|
||||
int32_t flag = stream->read_3bytes();
|
||||
stream->skip(-3);
|
||||
|
||||
return 0x09 == flag;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// detect the object-eof specially
|
||||
if (srs_amf0_is_object_eof(stream)) {
|
||||
*ppvalue = new __SrsAmf0ObjectEOF();
|
||||
if ((ret = (*ppvalue)->read(stream)) != ERROR_SUCCESS) {
|
||||
srs_freep(*ppvalue);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// marker
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
|
@ -1078,7 +1254,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
|||
if ((ret = srs_amf0_read_string(stream, data)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = SrsAmf0Any::str(data.c_str());
|
||||
*ppvalue = SrsAmf0Any::str(data.c_str());
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Boolean: {
|
||||
|
@ -1086,7 +1262,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
|||
if ((ret = srs_amf0_read_boolean(stream, data)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = SrsAmf0Any::boolean(data);
|
||||
*ppvalue = SrsAmf0Any::boolean(data);
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Number: {
|
||||
|
@ -1094,25 +1270,17 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
|||
if ((ret = srs_amf0_read_number(stream, data)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = SrsAmf0Any::number(data);
|
||||
*ppvalue = SrsAmf0Any::number(data);
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Null: {
|
||||
stream->skip(1);
|
||||
value = new __SrsAmf0Null();
|
||||
*ppvalue = new __SrsAmf0Null();
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Undefined: {
|
||||
stream->skip(1);
|
||||
value = new __SrsAmf0Undefined();
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_ObjectEnd: {
|
||||
__SrsAmf0ObjectEOF* p = NULL;
|
||||
if ((ret = srs_amf0_read_object_eof(stream, p)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = p;
|
||||
*ppvalue = new __SrsAmf0Undefined();
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Object: {
|
||||
|
@ -1120,7 +1288,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
|||
if ((ret = srs_amf0_read_object(stream, p)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = p;
|
||||
*ppvalue = p;
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_EcmaArray: {
|
||||
|
@ -1128,7 +1296,7 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value)
|
|||
if ((ret = srs_amf0_read_ecma_array(stream, p)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
value = p;
|
||||
*ppvalue = p;
|
||||
return ret;
|
||||
}
|
||||
case RTMP_AMF0_Invalid:
|
||||
|
@ -1149,15 +1317,15 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
|
|||
|
||||
switch (value->marker) {
|
||||
case RTMP_AMF0_String: {
|
||||
std::string data = srs_amf0_convert<__SrsAmf0String>(value)->value;
|
||||
std::string data = srs_amf0_convert<__SrsAmf0String*>(value)->value;
|
||||
return srs_amf0_write_string(stream, data);
|
||||
}
|
||||
case RTMP_AMF0_Boolean: {
|
||||
bool data = srs_amf0_convert<__SrsAmf0Boolean>(value)->value;
|
||||
bool data = srs_amf0_convert<__SrsAmf0Boolean*>(value)->value;
|
||||
return srs_amf0_write_boolean(stream, data);
|
||||
}
|
||||
case RTMP_AMF0_Number: {
|
||||
double data = srs_amf0_convert<__SrsAmf0Number>(value)->value;
|
||||
double data = srs_amf0_convert<__SrsAmf0Number*>(value)->value;
|
||||
return srs_amf0_write_number(stream, data);
|
||||
}
|
||||
case RTMP_AMF0_Null: {
|
||||
|
@ -1167,15 +1335,15 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
|
|||
return srs_amf0_write_undefined(stream);
|
||||
}
|
||||
case RTMP_AMF0_ObjectEnd: {
|
||||
__SrsAmf0ObjectEOF* p = srs_amf0_convert<__SrsAmf0ObjectEOF>(value);
|
||||
return srs_amf0_write_object_eof(stream, p);
|
||||
__SrsAmf0ObjectEOF* p = srs_amf0_convert<__SrsAmf0ObjectEOF*>(value);
|
||||
return p->write(stream);
|
||||
}
|
||||
case RTMP_AMF0_Object: {
|
||||
SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value);
|
||||
SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object*>(value);
|
||||
return srs_amf0_write_object(stream, p);
|
||||
}
|
||||
case RTMP_AMF0_EcmaArray: {
|
||||
SrsAmf0EcmaArray* p = srs_amf0_convert<SrsAmf0EcmaArray>(value);
|
||||
SrsAmf0EcmaArray* p = srs_amf0_convert<SrsAmf0EcmaArray*>(value);
|
||||
return srs_amf0_write_ecma_array(stream, p);
|
||||
}
|
||||
case RTMP_AMF0_Invalid:
|
||||
|
@ -1189,49 +1357,6 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srs_amf0_read_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF*& value)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// auto skip -2 to read the object eof.
|
||||
srs_assert(stream->pos() >= 2);
|
||||
stream->skip(-2);
|
||||
|
||||
// value
|
||||
if (!stream->require(2)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof value failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
int16_t temp = stream->read_2bytes();
|
||||
if (temp != 0x00) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof value check failed. "
|
||||
"must be 0x00, actual is %#x, ret=%d", temp, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// marker
|
||||
if (!stream->require(1)) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read object eof marker failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char marker = stream->read_1bytes();
|
||||
if (marker != RTMP_AMF0_ObjectEnd) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 check object eof marker failed. "
|
||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_ObjectEnd, ret);
|
||||
return ret;
|
||||
}
|
||||
srs_verbose("amf0 read object eof marker success");
|
||||
|
||||
value = new __SrsAmf0ObjectEOF();
|
||||
srs_verbose("amf0 read object eof success");
|
||||
|
||||
return ret;
|
||||
}
|
||||
int srs_amf0_write_object_eof(SrsStream* stream, __SrsAmf0ObjectEOF* value)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
|
|
@ -76,13 +76,22 @@ public:
|
|||
*/
|
||||
virtual double to_number();
|
||||
public:
|
||||
/**
|
||||
* get the size of amf0 any, including the marker size.
|
||||
*/
|
||||
virtual int size() = 0;
|
||||
/**
|
||||
* read elem from stream
|
||||
*/
|
||||
virtual int read(SrsStream* stream) = 0;
|
||||
virtual int write(SrsStream* stream) = 0;
|
||||
public:
|
||||
static SrsAmf0Any* str(const char* value = NULL);
|
||||
static SrsAmf0Any* boolean(bool value = false);
|
||||
static SrsAmf0Any* number(double value = 0.0);
|
||||
static SrsAmf0Any* null();
|
||||
static SrsAmf0Any* undefined();
|
||||
static SrsAmf0Any* object_eof();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -125,6 +134,8 @@ public:
|
|||
virtual ~__SrsAmf0ObjectEOF();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -219,6 +230,8 @@ public:
|
|||
virtual ~__SrsAmf0String();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -237,6 +250,8 @@ public:
|
|||
virtual ~__SrsAmf0Boolean();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -254,6 +269,8 @@ public:
|
|||
virtual ~__SrsAmf0Number();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -268,6 +285,8 @@ public:
|
|||
virtual ~__SrsAmf0Null();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -282,19 +301,10 @@ public:
|
|||
virtual ~__SrsAmf0Undefined();
|
||||
|
||||
virtual int size();
|
||||
virtual int read(SrsStream* stream);
|
||||
virtual int write(SrsStream* stream);
|
||||
};
|
||||
|
||||
/**
|
||||
* read amf0 utf8 string from stream.
|
||||
* 1.3.1 Strings and UTF-8
|
||||
* UTF-8 = U16 *(UTF8-char)
|
||||
* UTF8-char = UTF8-1 | UTF8-2 | UTF8-3 | UTF8-4
|
||||
* UTF8-1 = %x00-7F
|
||||
* @remark only support UTF8-1 char.
|
||||
*/
|
||||
extern int srs_amf0_read_utf8(SrsStream* stream, std::string& value);
|
||||
extern int srs_amf0_write_utf8(SrsStream* stream, std::string value);
|
||||
|
||||
/**
|
||||
* read amf0 string from stream.
|
||||
* 2.4 String Type
|
||||
|
@ -336,7 +346,10 @@ extern int srs_amf0_write_null(SrsStream* stream);
|
|||
extern int srs_amf0_read_undefined(SrsStream* stream);
|
||||
extern int srs_amf0_write_undefined(SrsStream* stream);
|
||||
|
||||
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value);
|
||||
/**
|
||||
* read anything from stream.
|
||||
*/
|
||||
extern int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue);
|
||||
|
||||
/**
|
||||
* read amf0 object from stream.
|
||||
|
@ -357,18 +370,4 @@ extern int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value);
|
|||
extern int srs_amf0_read_ecma_array(SrsStream* stream, SrsAmf0EcmaArray*& value);
|
||||
extern int srs_amf0_write_ecma_array(SrsStream* stream, SrsAmf0EcmaArray* value);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
template<class T>
|
||||
T* srs_amf0_convert(SrsAmf0Any* any)
|
||||
{
|
||||
T* p = dynamic_cast<T*>(any);
|
||||
srs_assert(p != NULL);
|
||||
return p;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2617,7 +2617,7 @@ int SrsPlayPacket::decode(SrsStream* stream)
|
|||
}
|
||||
|
||||
SrsAmf0Any* reset_value = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, reset_value)) != ERROR_SUCCESS) {
|
||||
if ((ret = srs_amf0_read_any(stream, &reset_value)) != ERROR_SUCCESS) {
|
||||
ret = ERROR_RTMP_AMF0_DECODE;
|
||||
srs_error("amf0 read play reset marker failed. ret=%d", ret);
|
||||
return ret;
|
||||
|
@ -3183,14 +3183,14 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream)
|
|||
|
||||
// the metadata maybe object or ecma array
|
||||
SrsAmf0Any* any = NULL;
|
||||
if ((ret = srs_amf0_read_any(stream, any)) != ERROR_SUCCESS) {
|
||||
if ((ret = srs_amf0_read_any(stream, &any)) != ERROR_SUCCESS) {
|
||||
srs_error("decode metadata metadata failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (any->is_object()) {
|
||||
srs_freep(metadata);
|
||||
metadata = srs_amf0_convert<SrsAmf0Object>(any);
|
||||
metadata = dynamic_cast<SrsAmf0Object*>(any);
|
||||
srs_info("decode metadata object success");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_utest_amf0.hpp>
|
||||
|
||||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_kernel_stream.hpp>
|
||||
|
||||
VOID TEST(AMF0Test, Size)
|
||||
{
|
||||
|
@ -270,14 +272,14 @@ VOID TEST(AMF0Test, AnyElem)
|
|||
if (true) {
|
||||
o = SrsAmf0Any::str();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_string());
|
||||
EXPECT_STREQ("", o->to_str().c_str());
|
||||
}
|
||||
if (true) {
|
||||
o = SrsAmf0Any::str("winlin");
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_string());
|
||||
EXPECT_STREQ("winlin", o->to_str().c_str());
|
||||
}
|
||||
|
@ -286,21 +288,21 @@ VOID TEST(AMF0Test, AnyElem)
|
|||
if (true) {
|
||||
o = SrsAmf0Any::boolean();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_boolean());
|
||||
EXPECT_FALSE(o->to_boolean());
|
||||
}
|
||||
if (true) {
|
||||
o = SrsAmf0Any::boolean(false);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_boolean());
|
||||
EXPECT_FALSE(o->to_boolean());
|
||||
}
|
||||
if (true) {
|
||||
o = SrsAmf0Any::boolean(true);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_boolean());
|
||||
EXPECT_TRUE(o->to_boolean());
|
||||
}
|
||||
|
@ -309,21 +311,21 @@ VOID TEST(AMF0Test, AnyElem)
|
|||
if (true) {
|
||||
o = SrsAmf0Any::number();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_number());
|
||||
EXPECT_DOUBLE_EQ(0, o->to_number());
|
||||
}
|
||||
if (true) {
|
||||
o = SrsAmf0Any::number(100);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_number());
|
||||
EXPECT_DOUBLE_EQ(100, o->to_number());
|
||||
}
|
||||
if (true) {
|
||||
o = SrsAmf0Any::number(-100);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_number());
|
||||
EXPECT_DOUBLE_EQ(-100, o->to_number());
|
||||
}
|
||||
|
@ -332,7 +334,7 @@ VOID TEST(AMF0Test, AnyElem)
|
|||
if (true) {
|
||||
o = SrsAmf0Any::null();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_null());
|
||||
}
|
||||
|
||||
|
@ -340,7 +342,261 @@ VOID TEST(AMF0Test, AnyElem)
|
|||
if (true) {
|
||||
o = SrsAmf0Any::undefined();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
EXPECT_TRUE(NULL != o);
|
||||
ASSERT_TRUE(NULL != o);
|
||||
EXPECT_TRUE(o->is_undefined());
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(AMF0Test, AnyIO)
|
||||
{
|
||||
SrsStream s;
|
||||
SrsAmf0Any* o = NULL;
|
||||
|
||||
char buf[1024];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf)));
|
||||
|
||||
// object eof
|
||||
if (true) {
|
||||
s.reset();
|
||||
s.current()[2] = 0x09;
|
||||
|
||||
o = SrsAmf0Any::object_eof();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_EQ(3, s.pos());
|
||||
|
||||
s.reset();
|
||||
s.current()[0] = 0x01;
|
||||
EXPECT_NE(ERROR_SUCCESS, o->read(&s));
|
||||
}
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::object_eof();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_EQ(3, s.pos());
|
||||
|
||||
s.skip(-3);
|
||||
EXPECT_EQ(0x09, s.read_3bytes());
|
||||
}
|
||||
|
||||
// string
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::str("winlin");
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(2, s.read_1bytes());
|
||||
EXPECT_EQ(6, s.read_2bytes());
|
||||
EXPECT_EQ('w', s.current()[0]);
|
||||
EXPECT_EQ('n', s.current()[5]);
|
||||
|
||||
s.reset();
|
||||
s.current()[3] = 'x';
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_STREQ("xinlin", o->to_str().c_str());
|
||||
}
|
||||
|
||||
// number
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::number(10);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(0, s.read_1bytes());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_DOUBLE_EQ(10, o->to_number());
|
||||
}
|
||||
|
||||
// boolean
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::boolean(true);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(1, s.read_1bytes());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_TRUE(o->to_boolean());
|
||||
}
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::boolean(false);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(1, s.read_1bytes());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_FALSE(o->to_boolean());
|
||||
}
|
||||
|
||||
// null
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::null();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(5, s.read_1bytes());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_TRUE(o->is_null());
|
||||
}
|
||||
|
||||
// undefined
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::undefined();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(6, s.read_1bytes());
|
||||
|
||||
s.reset();
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->read(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
EXPECT_TRUE(o->is_undefined());
|
||||
}
|
||||
|
||||
// any: string
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::str("winlin");
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
|
||||
SrsAmf0Any* po = NULL;
|
||||
EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po));
|
||||
ASSERT_TRUE(NULL != po);
|
||||
SrsAutoFree(SrsAmf0Any, po, false);
|
||||
ASSERT_TRUE(po->is_string());
|
||||
EXPECT_STREQ("winlin", po->to_str().c_str());
|
||||
}
|
||||
|
||||
// any: number
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::number(10);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
|
||||
SrsAmf0Any* po = NULL;
|
||||
EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po));
|
||||
ASSERT_TRUE(NULL != po);
|
||||
SrsAutoFree(SrsAmf0Any, po, false);
|
||||
ASSERT_TRUE(po->is_number());
|
||||
EXPECT_DOUBLE_EQ(10, po->to_number());
|
||||
}
|
||||
|
||||
// any: boolean
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::boolean(true);
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
|
||||
SrsAmf0Any* po = NULL;
|
||||
EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po));
|
||||
ASSERT_TRUE(NULL != po);
|
||||
SrsAutoFree(SrsAmf0Any, po, false);
|
||||
ASSERT_TRUE(po->is_boolean());
|
||||
EXPECT_TRUE(po->to_boolean());
|
||||
}
|
||||
|
||||
// any: null
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::null();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
|
||||
SrsAmf0Any* po = NULL;
|
||||
EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po));
|
||||
ASSERT_TRUE(NULL != po);
|
||||
SrsAutoFree(SrsAmf0Any, po, false);
|
||||
ASSERT_TRUE(po->is_null());
|
||||
}
|
||||
|
||||
// any: undefined
|
||||
if (true) {
|
||||
s.reset();
|
||||
|
||||
o = SrsAmf0Any::undefined();
|
||||
SrsAutoFree(SrsAmf0Any, o, false);
|
||||
|
||||
EXPECT_EQ(ERROR_SUCCESS, o->write(&s));
|
||||
EXPECT_EQ(o->size(), s.pos());
|
||||
|
||||
s.reset();
|
||||
|
||||
SrsAmf0Any* po = NULL;
|
||||
EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po));
|
||||
ASSERT_TRUE(NULL != po);
|
||||
SrsAutoFree(SrsAmf0Any, po, false);
|
||||
ASSERT_TRUE(po->is_undefined());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_utest_amf0.hpp>
|
||||
*/
|
||||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_protocol_amf0.hpp>
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue