mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
fix #185, AMF0 support 0x0B the date type codec. 2.0.5.
This commit is contained in:
parent
05cce97140
commit
6a3418cd45
6 changed files with 220 additions and 4 deletions
|
@ -220,6 +220,7 @@ Supported operating systems and hardware:
|
||||||
* 2013-10-17, Created.<br/>
|
* 2013-10-17, Created.<br/>
|
||||||
|
|
||||||
## History
|
## History
|
||||||
|
* v2.0, 2014-10-25, fix [#185](https://github.com/winlinvip/simple-rtmp-server/issues/185), AMF0 support 0x0B the date type codec. 2.0.5.
|
||||||
* v2.0, 2014-10-24, fix [#186](https://github.com/winlinvip/simple-rtmp-server/issues/186), hotfix for bug #186, drop connect args when not object. 2.0.4.
|
* v2.0, 2014-10-24, fix [#186](https://github.com/winlinvip/simple-rtmp-server/issues/186), hotfix for bug #186, drop connect args when not object. 2.0.4.
|
||||||
* v2.0, 2014-10-24, rename wiki/xxx to wiki/v1_CN_xxx. 2.0.3.
|
* v2.0, 2014-10-24, rename wiki/xxx to wiki/v1_CN_xxx. 2.0.3.
|
||||||
* v2.0, 2014-10-19, fix [#184](https://github.com/winlinvip/simple-rtmp-server/issues/184), support AnnexB in RTMP body for HLS. 2.0.2
|
* v2.0, 2014-10-19, fix [#184](https://github.com/winlinvip/simple-rtmp-server/issues/184), support AnnexB in RTMP body for HLS. 2.0.2
|
||||||
|
|
Binary file not shown.
|
@ -377,7 +377,7 @@ package
|
||||||
this.media_conn.connect(null);
|
this.media_conn.connect(null);
|
||||||
} else {
|
} else {
|
||||||
var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));
|
var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/"));
|
||||||
this.media_conn.connect(tcUrl);
|
this.media_conn.connect(tcUrl, new Date());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "2"
|
#define VERSION_MAJOR "2"
|
||||||
#define VERSION_MINOR "0"
|
#define VERSION_MINOR "0"
|
||||||
#define VERSION_REVISION "6"
|
#define VERSION_REVISION "7"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "SRS"
|
#define RTMP_SIG_SRS_KEY "SRS"
|
||||||
|
|
|
@ -109,6 +109,11 @@ bool SrsAmf0Any::is_strict_array()
|
||||||
return marker == RTMP_AMF0_StrictArray;
|
return marker == RTMP_AMF0_StrictArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsAmf0Any::is_date()
|
||||||
|
{
|
||||||
|
return marker == RTMP_AMF0_Date;
|
||||||
|
}
|
||||||
|
|
||||||
bool SrsAmf0Any::is_complex_object()
|
bool SrsAmf0Any::is_complex_object()
|
||||||
{
|
{
|
||||||
return is_object() || is_object_eof() || is_ecma_array() || is_strict_array();
|
return is_object() || is_object_eof() || is_ecma_array() || is_strict_array();
|
||||||
|
@ -142,6 +147,20 @@ double SrsAmf0Any::to_number()
|
||||||
return p->value;
|
return p->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t SrsAmf0Any::to_date()
|
||||||
|
{
|
||||||
|
SrsAmf0Date* p = dynamic_cast<SrsAmf0Date*>(this);
|
||||||
|
srs_assert(p != NULL);
|
||||||
|
return p->date();
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t SrsAmf0Any::to_date_time_zone()
|
||||||
|
{
|
||||||
|
SrsAmf0Date* p = dynamic_cast<SrsAmf0Date*>(this);
|
||||||
|
srs_assert(p != NULL);
|
||||||
|
return p->time_zone();
|
||||||
|
}
|
||||||
|
|
||||||
SrsAmf0Object* SrsAmf0Any::to_object()
|
SrsAmf0Object* SrsAmf0Any::to_object()
|
||||||
{
|
{
|
||||||
SrsAmf0Object* p = dynamic_cast<SrsAmf0Object*>(this);
|
SrsAmf0Object* p = dynamic_cast<SrsAmf0Object*>(this);
|
||||||
|
@ -189,6 +208,9 @@ void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level)
|
||||||
ss << "Number " << std::fixed << any->to_number() << endl;
|
ss << "Number " << std::fixed << any->to_number() << endl;
|
||||||
} else if (any->is_string()) {
|
} else if (any->is_string()) {
|
||||||
ss << "String " << any->to_str() << endl;
|
ss << "String " << any->to_str() << endl;
|
||||||
|
} else if (any->is_date()) {
|
||||||
|
ss << "Date " << std::hex << any->to_date()
|
||||||
|
<< "/" << std::hex << any->to_date_time_zone() << endl;
|
||||||
} else if (any->is_null()) {
|
} else if (any->is_null()) {
|
||||||
ss << "Null" << endl;
|
ss << "Null" << endl;
|
||||||
} else if (any->is_ecma_array()) {
|
} else if (any->is_ecma_array()) {
|
||||||
|
@ -304,6 +326,11 @@ SrsAmf0StrictArray* SrsAmf0Any::strict_array()
|
||||||
return new SrsAmf0StrictArray();
|
return new SrsAmf0StrictArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsAmf0Any* SrsAmf0Any::date(int64_t value)
|
||||||
|
{
|
||||||
|
return new SrsAmf0Date(value);
|
||||||
|
}
|
||||||
|
|
||||||
int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
|
int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
@ -360,6 +387,10 @@ int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue)
|
||||||
*ppvalue = SrsAmf0Any::strict_array();
|
*ppvalue = SrsAmf0Any::strict_array();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
case RTMP_AMF0_Date: {
|
||||||
|
*ppvalue = SrsAmf0Any::date();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
case RTMP_AMF0_Invalid:
|
case RTMP_AMF0_Invalid:
|
||||||
default: {
|
default: {
|
||||||
ret = ERROR_RTMP_AMF0_INVALID;
|
ret = ERROR_RTMP_AMF0_INVALID;
|
||||||
|
@ -805,7 +836,7 @@ int SrsAmf0EcmaArray::read(SrsStream* stream)
|
||||||
if (marker != RTMP_AMF0_EcmaArray) {
|
if (marker != RTMP_AMF0_EcmaArray) {
|
||||||
ret = ERROR_RTMP_AMF0_DECODE;
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
srs_error("amf0 check ecma_array marker failed. "
|
srs_error("amf0 check ecma_array marker failed. "
|
||||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
|
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_EcmaArray, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("amf0 read ecma_array marker success");
|
srs_verbose("amf0 read ecma_array marker success");
|
||||||
|
@ -1003,7 +1034,7 @@ int SrsAmf0StrictArray::read(SrsStream* stream)
|
||||||
if (marker != RTMP_AMF0_StrictArray) {
|
if (marker != RTMP_AMF0_StrictArray) {
|
||||||
ret = ERROR_RTMP_AMF0_DECODE;
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
srs_error("amf0 check strict_array marker failed. "
|
srs_error("amf0 check strict_array marker failed. "
|
||||||
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret);
|
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_StrictArray, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_verbose("amf0 read strict_array marker success");
|
srs_verbose("amf0 read strict_array marker success");
|
||||||
|
@ -1127,6 +1158,11 @@ int SrsAmf0Size::number()
|
||||||
return 1 + 8;
|
return 1 + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsAmf0Size::date()
|
||||||
|
{
|
||||||
|
return 1 + 8 + 2;
|
||||||
|
}
|
||||||
|
|
||||||
int SrsAmf0Size::null()
|
int SrsAmf0Size::null()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1278,6 +1314,130 @@ SrsAmf0Any* SrsAmf0Number::copy()
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsAmf0Date::SrsAmf0Date(int64_t value)
|
||||||
|
{
|
||||||
|
marker = RTMP_AMF0_Date;
|
||||||
|
_date_value = value;
|
||||||
|
_time_zone = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAmf0Date::~SrsAmf0Date()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsAmf0Date::total_size()
|
||||||
|
{
|
||||||
|
return SrsAmf0Size::date();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsAmf0Date::read(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// marker
|
||||||
|
if (!stream->require(1)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 read date marker failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char marker = stream->read_1bytes();
|
||||||
|
if (marker != RTMP_AMF0_Date) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 check date marker failed. "
|
||||||
|
"marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Date, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_verbose("amf0 read date marker success");
|
||||||
|
|
||||||
|
// date value
|
||||||
|
// An ActionScript Date is serialized as the number of milliseconds
|
||||||
|
// elapsed since the epoch of midnight on 1st Jan 1970 in the UTC
|
||||||
|
// time zone.
|
||||||
|
if (!stream->require(8)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 read date failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_date_value = stream->read_8bytes();
|
||||||
|
srs_verbose("amf0 read date success. date=%"PRId64, _date_value);
|
||||||
|
|
||||||
|
// time zone
|
||||||
|
// While the design of this type reserves room for time zone offset
|
||||||
|
// information, it should not be filled in, nor used, as it is unconventional
|
||||||
|
// to change time zones when serializing dates on a network. It is suggested
|
||||||
|
// that the time zone be queried independently as needed.
|
||||||
|
if (!stream->require(2)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_DECODE;
|
||||||
|
srs_error("amf0 read time zone failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_time_zone = stream->read_2bytes();
|
||||||
|
srs_verbose("amf0 read time zone success. zone=%d", _time_zone);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int SrsAmf0Date::write(SrsStream* stream)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// marker
|
||||||
|
if (!stream->require(1)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||||
|
srs_error("amf0 write date marker failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->write_1bytes(RTMP_AMF0_Date);
|
||||||
|
srs_verbose("amf0 write date marker success");
|
||||||
|
|
||||||
|
// date value
|
||||||
|
if (!stream->require(8)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||||
|
srs_error("amf0 write date failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->write_8bytes(_date_value);
|
||||||
|
srs_verbose("amf0 write date success. date=%"PRId64, _date_value);
|
||||||
|
|
||||||
|
// time zone
|
||||||
|
if (!stream->require(2)) {
|
||||||
|
ret = ERROR_RTMP_AMF0_ENCODE;
|
||||||
|
srs_error("amf0 write time zone failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->write_2bytes(_time_zone);
|
||||||
|
srs_verbose("amf0 write time zone success. date=%d", _time_zone);
|
||||||
|
|
||||||
|
srs_verbose("write date object success.");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAmf0Any* SrsAmf0Date::copy()
|
||||||
|
{
|
||||||
|
SrsAmf0Date* copy = new SrsAmf0Date(0);
|
||||||
|
|
||||||
|
copy->_date_value = _date_value;
|
||||||
|
copy->_time_zone = _time_zone;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t SrsAmf0Date::date()
|
||||||
|
{
|
||||||
|
return _date_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t SrsAmf0Date::time_zone()
|
||||||
|
{
|
||||||
|
return _time_zone;
|
||||||
|
}
|
||||||
|
|
||||||
SrsAmf0Null::SrsAmf0Null()
|
SrsAmf0Null::SrsAmf0Null()
|
||||||
{
|
{
|
||||||
marker = RTMP_AMF0_Null;
|
marker = RTMP_AMF0_Null;
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace _srs_internal
|
||||||
{
|
{
|
||||||
class SrsUnSortedHashtable;
|
class SrsUnSortedHashtable;
|
||||||
class SrsAmf0ObjectEOF;
|
class SrsAmf0ObjectEOF;
|
||||||
|
class SrsAmf0Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -185,6 +186,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool is_strict_array();
|
virtual bool is_strict_array();
|
||||||
/**
|
/**
|
||||||
|
* whether current instance is an AMF0 date.
|
||||||
|
* @return true if instance is an AMF0 date; otherwise, false.
|
||||||
|
* @remark, if true, use to_date() to get its value.
|
||||||
|
*/
|
||||||
|
virtual bool is_date();
|
||||||
|
/**
|
||||||
* whether current instance is an AMF0 object, object-EOF, ecma-array or strict-array.
|
* whether current instance is an AMF0 object, object-EOF, ecma-array or strict-array.
|
||||||
*/
|
*/
|
||||||
virtual bool is_complex_object();
|
virtual bool is_complex_object();
|
||||||
|
@ -212,6 +219,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual double to_number();
|
virtual double to_number();
|
||||||
/**
|
/**
|
||||||
|
* convert instance to date,
|
||||||
|
* @remark assert is_date(), user must ensure the type then convert.
|
||||||
|
*/
|
||||||
|
virtual int64_t to_date();
|
||||||
|
virtual int16_t to_date_time_zone();
|
||||||
|
/**
|
||||||
* convert instance to amf0 object,
|
* convert instance to amf0 object,
|
||||||
* @remark assert is_object(), user must ensure the type then convert.
|
* @remark assert is_object(), user must ensure the type then convert.
|
||||||
*/
|
*/
|
||||||
|
@ -274,6 +287,10 @@ public:
|
||||||
*/
|
*/
|
||||||
static SrsAmf0Any* number(double value = 0.0);
|
static SrsAmf0Any* number(double value = 0.0);
|
||||||
/**
|
/**
|
||||||
|
* create an AMF0 date instance
|
||||||
|
*/
|
||||||
|
static SrsAmf0Any* date(int64_t value = 0);
|
||||||
|
/**
|
||||||
* create an AMF0 null instance
|
* create an AMF0 null instance
|
||||||
*/
|
*/
|
||||||
static SrsAmf0Any* null();
|
static SrsAmf0Any* null();
|
||||||
|
@ -532,6 +549,7 @@ public:
|
||||||
static int utf8(std::string value);
|
static int utf8(std::string value);
|
||||||
static int str(std::string value);
|
static int str(std::string value);
|
||||||
static int number();
|
static int number();
|
||||||
|
static int date();
|
||||||
static int null();
|
static int null();
|
||||||
static int undefined();
|
static int undefined();
|
||||||
static int boolean();
|
static int boolean();
|
||||||
|
@ -673,6 +691,43 @@ namespace _srs_internal
|
||||||
virtual SrsAmf0Any* copy();
|
virtual SrsAmf0Any* copy();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2.13 Date Type
|
||||||
|
* time-zone = S16 ; reserved, not supported should be set to 0x0000
|
||||||
|
* date-type = date-marker DOUBLE time-zone
|
||||||
|
* @see: https://github.com/winlinvip/simple-rtmp-server/issues/185
|
||||||
|
*/
|
||||||
|
class SrsAmf0Date : public SrsAmf0Any
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int64_t _date_value;
|
||||||
|
int16_t _time_zone;
|
||||||
|
private:
|
||||||
|
friend class SrsAmf0Any;
|
||||||
|
/**
|
||||||
|
* make amf0 date to private,
|
||||||
|
* use should never declare it, use SrsAmf0Any::date() to create it.
|
||||||
|
*/
|
||||||
|
SrsAmf0Date(int64_t value);
|
||||||
|
public:
|
||||||
|
virtual ~SrsAmf0Date();
|
||||||
|
// serialize/deserialize to/from stream.
|
||||||
|
public:
|
||||||
|
virtual int total_size();
|
||||||
|
virtual int read(SrsStream* stream);
|
||||||
|
virtual int write(SrsStream* stream);
|
||||||
|
virtual SrsAmf0Any* copy();
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* get the date value.
|
||||||
|
*/
|
||||||
|
virtual int64_t date();
|
||||||
|
/**
|
||||||
|
* get the time_zone.
|
||||||
|
*/
|
||||||
|
virtual int16_t time_zone();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read amf0 null from stream.
|
* read amf0 null from stream.
|
||||||
* 2.7 null Type
|
* 2.7 null Type
|
||||||
|
|
Loading…
Reference in a new issue