From 6a3418cd453f0d72c4bd853ed1bd4ebc5285be39 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 25 Oct 2014 17:12:56 +0800 Subject: [PATCH] fix #185, AMF0 support 0x0B the date type codec. 2.0.5. --- README.md | 1 + .../players/srs_player/release/srs_player.swf | Bin 5572 -> 5586 bytes .../players/srs_player/src/srs_player.as | 2 +- trunk/src/core/srs_core.hpp | 2 +- trunk/src/rtmp/srs_protocol_amf0.cpp | 164 +++++++++++++++++- trunk/src/rtmp/srs_protocol_amf0.hpp | 55 ++++++ 6 files changed, 220 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0481ca09e..1a01609a3 100755 --- a/README.md +++ b/README.md @@ -220,6 +220,7 @@ Supported operating systems and hardware: * 2013-10-17, Created.
## 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, 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 diff --git a/trunk/research/players/srs_player/release/srs_player.swf b/trunk/research/players/srs_player/release/srs_player.swf index dff28fe19eb649a1a3679a967bffe4e3e7e4d346..82aca05c3bf3e820bd72ea73fc7d796b7f6e860b 100755 GIT binary patch delta 5475 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 ZJuJUw!BTk@zBo+%=Z_UY{|`V@0IVk`(O3Wg delta 5447 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 diff --git a/trunk/research/players/srs_player/src/srs_player.as b/trunk/research/players/srs_player/src/srs_player.as index a8fa5ec2c..5cf1a3c53 100755 --- a/trunk/research/players/srs_player/src/srs_player.as +++ b/trunk/research/players/srs_player/src/srs_player.as @@ -377,7 +377,7 @@ package this.media_conn.connect(null); } else { var tcUrl:String = this.user_url.substr(0, this.user_url.lastIndexOf("/")); - this.media_conn.connect(tcUrl); + this.media_conn.connect(tcUrl, new Date()); } } diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index c6f6ae378..25b19cb04 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR "2" #define VERSION_MINOR "0" -#define VERSION_REVISION "6" +#define VERSION_REVISION "7" #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/rtmp/srs_protocol_amf0.cpp b/trunk/src/rtmp/srs_protocol_amf0.cpp index 91df82614..2b6fdb95b 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.cpp +++ b/trunk/src/rtmp/srs_protocol_amf0.cpp @@ -109,6 +109,11 @@ bool SrsAmf0Any::is_strict_array() return marker == RTMP_AMF0_StrictArray; } +bool SrsAmf0Any::is_date() +{ + return marker == RTMP_AMF0_Date; +} + bool SrsAmf0Any::is_complex_object() { return is_object() || is_object_eof() || is_ecma_array() || is_strict_array(); @@ -142,6 +147,20 @@ double SrsAmf0Any::to_number() return p->value; } +int64_t SrsAmf0Any::to_date() +{ + SrsAmf0Date* p = dynamic_cast(this); + srs_assert(p != NULL); + return p->date(); +} + +int16_t SrsAmf0Any::to_date_time_zone() +{ + SrsAmf0Date* p = dynamic_cast(this); + srs_assert(p != NULL); + return p->time_zone(); +} + SrsAmf0Object* SrsAmf0Any::to_object() { SrsAmf0Object* p = dynamic_cast(this); @@ -189,6 +208,9 @@ void __srs_amf0_do_print(SrsAmf0Any* any, stringstream& ss, int level) ss << "Number " << std::fixed << any->to_number() << endl; } else if (any->is_string()) { 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()) { ss << "Null" << endl; } else if (any->is_ecma_array()) { @@ -304,6 +326,11 @@ SrsAmf0StrictArray* SrsAmf0Any::strict_array() return new SrsAmf0StrictArray(); } +SrsAmf0Any* SrsAmf0Any::date(int64_t value) +{ + return new SrsAmf0Date(value); +} + int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue) { int ret = ERROR_SUCCESS; @@ -360,6 +387,10 @@ int SrsAmf0Any::discovery(SrsStream* stream, SrsAmf0Any** ppvalue) *ppvalue = SrsAmf0Any::strict_array(); return ret; } + case RTMP_AMF0_Date: { + *ppvalue = SrsAmf0Any::date(); + return ret; + } case RTMP_AMF0_Invalid: default: { ret = ERROR_RTMP_AMF0_INVALID; @@ -805,7 +836,7 @@ int SrsAmf0EcmaArray::read(SrsStream* stream) if (marker != RTMP_AMF0_EcmaArray) { ret = ERROR_RTMP_AMF0_DECODE; 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; } srs_verbose("amf0 read ecma_array marker success"); @@ -1003,7 +1034,7 @@ int SrsAmf0StrictArray::read(SrsStream* stream) if (marker != RTMP_AMF0_StrictArray) { ret = ERROR_RTMP_AMF0_DECODE; 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; } srs_verbose("amf0 read strict_array marker success"); @@ -1127,6 +1158,11 @@ int SrsAmf0Size::number() return 1 + 8; } +int SrsAmf0Size::date() +{ + return 1 + 8 + 2; +} + int SrsAmf0Size::null() { return 1; @@ -1278,6 +1314,130 @@ SrsAmf0Any* SrsAmf0Number::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() { marker = RTMP_AMF0_Null; diff --git a/trunk/src/rtmp/srs_protocol_amf0.hpp b/trunk/src/rtmp/srs_protocol_amf0.hpp index 1ecc3f4ae..bbf27459a 100644 --- a/trunk/src/rtmp/srs_protocol_amf0.hpp +++ b/trunk/src/rtmp/srs_protocol_amf0.hpp @@ -43,6 +43,7 @@ namespace _srs_internal { class SrsUnSortedHashtable; class SrsAmf0ObjectEOF; + class SrsAmf0Date; } /* @@ -185,6 +186,12 @@ public: */ 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. */ virtual bool is_complex_object(); @@ -212,6 +219,12 @@ public: */ 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, * @remark assert is_object(), user must ensure the type then convert. */ @@ -274,6 +287,10 @@ public: */ static SrsAmf0Any* number(double value = 0.0); /** + * create an AMF0 date instance + */ + static SrsAmf0Any* date(int64_t value = 0); + /** * create an AMF0 null instance */ static SrsAmf0Any* null(); @@ -532,6 +549,7 @@ public: static int utf8(std::string value); static int str(std::string value); static int number(); + static int date(); static int null(); static int undefined(); static int boolean(); @@ -673,6 +691,43 @@ namespace _srs_internal 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. * 2.7 null Type