AMF 格式是 Adobe 推出的一个二进制数据格式
AMF0 :http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/amf/pdf/amf0-file-format-specification.pdf
AMF3 :http://download.macromedia.com/pub/labs/amf/amf3_spec_121207.pdf
rtmp流里分析帧类型18为AMF0类型,15为AMF3类型。
rtmp流里常用的AMF0格式有:
AMF_NUMBER 0x00
AMF_BOOLEAN 0x01
AMF_STRING 0x02
AMF_NULL 0x05
AMF_LONG_STRING 0x0C
AMF_OBJECT 0x03
AMF_OBJECT_END 0x09
解析流程:
一个字节为类型 :后面字节为数据内容
例子:
01 00
01 表示后面的值为bool , 00 为值 false
各个常用类型的解析
AMF_NUMBER :一个类型字节 + 八个数据字节(大编码)
00 41 1e 9a e4 00 00 00 00
00 表示 AMF_NUMBER
41 1e 9a e4 00 00 00 00 换算为 501433
AMF_BOOLEAN : 一个类型字节 + 一个数字字节
01 01
01 表示 AMF_BOOLEAN
01 为 true
AMF_STRING :一个类型字节 + 二个字节保存长度N (大编码) + N个数据字节
02 00 04 6d 70 34 32
02 表示 AMF_STRING
00 04 表示字符串长度为4
6d 70 34 32 换算成 “mp42”
AMF_NULL : 一个类型字节
05
05 表示 AMF_NULL 后面没有数据内容
AMF_LONG_STRING :一个类型字节 + 四个字节保存长度N(大编码) + N个数据字节
类似 AMF_STRING ,只是长度由4个字节组装
AMF_OBJECT : 一个类型字节 + N个组合字节[AMF_STRING + 一个类型字节 + 类型字节内容] + 长度为0的AMF_STRING + AMF_OBJECT_END类型字节
Name: level 为一个AMF_STRING类型,不带一个字节类型标示
String `status` 为一个AMF_STRING类型,带一个字节类型标示,也可以是带一个字节类型标示的AMF_BOOLEAN或者AMF_NUMBER
代码:
yuAMF.h
typedef enum
{
AMF_NUMBER = 0, AMF_BOOLEAN, AMF_STRING, AMF_OBJECT,
AMF_MOVIECLIP, /* reserved, not used */
AMF_NULL,
AMF_UNDEFINED,
AMF_REFERENCE,
AMF_ECMA_ARRAY,
AMF_OBJECT_END,
AMF_STRICT_ARRAY, AMF_DATE, AMF_LONG_STRING, AMF_UNSUPPORTED,
AMF_RECORDSET, /* reserved, not used */
AMF_XML_DOC, AMF_TYPED_OBJECT,
AMF_AVMPLUS, /* switch to AMF3 */
AMF_INVALID = 0xff
} AMFDataType;
typedef struct AVal
{
char *av_val;
int av_len;
} AVal;
class uyAMF {
public:
uyAMF(char* data , int len);
~uyAMF();
bool checkout();
AMFDataType AMF_GetType();
unsigned short AMF_DecodeInt16();
unsigned int AMF_DecodeInt24();
unsigned int AMF_DecodeInt32();
void AMF_DecodeString( AVal& bv);
void AMF_DecodeLongString( AVal& bv);
int AMF_DecodeBoolean();
double AMF_DecodeNumber();
void AMF_DecodeObject(std::map<std::string,std::string>& paramMap);
public:
char* amf_data;
int amf_len;
int decode_amf_len;
};
uyAMF.cpp
uyAMF::uyAMF(char *data, int len)
:amf_data(data)
,amf_len(len)
,decode_amf_len(0)
{
}
uyAMF::~uyAMF()
{
}
AMFDataType uyAMF::AMF_GetType()
{
decode_amf_len ++ ;
return (AMFDataType)*amf_data++;
}
unsigned short uyAMF::AMF_DecodeInt16()
{
if (decode_amf_len + 2 > amf_len)
{
return 0;
}
unsigned char *c = (unsigned char *) amf_data;
unsigned short val;
val = (c[0] << 8) | c[1];
amf_data += 2;
decode_amf_len += 2;
return val;
}
unsigned int uyAMF::AMF_DecodeInt24()
{
if (decode_amf_len + 3 > amf_len)
{
return 0;
}
unsigned char *c = (unsigned char *) amf_data;
unsigned int val;
val = (c[0] << 16) | (c[1] << 8) | c[2];
amf_data += 3;
decode_amf_len += 3;
return val;
}
unsigned int uyAMF::AMF_DecodeInt32()
{
if (decode_amf_len + 4 > amf_len)
{
return 0;
}
unsigned char *c = (unsigned char *)amf_data;
unsigned int val;
val = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
amf_data += 4;
decode_amf_len += 4;
return val;
}
void uyAMF::AMF_DecodeString(AVal& bv)
{
if (decode_amf_len + 1 > amf_len)
{
bv.av_len = 0;
bv.av_val = NULL;
return;
}
bv.av_len = AMF_DecodeInt16();
if (decode_amf_len + bv.av_len > amf_len)
{
bv.av_len = 0;
bv.av_val = NULL;
return;
}
bv.av_val = (bv.av_len > 0) ? (char *)amf_data : NULL;
amf_data += bv.av_len ;
decode_amf_len += bv.av_len;
}
void uyAMF::AMF_DecodeLongString(AVal &bv)
{
if (decode_amf_len + 1 > amf_len)
{
bv.av_len = 0;
bv.av_val = NULL;
return;
}
bv.av_len = AMF_DecodeInt32();
if (decode_amf_len + bv.av_len > amf_len)
{
bv.av_len = 0;
bv.av_val = NULL;
return;
}
bv.av_val = (bv.av_len > 0) ? (char *)amf_data : NULL;
amf_data += bv.av_len ;
decode_amf_len += bv.av_len;
}
int uyAMF::AMF_DecodeBoolean()
{
bool succ = *amf_data != 0;
amf_data += 1;
decode_amf_len += 1;
return succ;
}
double uyAMF::AMF_DecodeNumber()
{
if (decode_amf_len + 8 > amf_len)
{
return 8;
}
double dVal;
#if __FLOAT_WORD_ORDER == __BYTE_ORDER
#if __BYTE_ORDER == __BIG_ENDIAN
memcpy(&dVal, amf_data, 8);
#elif __BYTE_ORDER == __LITTLE_ENDIAN
unsigned char *ci, *co;
ci = (unsigned char *)amf_data;
co = (unsigned char *)&dVal;
co[0] = ci[7];
co[1] = ci[6];
co[2] = ci[5];
co[3] = ci[4];
co[4] = ci[3];
co[5] = ci[2];
co[6] = ci[1];
co[7] = ci[0];
#endif
#else
#if __BYTE_ORDER == __LITTLE_ENDIAN /* __FLOAT_WORD_ORER == __BIG_ENDIAN */
unsigned char *ci, *co;
ci = (unsigned char *)amf_data;
co = (unsigned char *)&dVal;
co[0] = ci[3];
co[1] = ci[2];
co[2] = ci[1];
co[3] = ci[0];
co[4] = ci[7];
co[5] = ci[6];
co[6] = ci[5];
co[7] = ci[4];
#else /* __BYTE_ORDER == __BIG_ENDIAN && __FLOAT_WORD_ORER == __LITTLE_ENDIAN */
unsigned char *ci, *co;
ci = (unsigned char *)amf_data;
co = (unsigned char *)&dVal;
co[0] = ci[4];
co[1] = ci[5];
co[2] = ci[6];
co[3] = ci[7];
co[4] = ci[0];
co[5] = ci[1];
co[6] = ci[2];
co[7] = ci[3];
#endif
#endif
decode_amf_len += 8;
amf_data += 8;
return dVal;
}
bool uyAMF::checkout()
{
return (decode_amf_len + 1 <= amf_len);
}
void uyAMF::AMF_DecodeObject(std::map<std::string, std::string>& paramMap)
{
AVal tmp;
std::string val;
std::string key;
bool succ = true;
while (succ)
{
key.clear();
val.clear();
AMF_DecodeString(tmp);
printf_info("Name : %s",tmp.av_val);
AMFDataType type = AMF_GetType();
key.append(tmp.av_val,tmp.av_len);
switch (type)
{
case AMF_STRING:
AMF_DecodeString(tmp);
printf_info("string : %s",tmp.av_val);
val.append(tmp.av_val,tmp.av_len);
break;
case AMF_NUMBER:
{
double db = AMF_DecodeNumber();
printf_info("double : %f",db);
char data[1024] = {0};
sprintf(data,"%f",db);
val = data;
break;
}
case AMF_BOOLEAN:
{
bool succ = AMF_DecodeBoolean();
printf_info("bool : %d",succ);
val = succ ? "true" : "false";
break;
}
case AMF_OBJECT_END:
default:
succ = false;
break;
}
paramMap[key] = val;
}
}
本文介绍了Adobe的AMF(Action Message Format)二进制数据格式,包括AMF0和AMF3的基本规范链接,并详细讲解了在rtmp流中AMF0类型的常见格式,如AMF_NUMBER、AMF_BOOLEAN、AMF_STRING等,以及解析流程和实例。通过理解这些内容,读者可以更好地解析AMF数据。
1423

被折叠的 条评论
为什么被折叠?



