mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 12:21:55 +00:00
amf0 object decode framework
This commit is contained in:
parent
810bb6ba38
commit
2886672347
7 changed files with 279 additions and 18 deletions
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
double srs_amf0_read_number(SrsStream* stream)
|
||||
std::string srs_amf0_read_string(SrsStream* stream)
|
||||
{
|
||||
return 0;
|
||||
// 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)
|
||||
{
|
||||
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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue