winlin

amf0 object decode framework

... ... @@ -43,5 +43,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define srs_assert(expression) assert(expression)
#include <stddef.h>
#include <sys/types.h>
#endif
\ No newline at end of file
... ...
... ... @@ -49,23 +49,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// origin array whos data takes the same form as LengthValueBytes
#define RTMP_AMF0_OriginStrictArray 0x20
std::string srs_amf0_read_string(SrsStream* stream)
std::string srs_amf0_read_utf8(SrsStream* stream)
{
std::string str;
// marker
if (!stream->require(1)) {
srs_warn("amf0 read string marker failed");
return str;
}
char marker = stream->read_char();
if (marker != RTMP_AMF0_String) {
srs_warn("amf0 check string marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_String);
return str;
}
srs_verbose("amf0 read string marker success");
// len
if (!stream->require(2)) {
srs_warn("amf0 read string length failed");
... ... @@ -74,6 +61,12 @@ std::string srs_amf0_read_string(SrsStream* stream)
int16_t len = stream->read_2bytes();
srs_verbose("amf0 read string length success. len=%d", len);
// empty string
if (len <= 0) {
srs_verbose("amf0 read empty string.");
return str;
}
// data
if (!stream->require(len)) {
srs_warn("amf0 read string data failed");
... ... @@ -96,8 +89,125 @@ std::string srs_amf0_read_string(SrsStream* stream)
return str;
}
std::string srs_amf0_read_string(SrsStream* stream)
{
// marker
if (!stream->require(1)) {
srs_warn("amf0 read string marker failed");
return "";
}
char marker = stream->read_char();
if (marker != RTMP_AMF0_String) {
srs_warn("amf0 check string marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_String);
return "";
}
srs_verbose("amf0 read string marker success");
return srs_amf0_read_utf8(stream);
}
double srs_amf0_read_number(SrsStream* stream)
{
return 0;
double value = 0;
// marker
if (!stream->require(1)) {
srs_warn("amf0 read number marker failed");
return value;
}
char marker = stream->read_char();
if (marker != RTMP_AMF0_Number) {
srs_warn("amf0 check number marker failed. marker=%#x, required=%#x", marker, RTMP_AMF0_Number);
return value;
}
srs_verbose("amf0 read number marker success");
// value
if (!stream->require(8)) {
srs_warn("amf0 read number value failed");
return value;
}
int64_t temp = stream->read_8bytes();
memcpy(&value, &temp, 8);
srs_verbose("amf0 read number value success. value=%.2f", value);
return value;
}
SrsAmf0Object* srs_amf0_read_object(SrsStream* stream)
{
SrsAmf0Object* value = NULL;
return value;
}
SrsAmf0Any::SrsAmf0Any()
{
marker = RTMP_AMF0_Null;
}
SrsAmf0Any::~SrsAmf0Any()
{
}
bool SrsAmf0Any::is_string()
{
return marker == RTMP_AMF0_String;
}
bool SrsAmf0Any::is_number()
{
return marker == RTMP_AMF0_Number;
}
bool SrsAmf0Any::is_object()
{
return marker == RTMP_AMF0_Object;
}
SrsAmf0String::SrsAmf0String()
{
marker = RTMP_AMF0_String;
}
SrsAmf0String::~SrsAmf0String()
{
}
SrsAmf0Number::SrsAmf0Number()
{
marker = RTMP_AMF0_Number;
value = 0;
}
SrsAmf0Number::~SrsAmf0Number()
{
}
SrsAmf0ObjectEOF::SrsAmf0ObjectEOF()
{
utf8_empty = 0x00;
object_end_marker = RTMP_AMF0_ObjectEnd;
}
SrsAmf0ObjectEOF::~SrsAmf0ObjectEOF()
{
}
SrsAmf0Object::SrsAmf0Object()
{
marker = RTMP_AMF0_Object;
}
SrsAmf0Object::~SrsAmf0Object()
{
std::map<std::string, SrsAmf0Any*>::iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
SrsAmf0Any* any = it->second;
delete any;
}
properties.clear();
}
... ...
... ... @@ -31,13 +31,27 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_core.hpp>
#include <string>
#include <map>
class SrsStream;
class SrsAmf0Object;
/**
* 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.
* @return default value is empty string.
*/
extern std::string srs_amf0_read_utf8(SrsStream* stream);
/**
* read amf0 string from stream.
* 2.4 String Type
* string-type = string-marker UTF-8
* @return default value is empty string.
*/
extern std::string srs_amf0_read_string(SrsStream* stream);
... ... @@ -45,7 +59,106 @@ extern std::string srs_amf0_read_string(SrsStream* stream);
* read amf0 number from stream.
* 2.2 Number Type
* number-type = number-marker DOUBLE
* @return default value is 0.
*/
extern double srs_amf0_read_number(SrsStream* stream);
/**
* read amf0 object from stream.
* 2.5 Object Type
* anonymous-object-type = object-marker *(object-property)
* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
*/
extern SrsAmf0Object* srs_amf0_read_object(SrsStream* stream);
/**
* any amf0 value.
* 2.1 Types Overview
* value-type = number-type | boolean-type | string-type | object-type
* | null-marker | undefined-marker | reference-type | ecma-array-type
* | strict-array-type | date-type | long-string-type | xml-document-type
* | typed-object-type
*/
struct SrsAmf0Any
{
char marker;
SrsAmf0Any();
virtual ~SrsAmf0Any();
virtual bool is_string();
virtual bool is_number();
virtual bool is_object();
/**
* 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* convert()
{
T* p = dynamic_cast<T>(this);
srs_assert(p != NULL);
return p;
}
};
/**
* read amf0 string from stream.
* 2.4 String Type
* string-type = string-marker UTF-8
* @return default value is empty string.
*/
struct SrsAmf0String : public SrsAmf0Any
{
std::string value;
SrsAmf0String();
virtual ~SrsAmf0String();
};
/**
* read amf0 number from stream.
* 2.2 Number Type
* number-type = number-marker DOUBLE
* @return default value is 0.
*/
struct SrsAmf0Number : public SrsAmf0Any
{
double value;
SrsAmf0Number();
virtual ~SrsAmf0Number();
};
/**
* 2.11 Object End Type
* object-end-type = UTF-8-empty object-end-marker
* 0x00 0x00 0x09
*/
struct SrsAmf0ObjectEOF
{
int16_t utf8_empty;
char object_end_marker;
SrsAmf0ObjectEOF();
virtual ~SrsAmf0ObjectEOF();
};
/**
* 2.5 Object Type
* anonymous-object-type = object-marker *(object-property)
* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker)
*/
struct SrsAmf0Object : public SrsAmf0Any
{
std::map<std::string, SrsAmf0Any*> properties;
SrsAmf0ObjectEOF eof;
SrsAmf0Object();
virtual ~SrsAmf0Object();
};
#endif
\ No newline at end of file
... ...
... ... @@ -320,6 +320,9 @@ int SrsPacket::decode(SrsStream* /*stream*/)
SrsConnectAppPacket::SrsConnectAppPacket()
{
command_name = RTMP_AMF0_COMMAND_CONNECT;
transaction_id = 1;
command_object = NULL;
}
SrsConnectAppPacket::~SrsConnectAppPacket()
... ... @@ -335,9 +338,10 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
}
command_name = srs_amf0_read_string(stream);
if (command_name.empty()) {
if (command_name.empty() || command_name != RTMP_AMF0_COMMAND_CONNECT) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode connect command_name failed. ret=%d", ret);
srs_error("amf0 decode connect command_name failed. "
"command_name=%s, ret=%d", command_name.c_str(), ret);
return ret;
}
... ... @@ -349,6 +353,15 @@ int SrsConnectAppPacket::decode(SrsStream* stream)
return ret;
}
command_object = srs_amf0_read_object(stream);
if (command_object == NULL) {
ret = ERROR_RTMP_AMF0_DECODE;
srs_error("amf0 decode connect command_object failed. ret=%d", ret);
return ret;
}
srs_info("amf0 decode connect packet success");
return ret;
}
... ...
... ... @@ -44,6 +44,7 @@ class SrsPacket;
class SrsStream;
class SrsMessage;
class SrsChunkStream;
class SrsAmf0Object;
/**
* 4.1. Message Header
... ... @@ -164,6 +165,7 @@ private:
private:
std::string command_name;
double transaction_id;
SrsAmf0Object* command_object;
public:
SrsConnectAppPacket();
virtual ~SrsConnectAppPacket();
... ...
... ... @@ -92,6 +92,24 @@ int16_t SrsStream::read_2bytes()
return value;
}
int64_t SrsStream::read_8bytes()
{
srs_assert(require(8));
int64_t value;
pp = (char*)&value;
pp[7] = *p++;
pp[6] = *p++;
pp[5] = *p++;
pp[4] = *p++;
pp[3] = *p++;
pp[2] = *p++;
pp[1] = *p++;
pp[0] = *p++;
return value;
}
std::string SrsStream::read_string(int len)
{
srs_assert(require(len));
... ...
... ... @@ -75,6 +75,10 @@ public:
*/
virtual int16_t read_2bytes();
/**
* get 8bytes int from stream.
*/
virtual int64_t read_8bytes();
/**
* get string from stream, length specifies by param len.
*/
virtual std::string read_string(int len);
... ...