diff --git a/README.md b/README.md
index 9a598a34e..e92db1b50 100755
--- a/README.md
+++ b/README.md
@@ -231,6 +231,7 @@ Supported operating systems and hardware:
* 2013-10-17, Created.
## History
+* v1.0, 2014-05-29, support flv inject and flv http streaming with start=bytes. 0.9.122
* v1.0, 2014-05-28, [1.0 mainline4(0.9.120)](https://github.com/winlinvip/simple-rtmp-server/releases/tag/1.0.mainline4) released. 39200 lines.
* v1.0, 2014-05-27, fix [#87](https://github.com/winlinvip/simple-rtmp-server/issues/87), add source id for full trackable log. 0.9.120
* v1.0, 2014-05-27, fix [#84](https://github.com/winlinvip/simple-rtmp-server/issues/84), unpublish when edge disconnect. 0.9.119
diff --git a/trunk/research/librtmp/srs_flv_injecter.c b/trunk/research/librtmp/srs_flv_injecter.c
index 8a500b445..9779081d6 100644
--- a/trunk/research/librtmp/srs_flv_injecter.c
+++ b/trunk/research/librtmp/srs_flv_injecter.c
@@ -38,7 +38,6 @@ gcc srs_flv_injecter.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_flv_i
#define ERROR_INJECTED 10000
int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc);
-int inject_flv(srs_flv_t ic, srs_flv_t oc);
int main(int argc, char** argv)
{
int ret = 0;
@@ -108,22 +107,52 @@ int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, s
{
int ret = 0;
- if ((*pic = srs_flv_open_read(in_flv_file)) == NULL) {
+ srs_flv_t ic;
+ srs_flv_t oc;
+
+ // to adjust metadata.
+ // the ic metadata end offset, the next tag start offset.
+ // all oc metadata must adjust according to:
+ // adjust = new_metadata_end_offset - metadata_end_offset
+ int64_t metadata_end_offset = 0;
+
+ // metadata
+ srs_amf0_t amf0_name = NULL;
+ srs_amf0_t amf0_data = NULL;
+ srs_amf0_t filepositions = NULL;
+
+ if ((ic = srs_flv_open_read(in_flv_file)) == NULL) {
ret = 2;
trace("open input flv file failed. ret=%d", ret);
return ret;
}
+ *pic = ic;
- if ((*poc = srs_flv_open_write(out_flv_file)) == NULL) {
+ if ((oc = srs_flv_open_write(out_flv_file)) == NULL) {
ret = 2;
trace("open output flv file failed. ret=%d", ret);
return ret;
}
+ *poc = oc;
+
+ /**
+ * we use two roundtrip to avoid the paddings of metadata,
+ * to support large keyframes videos without padding fields.
+ */
+ // build keyframes offset to metadata.
+ if ((ret = build_keyframes(ic, &amf0_name, &amf0_data, &filepositions, &metadata_end_offset)) != 0) {
+ return ret;
+ }
- if ((ret = inject_flv(*pic, *poc)) != 0) {
+ // inject the metadata to oc.
+ if ((ret = do_inject_flv(ic, oc, amf0_name, amf0_data, filepositions, metadata_end_offset)) != 0) {
return ret;
}
+ // TODO: FIXME: mem leak when error.
+ srs_amf0_free(amf0_name);
+ srs_amf0_free(amf0_data);
+
return ret;
}
@@ -148,12 +177,13 @@ int parse_metadata(char* data, int size, srs_amf0_t* pname, srs_amf0_t* pdata)
return ret;
}
-int inject_flv(srs_flv_t ic, srs_flv_t oc)
+int build_keyframes(srs_flv_t ic, srs_amf0_t *pname, srs_amf0_t* pdata, srs_amf0_t* pfilepositions, int64_t* pmetadata_end_offset)
{
int ret = 0;
// flv header
char header[13];
+
// packet data
char type;
u_int32_t timestamp = 0;
@@ -163,8 +193,8 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
// metadata
srs_amf0_t amf0_name = NULL;
- int amf0_name_size = 0;
srs_amf0_t amf0_data = NULL;
+
srs_amf0_t keyframes = NULL;
srs_amf0_t filepositions = NULL;
srs_amf0_t times = NULL;
@@ -184,7 +214,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
if ((ret = srs_flv_read_tag_header(ic, &type, &size, ×tamp)) != 0) {
if (srs_flv_is_eof(ret)) {
trace("parse completed.");
- break;
+ return 0;
}
trace("flv get packet failed. ret=%d", ret);
return ret;
@@ -192,7 +222,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
if (size <= 0) {
trace("invalid size=%d", size);
- break;
+ return ret;
}
// TODO: FIXME: mem leak when error.
@@ -208,30 +238,40 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
srs_amf0_strict_array_append(times, srs_amf0_create_number(((double)timestamp)/ 1000));
}
} else if (type == SRS_RTMP_TYPE_SCRIPT) {
+ *pmetadata_end_offset = srs_flv_tellg(ic);
if ((ret = parse_metadata(data, size, &amf0_name, &amf0_data)) != 0) {
return ret;
}
+ *pname = amf0_name;
+ *pdata = amf0_data;
+
if (srs_amf0_is_object(amf0_data)) {
keyframes = srs_amf0_object_property(amf0_data, "keyframes");
- if (keyframes != NULL) {
- return 0;
+ if (keyframes == NULL) {
+ keyframes = srs_amf0_create_ecma_array();
}
- keyframes = srs_amf0_create_ecma_array();
srs_amf0_object_property_set(amf0_data, "keyframes", keyframes);
- filepositions = srs_amf0_create_strict_array();
+ // always clear the old keyframes.
+ srs_amf0_ecma_array_clear(keyframes);
+
+ *pfilepositions = filepositions = srs_amf0_create_strict_array();
srs_amf0_object_property_set(keyframes, "filepositions", filepositions);
+
times = srs_amf0_create_strict_array();
srs_amf0_object_property_set(keyframes, "times", times);
} else if (srs_amf0_is_ecma_array(amf0_data)) {
keyframes = srs_amf0_ecma_array_property(amf0_data, "keyframes");
- if (keyframes != NULL) {
- return 0;
+ if (keyframes == NULL) {
+ keyframes = srs_amf0_create_ecma_array();
}
- keyframes = srs_amf0_create_ecma_array();
srs_amf0_ecma_array_property_set(amf0_data, "keyframes", keyframes);
- filepositions = srs_amf0_create_strict_array();
+ // always clear the old keyframes.
+ srs_amf0_ecma_array_clear(keyframes);
+
+ *pfilepositions = filepositions = srs_amf0_create_strict_array();
srs_amf0_ecma_array_property_set(keyframes, "filepositions", filepositions);
+
times = srs_amf0_create_strict_array();
srs_amf0_ecma_array_property_set(keyframes, "times", times);
}
@@ -240,6 +280,30 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
free(data);
}
+ return ret;
+}
+
+int do_inject_flv(srs_flv_t ic, srs_flv_t oc, srs_amf0_t amf0_name, srs_amf0_t amf0_data, srs_amf0_t filepositions, int64_t metadata_end_offset)
+{
+ int ret = 0;
+
+ // flv header
+ char header[13];
+ // packet data
+ char type;
+ u_int32_t timestamp = 0;
+ char* data = NULL;
+ int32_t size;
+
+ // metadata
+ srs_amf0_t fileposition = NULL;
+ int amf0_name_size = 0;
+ int i;
+
+ // the metadata end offset, the next tag start offset.
+ int64_t new_metadata_end_offset = 0;
+ int offset_adjust = 0;
+
// reset to write injected file
srs_flv_lseek(ic, 0);
@@ -255,7 +319,18 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
if (amf0_name != NULL && amf0_data != NULL) {
amf0_name_size = srs_amf0_size(amf0_name);
size = amf0_name_size + srs_amf0_size(amf0_data);
+
+ // adjust all offset of keyframes.
+ new_metadata_end_offset = srs_flv_tellg(oc) + srs_flv_size_tag(size);
+ // the adjust is new offset sub the old offset of metadata end.
+ offset_adjust = new_metadata_end_offset - metadata_end_offset;
+ for (i = 0; i < srs_amf0_strict_array_property_count(filepositions); i++) {
+ fileposition = srs_amf0_strict_array_property_at(filepositions, i);
+ srs_amf0_set_number(fileposition, srs_amf0_to_number(fileposition) + offset_adjust);
+ }
+
data = (char*)malloc(size);
+ memset(data, 0, size);
if ((ret = srs_amf0_serialize(amf0_name, data, amf0_name_size)) != 0) {
return ret;
}
@@ -267,6 +342,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
}
free(data);
}
+
trace("build keyframe infos from flv");
for (;;) {
// tag header
@@ -303,8 +379,5 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
free(data);
}
- srs_amf0_free(amf0_name);
- srs_amf0_free(amf0_data);
-
return ret;
}
diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp
index ed3275a94..20bdac12d 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 "0"
#define VERSION_MINOR "9"
-#define VERSION_REVISION "121"
+#define VERSION_REVISION "122"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "SRS"
diff --git a/trunk/src/kernel/srs_kernel_flv.cpp b/trunk/src/kernel/srs_kernel_flv.cpp
index 60c7e313f..d5c25b8be 100644
--- a/trunk/src/kernel/srs_kernel_flv.cpp
+++ b/trunk/src/kernel/srs_kernel_flv.cpp
@@ -330,6 +330,11 @@ int SrsFlvEncoder::write_video(int64_t timestamp, char* data, int size)
return ret;
}
+int SrsFlvEncoder::size_tag(int data_size)
+{
+ return SRS_FLV_TAG_HEADER_SIZE + data_size + SRS_FLV_PREVIOUS_TAG_SIZE;
+}
+
int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_size)
{
int ret = ERROR_SUCCESS;
diff --git a/trunk/src/kernel/srs_kernel_flv.hpp b/trunk/src/kernel/srs_kernel_flv.hpp
index 8efd3b800..f5f282f3e 100644
--- a/trunk/src/kernel/srs_kernel_flv.hpp
+++ b/trunk/src/kernel/srs_kernel_flv.hpp
@@ -105,6 +105,11 @@ public:
*/
virtual int write_audio(int64_t timestamp, char* data, int size);
virtual int write_video(int64_t timestamp, char* data, int size);
+ /**
+ * get the tag size,
+ * including the tag header, body, and 4bytes previous tag size.
+ */
+ static int size_tag(int data_size);
private:
virtual int write_tag(char* header, int header_size, char* tag, int tag_size);
};
diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp
index 7648d1f70..f1d2d5451 100644
--- a/trunk/src/libs/srs_librtmp.cpp
+++ b/trunk/src/libs/srs_librtmp.cpp
@@ -519,6 +519,11 @@ int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int si
return ret;
}
+int srs_flv_size_tag(int data_size)
+{
+ return SrsFlvEncoder::size_tag(data_size);
+}
+
int64_t srs_flv_tellg(srs_flv_t flv)
{
FlvContext* context = (FlvContext*)flv;
@@ -684,6 +689,12 @@ amf0_number srs_amf0_to_number(srs_amf0_t amf0)
return any->to_number();
}
+void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value)
+{
+ SrsAmf0Any* any = (SrsAmf0Any*)amf0;
+ any->set_number(value);
+}
+
int srs_amf0_object_property_count(srs_amf0_t amf0)
{
SrsAmf0Object* obj = (SrsAmf0Object*)amf0;
@@ -746,6 +757,12 @@ void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf
obj->set(name, any);
}
+void srs_amf0_ecma_array_clear(srs_amf0_t amf0)
+{
+ SrsAmf0EcmaArray* obj = (SrsAmf0EcmaArray*)amf0;
+ obj->clear();
+}
+
int srs_amf0_strict_array_property_count(srs_amf0_t amf0)
{
SrsAmf0StrictArray * obj = (SrsAmf0StrictArray*)amf0;
diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp
index d3bd5fde8..c236ea710 100644
--- a/trunk/src/libs/srs_librtmp.hpp
+++ b/trunk/src/libs/srs_librtmp.hpp
@@ -169,6 +169,8 @@ int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size);
int srs_flv_write_header(srs_flv_t flv, char header[9]);
/* write flv tag to file, auto write the 4bytes previous tag size */
int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size);
+/* get the tag size, for flv injecter to adjust offset, size=tag_header+data+previous_tag */
+int srs_flv_size_tag(int data_size);
/* file stream */
/* file stream tellg to get offset */
int64_t srs_flv_tellg(srs_flv_t flv);
@@ -211,6 +213,8 @@ amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
const char* srs_amf0_to_string(srs_amf0_t amf0);
amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
amf0_number srs_amf0_to_number(srs_amf0_t amf0);
+/* value setter */
+void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value);
/* object value converter */
int srs_amf0_object_property_count(srs_amf0_t amf0);
const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index);
@@ -223,6 +227,7 @@ const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name);
void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
+void srs_amf0_ecma_array_clear(srs_amf0_t amf0);
/* strict array value converter */
int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
diff --git a/trunk/src/rtmp/srs_protocol_amf0.cpp b/trunk/src/rtmp/srs_protocol_amf0.cpp
index 716f4ce16..00c5bd22e 100644
--- a/trunk/src/rtmp/srs_protocol_amf0.cpp
+++ b/trunk/src/rtmp/srs_protocol_amf0.cpp
@@ -75,6 +75,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -95,6 +96,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -114,6 +116,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -130,6 +133,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -146,6 +150,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -173,6 +178,8 @@ public:
virtual SrsAmf0Any* get_property(std::string name);
virtual SrsAmf0Any* ensure_property_string(std::string name);
virtual SrsAmf0Any* ensure_property_number(std::string name);
+
+ virtual void copy(__SrsUnSortedHashtable* src);
};
/**
@@ -191,6 +198,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
};
/**
@@ -310,6 +318,13 @@ SrsAmf0StrictArray* SrsAmf0Any::to_strict_array()
return p;
}
+void SrsAmf0Any::set_number(double value)
+{
+ __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this);
+ srs_assert(p != NULL);
+ p->value = value;
+}
+
bool SrsAmf0Any::is_object_eof()
{
return marker == RTMP_AMF0_ObjectEnd;
@@ -433,13 +448,7 @@ __SrsUnSortedHashtable::__SrsUnSortedHashtable()
__SrsUnSortedHashtable::~__SrsUnSortedHashtable()
{
- std::vector::iterator it;
- for (it = properties.begin(); it != properties.end(); ++it) {
- SrsAmf0ObjectPropertyType& elem = *it;
- SrsAmf0Any* any = elem.second;
- srs_freep(any);
- }
- properties.clear();
+ clear();
}
int __SrsUnSortedHashtable::count()
@@ -449,6 +458,12 @@ int __SrsUnSortedHashtable::count()
void __SrsUnSortedHashtable::clear()
{
+ std::vector::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ SrsAmf0ObjectPropertyType& elem = *it;
+ SrsAmf0Any* any = elem.second;
+ srs_freep(any);
+ }
properties.clear();
}
@@ -543,6 +558,17 @@ SrsAmf0Any* __SrsUnSortedHashtable::ensure_property_number(string name)
return prop;
}
+void __SrsUnSortedHashtable::copy(__SrsUnSortedHashtable* src)
+{
+ std::vector::iterator it;
+ for (it = src->properties.begin(); it != src->properties.end(); ++it) {
+ SrsAmf0ObjectPropertyType& elem = *it;
+ std::string key = elem.first;
+ SrsAmf0Any* any = elem.second;
+ set(key, any->copy());
+ }
+}
+
__SrsAmf0ObjectEOF::__SrsAmf0ObjectEOF()
{
marker = RTMP_AMF0_ObjectEnd;
@@ -623,6 +649,11 @@ int __SrsAmf0ObjectEOF::write(SrsStream* stream)
return ret;
}
+SrsAmf0Any* __SrsAmf0ObjectEOF::copy()
+{
+ return new __SrsAmf0ObjectEOF();
+}
+
SrsAmf0Object::SrsAmf0Object()
{
properties = new __SrsUnSortedHashtable();
@@ -750,6 +781,13 @@ int SrsAmf0Object::write(SrsStream* stream)
return ret;
}
+SrsAmf0Any* SrsAmf0Object::copy()
+{
+ SrsAmf0Object* copy = new SrsAmf0Object();
+ copy->properties->copy(properties);
+ return copy;
+}
+
int SrsAmf0Object::count()
{
return properties->count();
@@ -792,6 +830,7 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_number(string name)
SrsAmf0EcmaArray::SrsAmf0EcmaArray()
{
+ _count = 0;
properties = new __SrsUnSortedHashtable();
eof = new __SrsAmf0ObjectEOF();
marker = RTMP_AMF0_EcmaArray;
@@ -937,6 +976,14 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
return ret;
}
+SrsAmf0Any* SrsAmf0EcmaArray::copy()
+{
+ SrsAmf0EcmaArray* copy = new SrsAmf0EcmaArray();
+ copy->properties->copy(properties);
+ copy->_count = _count;
+ return copy;
+}
+
void SrsAmf0EcmaArray::clear()
{
properties->clear();
@@ -1097,6 +1144,20 @@ int SrsAmf0StrictArray::write(SrsStream* stream)
return ret;
}
+SrsAmf0Any* SrsAmf0StrictArray::copy()
+{
+ SrsAmf0StrictArray* copy = new SrsAmf0StrictArray();
+
+ std::vector::iterator it;
+ for (it = properties.begin(); it != properties.end(); ++it) {
+ SrsAmf0Any* any = *it;
+ copy->append(any->copy());
+ }
+
+ copy->_count = _count;
+ return copy;
+}
+
void SrsAmf0StrictArray::clear()
{
properties.clear();
@@ -1116,6 +1177,7 @@ SrsAmf0Any* SrsAmf0StrictArray::at(int index)
void SrsAmf0StrictArray::append(SrsAmf0Any* any)
{
properties.push_back(any);
+ _count = (int32_t)properties.size();
}
int SrsAmf0Size::utf8(string value)
@@ -1216,6 +1278,12 @@ int __SrsAmf0String::write(SrsStream* stream)
return srs_amf0_write_string(stream, value);
}
+SrsAmf0Any* __SrsAmf0String::copy()
+{
+ __SrsAmf0String* copy = new __SrsAmf0String(value.c_str());
+ return copy;
+}
+
__SrsAmf0Boolean::__SrsAmf0Boolean(bool _value)
{
marker = RTMP_AMF0_Boolean;
@@ -1241,6 +1309,12 @@ int __SrsAmf0Boolean::write(SrsStream* stream)
return srs_amf0_write_boolean(stream, value);
}
+SrsAmf0Any* __SrsAmf0Boolean::copy()
+{
+ __SrsAmf0Boolean* copy = new __SrsAmf0Boolean(value);
+ return copy;
+}
+
__SrsAmf0Number::__SrsAmf0Number(double _value)
{
marker = RTMP_AMF0_Number;
@@ -1266,6 +1340,12 @@ int __SrsAmf0Number::write(SrsStream* stream)
return srs_amf0_write_number(stream, value);
}
+SrsAmf0Any* __SrsAmf0Number::copy()
+{
+ __SrsAmf0Number* copy = new __SrsAmf0Number(value);
+ return copy;
+}
+
__SrsAmf0Null::__SrsAmf0Null()
{
marker = RTMP_AMF0_Null;
@@ -1290,6 +1370,12 @@ int __SrsAmf0Null::write(SrsStream* stream)
return srs_amf0_write_null(stream);
}
+SrsAmf0Any* __SrsAmf0Null::copy()
+{
+ __SrsAmf0Null* copy = new __SrsAmf0Null();
+ return copy;
+}
+
__SrsAmf0Undefined::__SrsAmf0Undefined()
{
marker = RTMP_AMF0_Undefined;
@@ -1314,6 +1400,12 @@ int __SrsAmf0Undefined::write(SrsStream* stream)
return srs_amf0_write_undefined(stream);
}
+SrsAmf0Any* __SrsAmf0Undefined::copy()
+{
+ __SrsAmf0Undefined* copy = new __SrsAmf0Undefined();
+ return copy;
+}
+
int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue)
{
int ret = ERROR_SUCCESS;
diff --git a/trunk/src/rtmp/srs_protocol_amf0.hpp b/trunk/src/rtmp/srs_protocol_amf0.hpp
index df8401958..0b751dc9a 100644
--- a/trunk/src/rtmp/srs_protocol_amf0.hpp
+++ b/trunk/src/rtmp/srs_protocol_amf0.hpp
@@ -63,6 +63,11 @@ class __SrsAmf0ObjectEOF;
// SrsAmf0Object* obj = SrsAmf0Any::object();
// 5. SrsAmf0EcmaArray: create the amf0 ecma array.
// SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
+// 6. SrsAmf0Any: set basic type value
+// SrsAmf0Any* pany = ...
+// if (pany->is_number()) {
+// pany->set_number(100.1);
+// }
//
// please carefully the size and count of amf0 any:
// 1. total_size(): the total memory size the object wrote to buffer.
@@ -129,6 +134,12 @@ public:
*/
virtual SrsAmf0EcmaArray* to_ecma_array();
virtual SrsAmf0StrictArray* to_strict_array();
+public:
+ /**
+ * set the number of any when is_number() indicates true.
+ * user must ensure the type is a number, or assert failed.
+ */
+ virtual void set_number(double value);
public:
/**
* get the size of amf0 any, including the marker size.
@@ -139,6 +150,7 @@ public:
*/
virtual int read(SrsStream* stream) = 0;
virtual int write(SrsStream* stream) = 0;
+ virtual SrsAmf0Any* copy() = 0;
public:
static SrsAmf0Any* str(const char* value = NULL);
static SrsAmf0Any* boolean(bool value = false);
@@ -175,6 +187,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
public:
virtual int count();
@@ -215,6 +228,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
public:
virtual void clear();
@@ -254,6 +268,7 @@ public:
virtual int total_size();
virtual int read(SrsStream* stream);
virtual int write(SrsStream* stream);
+ virtual SrsAmf0Any* copy();
public:
virtual void clear();
diff --git a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp
index 37c0aaac2..786a32ade 100644
--- a/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp
+++ b/trunk/src/rtmp/srs_protocol_rtmp_stack.cpp
@@ -3173,10 +3173,9 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream)
// if ecma array, copy to object.
for (int i = 0; i < arr->count(); i++) {
- metadata->set(arr->key_at(i), arr->value_at(i));
+ metadata->set(arr->key_at(i), arr->value_at(i)->copy());
}
- arr->clear();
srs_info("decode metadata array success");
}