winlin

support flv inject and flv http streaming with start=bytes. 0.9.122

@@ -231,6 +231,7 @@ Supported operating systems and hardware: @@ -231,6 +231,7 @@ Supported operating systems and hardware:
231 * 2013-10-17, Created.<br/> 231 * 2013-10-17, Created.<br/>
232 232
233 ## History 233 ## History
  234 +* v1.0, 2014-05-29, support flv inject and flv http streaming with start=bytes. 0.9.122
234 * <strong>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.</strong> 235 * <strong>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.</strong>
235 * 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 236 * 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
236 * v1.0, 2014-05-27, fix [#84](https://github.com/winlinvip/simple-rtmp-server/issues/84), unpublish when edge disconnect. 0.9.119 237 * v1.0, 2014-05-27, fix [#84](https://github.com/winlinvip/simple-rtmp-server/issues/84), unpublish when edge disconnect. 0.9.119
@@ -38,7 +38,6 @@ gcc srs_flv_injecter.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_flv_i @@ -38,7 +38,6 @@ gcc srs_flv_injecter.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_flv_i
38 #define ERROR_INJECTED 10000 38 #define ERROR_INJECTED 10000
39 39
40 int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc); 40 int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, srs_flv_t* poc);
41 -int inject_flv(srs_flv_t ic, srs_flv_t oc);  
42 int main(int argc, char** argv) 41 int main(int argc, char** argv)
43 { 42 {
44 int ret = 0; 43 int ret = 0;
@@ -108,22 +107,52 @@ int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, s @@ -108,22 +107,52 @@ int process(const char* in_flv_file, const char* out_flv_file, srs_flv_t* pic, s
108 { 107 {
109 int ret = 0; 108 int ret = 0;
110 109
111 - if ((*pic = srs_flv_open_read(in_flv_file)) == NULL) { 110 + srs_flv_t ic;
  111 + srs_flv_t oc;
  112 +
  113 + // to adjust metadata.
  114 + // the ic metadata end offset, the next tag start offset.
  115 + // all oc metadata must adjust according to:
  116 + // adjust = new_metadata_end_offset - metadata_end_offset
  117 + int64_t metadata_end_offset = 0;
  118 +
  119 + // metadata
  120 + srs_amf0_t amf0_name = NULL;
  121 + srs_amf0_t amf0_data = NULL;
  122 + srs_amf0_t filepositions = NULL;
  123 +
  124 + if ((ic = srs_flv_open_read(in_flv_file)) == NULL) {
112 ret = 2; 125 ret = 2;
113 trace("open input flv file failed. ret=%d", ret); 126 trace("open input flv file failed. ret=%d", ret);
114 return ret; 127 return ret;
115 } 128 }
  129 + *pic = ic;
116 130
117 - if ((*poc = srs_flv_open_write(out_flv_file)) == NULL) { 131 + if ((oc = srs_flv_open_write(out_flv_file)) == NULL) {
118 ret = 2; 132 ret = 2;
119 trace("open output flv file failed. ret=%d", ret); 133 trace("open output flv file failed. ret=%d", ret);
120 return ret; 134 return ret;
121 } 135 }
  136 + *poc = oc;
  137 +
  138 + /**
  139 + * we use two roundtrip to avoid the paddings of metadata,
  140 + * to support large keyframes videos without padding fields.
  141 + */
  142 + // build keyframes offset to metadata.
  143 + if ((ret = build_keyframes(ic, &amf0_name, &amf0_data, &filepositions, &metadata_end_offset)) != 0) {
  144 + return ret;
  145 + }
122 146
123 - if ((ret = inject_flv(*pic, *poc)) != 0) { 147 + // inject the metadata to oc.
  148 + if ((ret = do_inject_flv(ic, oc, amf0_name, amf0_data, filepositions, metadata_end_offset)) != 0) {
124 return ret; 149 return ret;
125 } 150 }
126 151
  152 + // TODO: FIXME: mem leak when error.
  153 + srs_amf0_free(amf0_name);
  154 + srs_amf0_free(amf0_data);
  155 +
127 return ret; 156 return ret;
128 } 157 }
129 158
@@ -148,12 +177,13 @@ int parse_metadata(char* data, int size, srs_amf0_t* pname, srs_amf0_t* pdata) @@ -148,12 +177,13 @@ int parse_metadata(char* data, int size, srs_amf0_t* pname, srs_amf0_t* pdata)
148 return ret; 177 return ret;
149 } 178 }
150 179
151 -int inject_flv(srs_flv_t ic, srs_flv_t oc) 180 +int build_keyframes(srs_flv_t ic, srs_amf0_t *pname, srs_amf0_t* pdata, srs_amf0_t* pfilepositions, int64_t* pmetadata_end_offset)
152 { 181 {
153 int ret = 0; 182 int ret = 0;
154 183
155 // flv header 184 // flv header
156 char header[13]; 185 char header[13];
  186 +
157 // packet data 187 // packet data
158 char type; 188 char type;
159 u_int32_t timestamp = 0; 189 u_int32_t timestamp = 0;
@@ -163,8 +193,8 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -163,8 +193,8 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
163 193
164 // metadata 194 // metadata
165 srs_amf0_t amf0_name = NULL; 195 srs_amf0_t amf0_name = NULL;
166 - int amf0_name_size = 0;  
167 srs_amf0_t amf0_data = NULL; 196 srs_amf0_t amf0_data = NULL;
  197 +
168 srs_amf0_t keyframes = NULL; 198 srs_amf0_t keyframes = NULL;
169 srs_amf0_t filepositions = NULL; 199 srs_amf0_t filepositions = NULL;
170 srs_amf0_t times = NULL; 200 srs_amf0_t times = NULL;
@@ -184,7 +214,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -184,7 +214,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
184 if ((ret = srs_flv_read_tag_header(ic, &type, &size, &timestamp)) != 0) { 214 if ((ret = srs_flv_read_tag_header(ic, &type, &size, &timestamp)) != 0) {
185 if (srs_flv_is_eof(ret)) { 215 if (srs_flv_is_eof(ret)) {
186 trace("parse completed."); 216 trace("parse completed.");
187 - break; 217 + return 0;
188 } 218 }
189 trace("flv get packet failed. ret=%d", ret); 219 trace("flv get packet failed. ret=%d", ret);
190 return ret; 220 return ret;
@@ -192,7 +222,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -192,7 +222,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
192 222
193 if (size <= 0) { 223 if (size <= 0) {
194 trace("invalid size=%d", size); 224 trace("invalid size=%d", size);
195 - break; 225 + return ret;
196 } 226 }
197 227
198 // TODO: FIXME: mem leak when error. 228 // TODO: FIXME: mem leak when error.
@@ -208,30 +238,40 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -208,30 +238,40 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
208 srs_amf0_strict_array_append(times, srs_amf0_create_number(((double)timestamp)/ 1000)); 238 srs_amf0_strict_array_append(times, srs_amf0_create_number(((double)timestamp)/ 1000));
209 } 239 }
210 } else if (type == SRS_RTMP_TYPE_SCRIPT) { 240 } else if (type == SRS_RTMP_TYPE_SCRIPT) {
  241 + *pmetadata_end_offset = srs_flv_tellg(ic);
211 if ((ret = parse_metadata(data, size, &amf0_name, &amf0_data)) != 0) { 242 if ((ret = parse_metadata(data, size, &amf0_name, &amf0_data)) != 0) {
212 return ret; 243 return ret;
213 } 244 }
214 245
  246 + *pname = amf0_name;
  247 + *pdata = amf0_data;
  248 +
215 if (srs_amf0_is_object(amf0_data)) { 249 if (srs_amf0_is_object(amf0_data)) {
216 keyframes = srs_amf0_object_property(amf0_data, "keyframes"); 250 keyframes = srs_amf0_object_property(amf0_data, "keyframes");
217 - if (keyframes != NULL) {  
218 - return 0; 251 + if (keyframes == NULL) {
  252 + keyframes = srs_amf0_create_ecma_array();
219 } 253 }
220 - keyframes = srs_amf0_create_ecma_array();  
221 srs_amf0_object_property_set(amf0_data, "keyframes", keyframes); 254 srs_amf0_object_property_set(amf0_data, "keyframes", keyframes);
222 - filepositions = srs_amf0_create_strict_array(); 255 + // always clear the old keyframes.
  256 + srs_amf0_ecma_array_clear(keyframes);
  257 +
  258 + *pfilepositions = filepositions = srs_amf0_create_strict_array();
223 srs_amf0_object_property_set(keyframes, "filepositions", filepositions); 259 srs_amf0_object_property_set(keyframes, "filepositions", filepositions);
  260 +
224 times = srs_amf0_create_strict_array(); 261 times = srs_amf0_create_strict_array();
225 srs_amf0_object_property_set(keyframes, "times", times); 262 srs_amf0_object_property_set(keyframes, "times", times);
226 } else if (srs_amf0_is_ecma_array(amf0_data)) { 263 } else if (srs_amf0_is_ecma_array(amf0_data)) {
227 keyframes = srs_amf0_ecma_array_property(amf0_data, "keyframes"); 264 keyframes = srs_amf0_ecma_array_property(amf0_data, "keyframes");
228 - if (keyframes != NULL) {  
229 - return 0; 265 + if (keyframes == NULL) {
  266 + keyframes = srs_amf0_create_ecma_array();
230 } 267 }
231 - keyframes = srs_amf0_create_ecma_array();  
232 srs_amf0_ecma_array_property_set(amf0_data, "keyframes", keyframes); 268 srs_amf0_ecma_array_property_set(amf0_data, "keyframes", keyframes);
233 - filepositions = srs_amf0_create_strict_array(); 269 + // always clear the old keyframes.
  270 + srs_amf0_ecma_array_clear(keyframes);
  271 +
  272 + *pfilepositions = filepositions = srs_amf0_create_strict_array();
234 srs_amf0_ecma_array_property_set(keyframes, "filepositions", filepositions); 273 srs_amf0_ecma_array_property_set(keyframes, "filepositions", filepositions);
  274 +
235 times = srs_amf0_create_strict_array(); 275 times = srs_amf0_create_strict_array();
236 srs_amf0_ecma_array_property_set(keyframes, "times", times); 276 srs_amf0_ecma_array_property_set(keyframes, "times", times);
237 } 277 }
@@ -240,6 +280,30 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -240,6 +280,30 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
240 free(data); 280 free(data);
241 } 281 }
242 282
  283 + return ret;
  284 +}
  285 +
  286 +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)
  287 +{
  288 + int ret = 0;
  289 +
  290 + // flv header
  291 + char header[13];
  292 + // packet data
  293 + char type;
  294 + u_int32_t timestamp = 0;
  295 + char* data = NULL;
  296 + int32_t size;
  297 +
  298 + // metadata
  299 + srs_amf0_t fileposition = NULL;
  300 + int amf0_name_size = 0;
  301 + int i;
  302 +
  303 + // the metadata end offset, the next tag start offset.
  304 + int64_t new_metadata_end_offset = 0;
  305 + int offset_adjust = 0;
  306 +
243 // reset to write injected file 307 // reset to write injected file
244 srs_flv_lseek(ic, 0); 308 srs_flv_lseek(ic, 0);
245 309
@@ -255,7 +319,18 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -255,7 +319,18 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
255 if (amf0_name != NULL && amf0_data != NULL) { 319 if (amf0_name != NULL && amf0_data != NULL) {
256 amf0_name_size = srs_amf0_size(amf0_name); 320 amf0_name_size = srs_amf0_size(amf0_name);
257 size = amf0_name_size + srs_amf0_size(amf0_data); 321 size = amf0_name_size + srs_amf0_size(amf0_data);
  322 +
  323 + // adjust all offset of keyframes.
  324 + new_metadata_end_offset = srs_flv_tellg(oc) + srs_flv_size_tag(size);
  325 + // the adjust is new offset sub the old offset of metadata end.
  326 + offset_adjust = new_metadata_end_offset - metadata_end_offset;
  327 + for (i = 0; i < srs_amf0_strict_array_property_count(filepositions); i++) {
  328 + fileposition = srs_amf0_strict_array_property_at(filepositions, i);
  329 + srs_amf0_set_number(fileposition, srs_amf0_to_number(fileposition) + offset_adjust);
  330 + }
  331 +
258 data = (char*)malloc(size); 332 data = (char*)malloc(size);
  333 + memset(data, 0, size);
259 if ((ret = srs_amf0_serialize(amf0_name, data, amf0_name_size)) != 0) { 334 if ((ret = srs_amf0_serialize(amf0_name, data, amf0_name_size)) != 0) {
260 return ret; 335 return ret;
261 } 336 }
@@ -267,6 +342,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -267,6 +342,7 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
267 } 342 }
268 free(data); 343 free(data);
269 } 344 }
  345 +
270 trace("build keyframe infos from flv"); 346 trace("build keyframe infos from flv");
271 for (;;) { 347 for (;;) {
272 // tag header 348 // tag header
@@ -303,8 +379,5 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc) @@ -303,8 +379,5 @@ int inject_flv(srs_flv_t ic, srs_flv_t oc)
303 free(data); 379 free(data);
304 } 380 }
305 381
306 - srs_amf0_free(amf0_name);  
307 - srs_amf0_free(amf0_data);  
308 -  
309 return ret; 382 return ret;
310 } 383 }
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // current release version 31 // current release version
32 #define VERSION_MAJOR "0" 32 #define VERSION_MAJOR "0"
33 #define VERSION_MINOR "9" 33 #define VERSION_MINOR "9"
34 -#define VERSION_REVISION "121" 34 +#define VERSION_REVISION "122"
35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION 35 #define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
36 // server info. 36 // server info.
37 #define RTMP_SIG_SRS_KEY "SRS" 37 #define RTMP_SIG_SRS_KEY "SRS"
@@ -330,6 +330,11 @@ int SrsFlvEncoder::write_video(int64_t timestamp, char* data, int size) @@ -330,6 +330,11 @@ int SrsFlvEncoder::write_video(int64_t timestamp, char* data, int size)
330 return ret; 330 return ret;
331 } 331 }
332 332
  333 +int SrsFlvEncoder::size_tag(int data_size)
  334 +{
  335 + return SRS_FLV_TAG_HEADER_SIZE + data_size + SRS_FLV_PREVIOUS_TAG_SIZE;
  336 +}
  337 +
333 int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_size) 338 int SrsFlvEncoder::write_tag(char* header, int header_size, char* tag, int tag_size)
334 { 339 {
335 int ret = ERROR_SUCCESS; 340 int ret = ERROR_SUCCESS;
@@ -105,6 +105,11 @@ public: @@ -105,6 +105,11 @@ public:
105 */ 105 */
106 virtual int write_audio(int64_t timestamp, char* data, int size); 106 virtual int write_audio(int64_t timestamp, char* data, int size);
107 virtual int write_video(int64_t timestamp, char* data, int size); 107 virtual int write_video(int64_t timestamp, char* data, int size);
  108 + /**
  109 + * get the tag size,
  110 + * including the tag header, body, and 4bytes previous tag size.
  111 + */
  112 + static int size_tag(int data_size);
108 private: 113 private:
109 virtual int write_tag(char* header, int header_size, char* tag, int tag_size); 114 virtual int write_tag(char* header, int header_size, char* tag, int tag_size);
110 }; 115 };
@@ -519,6 +519,11 @@ int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int si @@ -519,6 +519,11 @@ int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int si
519 return ret; 519 return ret;
520 } 520 }
521 521
  522 +int srs_flv_size_tag(int data_size)
  523 +{
  524 + return SrsFlvEncoder::size_tag(data_size);
  525 +}
  526 +
522 int64_t srs_flv_tellg(srs_flv_t flv) 527 int64_t srs_flv_tellg(srs_flv_t flv)
523 { 528 {
524 FlvContext* context = (FlvContext*)flv; 529 FlvContext* context = (FlvContext*)flv;
@@ -684,6 +689,12 @@ amf0_number srs_amf0_to_number(srs_amf0_t amf0) @@ -684,6 +689,12 @@ amf0_number srs_amf0_to_number(srs_amf0_t amf0)
684 return any->to_number(); 689 return any->to_number();
685 } 690 }
686 691
  692 +void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value)
  693 +{
  694 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  695 + any->set_number(value);
  696 +}
  697 +
687 int srs_amf0_object_property_count(srs_amf0_t amf0) 698 int srs_amf0_object_property_count(srs_amf0_t amf0)
688 { 699 {
689 SrsAmf0Object* obj = (SrsAmf0Object*)amf0; 700 SrsAmf0Object* obj = (SrsAmf0Object*)amf0;
@@ -746,6 +757,12 @@ void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf @@ -746,6 +757,12 @@ void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf
746 obj->set(name, any); 757 obj->set(name, any);
747 } 758 }
748 759
  760 +void srs_amf0_ecma_array_clear(srs_amf0_t amf0)
  761 +{
  762 + SrsAmf0EcmaArray* obj = (SrsAmf0EcmaArray*)amf0;
  763 + obj->clear();
  764 +}
  765 +
749 int srs_amf0_strict_array_property_count(srs_amf0_t amf0) 766 int srs_amf0_strict_array_property_count(srs_amf0_t amf0)
750 { 767 {
751 SrsAmf0StrictArray * obj = (SrsAmf0StrictArray*)amf0; 768 SrsAmf0StrictArray * obj = (SrsAmf0StrictArray*)amf0;
@@ -169,6 +169,8 @@ int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size); @@ -169,6 +169,8 @@ int srs_flv_read_tag_data(srs_flv_t flv, char* data, int32_t size);
169 int srs_flv_write_header(srs_flv_t flv, char header[9]); 169 int srs_flv_write_header(srs_flv_t flv, char header[9]);
170 /* write flv tag to file, auto write the 4bytes previous tag size */ 170 /* write flv tag to file, auto write the 4bytes previous tag size */
171 int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size); 171 int srs_flv_write_tag(srs_flv_t flv, char type, int32_t time, char* data, int size);
  172 +/* get the tag size, for flv injecter to adjust offset, size=tag_header+data+previous_tag */
  173 +int srs_flv_size_tag(int data_size);
172 /* file stream */ 174 /* file stream */
173 /* file stream tellg to get offset */ 175 /* file stream tellg to get offset */
174 int64_t srs_flv_tellg(srs_flv_t flv); 176 int64_t srs_flv_tellg(srs_flv_t flv);
@@ -211,6 +213,8 @@ amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0); @@ -211,6 +213,8 @@ amf0_bool srs_amf0_is_strict_array(srs_amf0_t amf0);
211 const char* srs_amf0_to_string(srs_amf0_t amf0); 213 const char* srs_amf0_to_string(srs_amf0_t amf0);
212 amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0); 214 amf0_bool srs_amf0_to_boolean(srs_amf0_t amf0);
213 amf0_number srs_amf0_to_number(srs_amf0_t amf0); 215 amf0_number srs_amf0_to_number(srs_amf0_t amf0);
  216 +/* value setter */
  217 +void srs_amf0_set_number(srs_amf0_t amf0, amf0_number value);
214 /* object value converter */ 218 /* object value converter */
215 int srs_amf0_object_property_count(srs_amf0_t amf0); 219 int srs_amf0_object_property_count(srs_amf0_t amf0);
216 const char* srs_amf0_object_property_name_at(srs_amf0_t amf0, int index); 220 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); @@ -223,6 +227,7 @@ const char* srs_amf0_ecma_array_property_name_at(srs_amf0_t amf0, int index);
223 srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index); 227 srs_amf0_t srs_amf0_ecma_array_property_value_at(srs_amf0_t amf0, int index);
224 srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name); 228 srs_amf0_t srs_amf0_ecma_array_property(srs_amf0_t amf0, const char* name);
225 void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value); 229 void srs_amf0_ecma_array_property_set(srs_amf0_t amf0, const char* name, srs_amf0_t value);
  230 +void srs_amf0_ecma_array_clear(srs_amf0_t amf0);
226 /* strict array value converter */ 231 /* strict array value converter */
227 int srs_amf0_strict_array_property_count(srs_amf0_t amf0); 232 int srs_amf0_strict_array_property_count(srs_amf0_t amf0);
228 srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index); 233 srs_amf0_t srs_amf0_strict_array_property_at(srs_amf0_t amf0, int index);
@@ -75,6 +75,7 @@ public: @@ -75,6 +75,7 @@ public:
75 virtual int total_size(); 75 virtual int total_size();
76 virtual int read(SrsStream* stream); 76 virtual int read(SrsStream* stream);
77 virtual int write(SrsStream* stream); 77 virtual int write(SrsStream* stream);
  78 + virtual SrsAmf0Any* copy();
78 }; 79 };
79 80
80 /** 81 /**
@@ -95,6 +96,7 @@ public: @@ -95,6 +96,7 @@ public:
95 virtual int total_size(); 96 virtual int total_size();
96 virtual int read(SrsStream* stream); 97 virtual int read(SrsStream* stream);
97 virtual int write(SrsStream* stream); 98 virtual int write(SrsStream* stream);
  99 + virtual SrsAmf0Any* copy();
98 }; 100 };
99 101
100 /** 102 /**
@@ -114,6 +116,7 @@ public: @@ -114,6 +116,7 @@ public:
114 virtual int total_size(); 116 virtual int total_size();
115 virtual int read(SrsStream* stream); 117 virtual int read(SrsStream* stream);
116 virtual int write(SrsStream* stream); 118 virtual int write(SrsStream* stream);
  119 + virtual SrsAmf0Any* copy();
117 }; 120 };
118 121
119 /** 122 /**
@@ -130,6 +133,7 @@ public: @@ -130,6 +133,7 @@ public:
130 virtual int total_size(); 133 virtual int total_size();
131 virtual int read(SrsStream* stream); 134 virtual int read(SrsStream* stream);
132 virtual int write(SrsStream* stream); 135 virtual int write(SrsStream* stream);
  136 + virtual SrsAmf0Any* copy();
133 }; 137 };
134 138
135 /** 139 /**
@@ -146,6 +150,7 @@ public: @@ -146,6 +150,7 @@ public:
146 virtual int total_size(); 150 virtual int total_size();
147 virtual int read(SrsStream* stream); 151 virtual int read(SrsStream* stream);
148 virtual int write(SrsStream* stream); 152 virtual int write(SrsStream* stream);
  153 + virtual SrsAmf0Any* copy();
149 }; 154 };
150 155
151 /** 156 /**
@@ -173,6 +178,8 @@ public: @@ -173,6 +178,8 @@ public:
173 virtual SrsAmf0Any* get_property(std::string name); 178 virtual SrsAmf0Any* get_property(std::string name);
174 virtual SrsAmf0Any* ensure_property_string(std::string name); 179 virtual SrsAmf0Any* ensure_property_string(std::string name);
175 virtual SrsAmf0Any* ensure_property_number(std::string name); 180 virtual SrsAmf0Any* ensure_property_number(std::string name);
  181 +
  182 + virtual void copy(__SrsUnSortedHashtable* src);
176 }; 183 };
177 184
178 /** 185 /**
@@ -191,6 +198,7 @@ public: @@ -191,6 +198,7 @@ public:
191 virtual int total_size(); 198 virtual int total_size();
192 virtual int read(SrsStream* stream); 199 virtual int read(SrsStream* stream);
193 virtual int write(SrsStream* stream); 200 virtual int write(SrsStream* stream);
  201 + virtual SrsAmf0Any* copy();
194 }; 202 };
195 203
196 /** 204 /**
@@ -310,6 +318,13 @@ SrsAmf0StrictArray* SrsAmf0Any::to_strict_array() @@ -310,6 +318,13 @@ SrsAmf0StrictArray* SrsAmf0Any::to_strict_array()
310 return p; 318 return p;
311 } 319 }
312 320
  321 +void SrsAmf0Any::set_number(double value)
  322 +{
  323 + __SrsAmf0Number* p = dynamic_cast<__SrsAmf0Number*>(this);
  324 + srs_assert(p != NULL);
  325 + p->value = value;
  326 +}
  327 +
313 bool SrsAmf0Any::is_object_eof() 328 bool SrsAmf0Any::is_object_eof()
314 { 329 {
315 return marker == RTMP_AMF0_ObjectEnd; 330 return marker == RTMP_AMF0_ObjectEnd;
@@ -433,13 +448,7 @@ __SrsUnSortedHashtable::__SrsUnSortedHashtable() @@ -433,13 +448,7 @@ __SrsUnSortedHashtable::__SrsUnSortedHashtable()
433 448
434 __SrsUnSortedHashtable::~__SrsUnSortedHashtable() 449 __SrsUnSortedHashtable::~__SrsUnSortedHashtable()
435 { 450 {
436 - std::vector<SrsAmf0ObjectPropertyType>::iterator it;  
437 - for (it = properties.begin(); it != properties.end(); ++it) {  
438 - SrsAmf0ObjectPropertyType& elem = *it;  
439 - SrsAmf0Any* any = elem.second;  
440 - srs_freep(any);  
441 - }  
442 - properties.clear(); 451 + clear();
443 } 452 }
444 453
445 int __SrsUnSortedHashtable::count() 454 int __SrsUnSortedHashtable::count()
@@ -449,6 +458,12 @@ int __SrsUnSortedHashtable::count() @@ -449,6 +458,12 @@ int __SrsUnSortedHashtable::count()
449 458
450 void __SrsUnSortedHashtable::clear() 459 void __SrsUnSortedHashtable::clear()
451 { 460 {
  461 + std::vector<SrsAmf0ObjectPropertyType>::iterator it;
  462 + for (it = properties.begin(); it != properties.end(); ++it) {
  463 + SrsAmf0ObjectPropertyType& elem = *it;
  464 + SrsAmf0Any* any = elem.second;
  465 + srs_freep(any);
  466 + }
452 properties.clear(); 467 properties.clear();
453 } 468 }
454 469
@@ -543,6 +558,17 @@ SrsAmf0Any* __SrsUnSortedHashtable::ensure_property_number(string name) @@ -543,6 +558,17 @@ SrsAmf0Any* __SrsUnSortedHashtable::ensure_property_number(string name)
543 return prop; 558 return prop;
544 } 559 }
545 560
  561 +void __SrsUnSortedHashtable::copy(__SrsUnSortedHashtable* src)
  562 +{
  563 + std::vector<SrsAmf0ObjectPropertyType>::iterator it;
  564 + for (it = src->properties.begin(); it != src->properties.end(); ++it) {
  565 + SrsAmf0ObjectPropertyType& elem = *it;
  566 + std::string key = elem.first;
  567 + SrsAmf0Any* any = elem.second;
  568 + set(key, any->copy());
  569 + }
  570 +}
  571 +
546 __SrsAmf0ObjectEOF::__SrsAmf0ObjectEOF() 572 __SrsAmf0ObjectEOF::__SrsAmf0ObjectEOF()
547 { 573 {
548 marker = RTMP_AMF0_ObjectEnd; 574 marker = RTMP_AMF0_ObjectEnd;
@@ -623,6 +649,11 @@ int __SrsAmf0ObjectEOF::write(SrsStream* stream) @@ -623,6 +649,11 @@ int __SrsAmf0ObjectEOF::write(SrsStream* stream)
623 return ret; 649 return ret;
624 } 650 }
625 651
  652 +SrsAmf0Any* __SrsAmf0ObjectEOF::copy()
  653 +{
  654 + return new __SrsAmf0ObjectEOF();
  655 +}
  656 +
626 SrsAmf0Object::SrsAmf0Object() 657 SrsAmf0Object::SrsAmf0Object()
627 { 658 {
628 properties = new __SrsUnSortedHashtable(); 659 properties = new __SrsUnSortedHashtable();
@@ -750,6 +781,13 @@ int SrsAmf0Object::write(SrsStream* stream) @@ -750,6 +781,13 @@ int SrsAmf0Object::write(SrsStream* stream)
750 return ret; 781 return ret;
751 } 782 }
752 783
  784 +SrsAmf0Any* SrsAmf0Object::copy()
  785 +{
  786 + SrsAmf0Object* copy = new SrsAmf0Object();
  787 + copy->properties->copy(properties);
  788 + return copy;
  789 +}
  790 +
753 int SrsAmf0Object::count() 791 int SrsAmf0Object::count()
754 { 792 {
755 return properties->count(); 793 return properties->count();
@@ -792,6 +830,7 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_number(string name) @@ -792,6 +830,7 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_number(string name)
792 830
793 SrsAmf0EcmaArray::SrsAmf0EcmaArray() 831 SrsAmf0EcmaArray::SrsAmf0EcmaArray()
794 { 832 {
  833 + _count = 0;
795 properties = new __SrsUnSortedHashtable(); 834 properties = new __SrsUnSortedHashtable();
796 eof = new __SrsAmf0ObjectEOF(); 835 eof = new __SrsAmf0ObjectEOF();
797 marker = RTMP_AMF0_EcmaArray; 836 marker = RTMP_AMF0_EcmaArray;
@@ -937,6 +976,14 @@ int SrsAmf0EcmaArray::write(SrsStream* stream) @@ -937,6 +976,14 @@ int SrsAmf0EcmaArray::write(SrsStream* stream)
937 return ret; 976 return ret;
938 } 977 }
939 978
  979 +SrsAmf0Any* SrsAmf0EcmaArray::copy()
  980 +{
  981 + SrsAmf0EcmaArray* copy = new SrsAmf0EcmaArray();
  982 + copy->properties->copy(properties);
  983 + copy->_count = _count;
  984 + return copy;
  985 +}
  986 +
940 void SrsAmf0EcmaArray::clear() 987 void SrsAmf0EcmaArray::clear()
941 { 988 {
942 properties->clear(); 989 properties->clear();
@@ -1097,6 +1144,20 @@ int SrsAmf0StrictArray::write(SrsStream* stream) @@ -1097,6 +1144,20 @@ int SrsAmf0StrictArray::write(SrsStream* stream)
1097 return ret; 1144 return ret;
1098 } 1145 }
1099 1146
  1147 +SrsAmf0Any* SrsAmf0StrictArray::copy()
  1148 +{
  1149 + SrsAmf0StrictArray* copy = new SrsAmf0StrictArray();
  1150 +
  1151 + std::vector<SrsAmf0Any*>::iterator it;
  1152 + for (it = properties.begin(); it != properties.end(); ++it) {
  1153 + SrsAmf0Any* any = *it;
  1154 + copy->append(any->copy());
  1155 + }
  1156 +
  1157 + copy->_count = _count;
  1158 + return copy;
  1159 +}
  1160 +
1100 void SrsAmf0StrictArray::clear() 1161 void SrsAmf0StrictArray::clear()
1101 { 1162 {
1102 properties.clear(); 1163 properties.clear();
@@ -1116,6 +1177,7 @@ SrsAmf0Any* SrsAmf0StrictArray::at(int index) @@ -1116,6 +1177,7 @@ SrsAmf0Any* SrsAmf0StrictArray::at(int index)
1116 void SrsAmf0StrictArray::append(SrsAmf0Any* any) 1177 void SrsAmf0StrictArray::append(SrsAmf0Any* any)
1117 { 1178 {
1118 properties.push_back(any); 1179 properties.push_back(any);
  1180 + _count = (int32_t)properties.size();
1119 } 1181 }
1120 1182
1121 int SrsAmf0Size::utf8(string value) 1183 int SrsAmf0Size::utf8(string value)
@@ -1216,6 +1278,12 @@ int __SrsAmf0String::write(SrsStream* stream) @@ -1216,6 +1278,12 @@ int __SrsAmf0String::write(SrsStream* stream)
1216 return srs_amf0_write_string(stream, value); 1278 return srs_amf0_write_string(stream, value);
1217 } 1279 }
1218 1280
  1281 +SrsAmf0Any* __SrsAmf0String::copy()
  1282 +{
  1283 + __SrsAmf0String* copy = new __SrsAmf0String(value.c_str());
  1284 + return copy;
  1285 +}
  1286 +
1219 __SrsAmf0Boolean::__SrsAmf0Boolean(bool _value) 1287 __SrsAmf0Boolean::__SrsAmf0Boolean(bool _value)
1220 { 1288 {
1221 marker = RTMP_AMF0_Boolean; 1289 marker = RTMP_AMF0_Boolean;
@@ -1241,6 +1309,12 @@ int __SrsAmf0Boolean::write(SrsStream* stream) @@ -1241,6 +1309,12 @@ int __SrsAmf0Boolean::write(SrsStream* stream)
1241 return srs_amf0_write_boolean(stream, value); 1309 return srs_amf0_write_boolean(stream, value);
1242 } 1310 }
1243 1311
  1312 +SrsAmf0Any* __SrsAmf0Boolean::copy()
  1313 +{
  1314 + __SrsAmf0Boolean* copy = new __SrsAmf0Boolean(value);
  1315 + return copy;
  1316 +}
  1317 +
1244 __SrsAmf0Number::__SrsAmf0Number(double _value) 1318 __SrsAmf0Number::__SrsAmf0Number(double _value)
1245 { 1319 {
1246 marker = RTMP_AMF0_Number; 1320 marker = RTMP_AMF0_Number;
@@ -1266,6 +1340,12 @@ int __SrsAmf0Number::write(SrsStream* stream) @@ -1266,6 +1340,12 @@ int __SrsAmf0Number::write(SrsStream* stream)
1266 return srs_amf0_write_number(stream, value); 1340 return srs_amf0_write_number(stream, value);
1267 } 1341 }
1268 1342
  1343 +SrsAmf0Any* __SrsAmf0Number::copy()
  1344 +{
  1345 + __SrsAmf0Number* copy = new __SrsAmf0Number(value);
  1346 + return copy;
  1347 +}
  1348 +
1269 __SrsAmf0Null::__SrsAmf0Null() 1349 __SrsAmf0Null::__SrsAmf0Null()
1270 { 1350 {
1271 marker = RTMP_AMF0_Null; 1351 marker = RTMP_AMF0_Null;
@@ -1290,6 +1370,12 @@ int __SrsAmf0Null::write(SrsStream* stream) @@ -1290,6 +1370,12 @@ int __SrsAmf0Null::write(SrsStream* stream)
1290 return srs_amf0_write_null(stream); 1370 return srs_amf0_write_null(stream);
1291 } 1371 }
1292 1372
  1373 +SrsAmf0Any* __SrsAmf0Null::copy()
  1374 +{
  1375 + __SrsAmf0Null* copy = new __SrsAmf0Null();
  1376 + return copy;
  1377 +}
  1378 +
1293 __SrsAmf0Undefined::__SrsAmf0Undefined() 1379 __SrsAmf0Undefined::__SrsAmf0Undefined()
1294 { 1380 {
1295 marker = RTMP_AMF0_Undefined; 1381 marker = RTMP_AMF0_Undefined;
@@ -1314,6 +1400,12 @@ int __SrsAmf0Undefined::write(SrsStream* stream) @@ -1314,6 +1400,12 @@ int __SrsAmf0Undefined::write(SrsStream* stream)
1314 return srs_amf0_write_undefined(stream); 1400 return srs_amf0_write_undefined(stream);
1315 } 1401 }
1316 1402
  1403 +SrsAmf0Any* __SrsAmf0Undefined::copy()
  1404 +{
  1405 + __SrsAmf0Undefined* copy = new __SrsAmf0Undefined();
  1406 + return copy;
  1407 +}
  1408 +
1317 int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue) 1409 int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any** ppvalue)
1318 { 1410 {
1319 int ret = ERROR_SUCCESS; 1411 int ret = ERROR_SUCCESS;
@@ -63,6 +63,11 @@ class __SrsAmf0ObjectEOF; @@ -63,6 +63,11 @@ class __SrsAmf0ObjectEOF;
63 // SrsAmf0Object* obj = SrsAmf0Any::object(); 63 // SrsAmf0Object* obj = SrsAmf0Any::object();
64 // 5. SrsAmf0EcmaArray: create the amf0 ecma array. 64 // 5. SrsAmf0EcmaArray: create the amf0 ecma array.
65 // SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array(); 65 // SrsAmf0EcmaArray* arr = SrsAmf0Any::ecma_array();
  66 +// 6. SrsAmf0Any: set basic type value
  67 +// SrsAmf0Any* pany = ...
  68 +// if (pany->is_number()) {
  69 +// pany->set_number(100.1);
  70 +// }
66 // 71 //
67 // please carefully the size and count of amf0 any: 72 // please carefully the size and count of amf0 any:
68 // 1. total_size(): the total memory size the object wrote to buffer. 73 // 1. total_size(): the total memory size the object wrote to buffer.
@@ -131,6 +136,12 @@ public: @@ -131,6 +136,12 @@ public:
131 virtual SrsAmf0StrictArray* to_strict_array(); 136 virtual SrsAmf0StrictArray* to_strict_array();
132 public: 137 public:
133 /** 138 /**
  139 + * set the number of any when is_number() indicates true.
  140 + * user must ensure the type is a number, or assert failed.
  141 + */
  142 + virtual void set_number(double value);
  143 +public:
  144 + /**
134 * get the size of amf0 any, including the marker size. 145 * get the size of amf0 any, including the marker size.
135 */ 146 */
136 virtual int total_size() = 0; 147 virtual int total_size() = 0;
@@ -139,6 +150,7 @@ public: @@ -139,6 +150,7 @@ public:
139 */ 150 */
140 virtual int read(SrsStream* stream) = 0; 151 virtual int read(SrsStream* stream) = 0;
141 virtual int write(SrsStream* stream) = 0; 152 virtual int write(SrsStream* stream) = 0;
  153 + virtual SrsAmf0Any* copy() = 0;
142 public: 154 public:
143 static SrsAmf0Any* str(const char* value = NULL); 155 static SrsAmf0Any* str(const char* value = NULL);
144 static SrsAmf0Any* boolean(bool value = false); 156 static SrsAmf0Any* boolean(bool value = false);
@@ -175,6 +187,7 @@ public: @@ -175,6 +187,7 @@ public:
175 virtual int total_size(); 187 virtual int total_size();
176 virtual int read(SrsStream* stream); 188 virtual int read(SrsStream* stream);
177 virtual int write(SrsStream* stream); 189 virtual int write(SrsStream* stream);
  190 + virtual SrsAmf0Any* copy();
178 191
179 public: 192 public:
180 virtual int count(); 193 virtual int count();
@@ -215,6 +228,7 @@ public: @@ -215,6 +228,7 @@ public:
215 virtual int total_size(); 228 virtual int total_size();
216 virtual int read(SrsStream* stream); 229 virtual int read(SrsStream* stream);
217 virtual int write(SrsStream* stream); 230 virtual int write(SrsStream* stream);
  231 + virtual SrsAmf0Any* copy();
218 232
219 public: 233 public:
220 virtual void clear(); 234 virtual void clear();
@@ -254,6 +268,7 @@ public: @@ -254,6 +268,7 @@ public:
254 virtual int total_size(); 268 virtual int total_size();
255 virtual int read(SrsStream* stream); 269 virtual int read(SrsStream* stream);
256 virtual int write(SrsStream* stream); 270 virtual int write(SrsStream* stream);
  271 + virtual SrsAmf0Any* copy();
257 272
258 public: 273 public:
259 virtual void clear(); 274 virtual void clear();
@@ -3173,10 +3173,9 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream) @@ -3173,10 +3173,9 @@ int SrsOnMetaDataPacket::decode(SrsStream* stream)
3173 3173
3174 // if ecma array, copy to object. 3174 // if ecma array, copy to object.
3175 for (int i = 0; i < arr->count(); i++) { 3175 for (int i = 0; i < arr->count(); i++) {
3176 - metadata->set(arr->key_at(i), arr->value_at(i)); 3176 + metadata->set(arr->key_at(i), arr->value_at(i)->copy());
3177 } 3177 }
3178 3178
3179 - arr->clear();  
3180 srs_info("decode metadata array success"); 3179 srs_info("decode metadata array success");
3181 } 3180 }
3182 3181