正在显示
6 个修改的文件
包含
344 行增加
和
26 行删除
| @@ -54,6 +54,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -54,6 +54,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 54 | #define RTMP_AMF0_Invalid 0x3F | 54 | #define RTMP_AMF0_Invalid 0x3F |
| 55 | 55 | ||
| 56 | int srs_amf0_get_object_eof_size(); | 56 | int srs_amf0_get_object_eof_size(); |
| 57 | +int srs_amf0_get_any_size(SrsAmf0Any* value); | ||
| 57 | int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*&); | 58 | int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*&); |
| 58 | int srs_amf0_write_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*); | 59 | int srs_amf0_write_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*); |
| 59 | int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value); | 60 | int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value); |
| @@ -88,43 +89,51 @@ bool SrsAmf0Any::is_object() | @@ -88,43 +89,51 @@ bool SrsAmf0Any::is_object() | ||
| 88 | return marker == RTMP_AMF0_Object; | 89 | return marker == RTMP_AMF0_Object; |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 92 | +bool SrsAmf0Any::is_ecma_array() | ||
| 93 | +{ | ||
| 94 | + return marker == RTMP_AMF0_EcmaArray; | ||
| 95 | +} | ||
| 96 | + | ||
| 91 | bool SrsAmf0Any::is_object_eof() | 97 | bool SrsAmf0Any::is_object_eof() |
| 92 | { | 98 | { |
| 93 | return marker == RTMP_AMF0_ObjectEnd; | 99 | return marker == RTMP_AMF0_ObjectEnd; |
| 94 | } | 100 | } |
| 95 | 101 | ||
| 96 | -SrsAmf0String::SrsAmf0String() | 102 | +SrsAmf0String::SrsAmf0String(const char* _value) |
| 97 | { | 103 | { |
| 98 | marker = RTMP_AMF0_String; | 104 | marker = RTMP_AMF0_String; |
| 105 | + if (_value) { | ||
| 106 | + value = _value; | ||
| 107 | + } | ||
| 99 | } | 108 | } |
| 100 | 109 | ||
| 101 | SrsAmf0String::~SrsAmf0String() | 110 | SrsAmf0String::~SrsAmf0String() |
| 102 | { | 111 | { |
| 103 | } | 112 | } |
| 104 | 113 | ||
| 105 | -SrsAmf0Boolean::SrsAmf0Boolean() | 114 | +SrsAmf0Boolean::SrsAmf0Boolean(bool _value) |
| 106 | { | 115 | { |
| 107 | marker = RTMP_AMF0_Boolean; | 116 | marker = RTMP_AMF0_Boolean; |
| 108 | - value = false; | 117 | + value = _value; |
| 109 | } | 118 | } |
| 110 | 119 | ||
| 111 | SrsAmf0Boolean::~SrsAmf0Boolean() | 120 | SrsAmf0Boolean::~SrsAmf0Boolean() |
| 112 | { | 121 | { |
| 113 | } | 122 | } |
| 114 | 123 | ||
| 115 | -SrsAmf0Number::SrsAmf0Number() | 124 | +SrsAmf0Number::SrsAmf0Number(double _value) |
| 116 | { | 125 | { |
| 117 | marker = RTMP_AMF0_Number; | 126 | marker = RTMP_AMF0_Number; |
| 118 | - value = 0; | 127 | + value = _value; |
| 119 | } | 128 | } |
| 120 | 129 | ||
| 121 | SrsAmf0Number::~SrsAmf0Number() | 130 | SrsAmf0Number::~SrsAmf0Number() |
| 122 | { | 131 | { |
| 123 | - marker = RTMP_AMF0_ObjectEnd; | ||
| 124 | } | 132 | } |
| 125 | 133 | ||
| 126 | SrsAmf0ObjectEOF::SrsAmf0ObjectEOF() | 134 | SrsAmf0ObjectEOF::SrsAmf0ObjectEOF() |
| 127 | { | 135 | { |
| 136 | + marker = RTMP_AMF0_ObjectEnd; | ||
| 128 | utf8_empty = 0x00; | 137 | utf8_empty = 0x00; |
| 129 | } | 138 | } |
| 130 | 139 | ||
| @@ -173,6 +182,47 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name) | @@ -173,6 +182,47 @@ SrsAmf0Any* SrsAmf0Object::ensure_property_string(std::string name) | ||
| 173 | return prop; | 182 | return prop; |
| 174 | } | 183 | } |
| 175 | 184 | ||
| 185 | +SrsASrsAmf0EcmaArray::SrsASrsAmf0EcmaArray() | ||
| 186 | +{ | ||
| 187 | + marker = RTMP_AMF0_EcmaArray; | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +SrsASrsAmf0EcmaArray::~SrsASrsAmf0EcmaArray() | ||
| 191 | +{ | ||
| 192 | + std::map<std::string, SrsAmf0Any*>::iterator it; | ||
| 193 | + for (it = properties.begin(); it != properties.end(); ++it) { | ||
| 194 | + SrsAmf0Any* any = it->second; | ||
| 195 | + delete any; | ||
| 196 | + } | ||
| 197 | + properties.clear(); | ||
| 198 | +} | ||
| 199 | + | ||
| 200 | +SrsAmf0Any* SrsASrsAmf0EcmaArray::get_property(std::string name) | ||
| 201 | +{ | ||
| 202 | + std::map<std::string, SrsAmf0Any*>::iterator it; | ||
| 203 | + | ||
| 204 | + if ((it = properties.find(name)) == properties.end()) { | ||
| 205 | + return NULL; | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + return it->second; | ||
| 209 | +} | ||
| 210 | + | ||
| 211 | +SrsAmf0Any* SrsASrsAmf0EcmaArray::ensure_property_string(std::string name) | ||
| 212 | +{ | ||
| 213 | + SrsAmf0Any* prop = get_property(name); | ||
| 214 | + | ||
| 215 | + if (!prop) { | ||
| 216 | + return NULL; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + if (!prop->is_string()) { | ||
| 220 | + return NULL; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + return prop; | ||
| 224 | +} | ||
| 225 | + | ||
| 176 | int srs_amf0_read_utf8(SrsStream* stream, std::string& value) | 226 | int srs_amf0_read_utf8(SrsStream* stream, std::string& value) |
| 177 | { | 227 | { |
| 178 | int ret = ERROR_SUCCESS; | 228 | int ret = ERROR_SUCCESS; |
| @@ -481,6 +531,14 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) | @@ -481,6 +531,14 @@ int srs_amf0_read_any(SrsStream* stream, SrsAmf0Any*& value) | ||
| 481 | value = p; | 531 | value = p; |
| 482 | return ret; | 532 | return ret; |
| 483 | } | 533 | } |
| 534 | + case RTMP_AMF0_EcmaArray: { | ||
| 535 | + SrsASrsAmf0EcmaArray* p = NULL; | ||
| 536 | + if ((ret = srs_amf0_read_ecma_array(stream, p)) != ERROR_SUCCESS) { | ||
| 537 | + return ret; | ||
| 538 | + } | ||
| 539 | + value = p; | ||
| 540 | + return ret; | ||
| 541 | + } | ||
| 484 | case RTMP_AMF0_Invalid: | 542 | case RTMP_AMF0_Invalid: |
| 485 | default: { | 543 | default: { |
| 486 | ret = ERROR_RTMP_AMF0_INVALID; | 544 | ret = ERROR_RTMP_AMF0_INVALID; |
| @@ -518,6 +576,10 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | @@ -518,6 +576,10 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | ||
| 518 | SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value); | 576 | SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value); |
| 519 | return srs_amf0_write_object(stream, p); | 577 | return srs_amf0_write_object(stream, p); |
| 520 | } | 578 | } |
| 579 | + case RTMP_AMF0_EcmaArray: { | ||
| 580 | + SrsASrsAmf0EcmaArray* p = srs_amf0_convert<SrsASrsAmf0EcmaArray>(value); | ||
| 581 | + return srs_amf0_write_ecma_array(stream, p); | ||
| 582 | + } | ||
| 521 | case RTMP_AMF0_Invalid: | 583 | case RTMP_AMF0_Invalid: |
| 522 | default: { | 584 | default: { |
| 523 | ret = ERROR_RTMP_AMF0_INVALID; | 585 | ret = ERROR_RTMP_AMF0_INVALID; |
| @@ -529,6 +591,52 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | @@ -529,6 +591,52 @@ int srs_amf0_write_any(SrsStream* stream, SrsAmf0Any* value) | ||
| 529 | return ret; | 591 | return ret; |
| 530 | } | 592 | } |
| 531 | 593 | ||
| 594 | +int srs_amf0_get_any_size(SrsAmf0Any* value) | ||
| 595 | +{ | ||
| 596 | + if (!value) { | ||
| 597 | + return 0; | ||
| 598 | + } | ||
| 599 | + | ||
| 600 | + int size = 0; | ||
| 601 | + | ||
| 602 | + switch (value->marker) { | ||
| 603 | + case RTMP_AMF0_String: { | ||
| 604 | + SrsAmf0String* p = srs_amf0_convert<SrsAmf0String>(value); | ||
| 605 | + size += srs_amf0_get_string_size(p->value); | ||
| 606 | + break; | ||
| 607 | + } | ||
| 608 | + case RTMP_AMF0_Boolean: { | ||
| 609 | + size += srs_amf0_get_boolean_size(); | ||
| 610 | + break; | ||
| 611 | + } | ||
| 612 | + case RTMP_AMF0_Number: { | ||
| 613 | + size += srs_amf0_get_number_size(); | ||
| 614 | + break; | ||
| 615 | + } | ||
| 616 | + case RTMP_AMF0_ObjectEnd: { | ||
| 617 | + size += srs_amf0_get_object_eof_size(); | ||
| 618 | + break; | ||
| 619 | + } | ||
| 620 | + case RTMP_AMF0_Object: { | ||
| 621 | + SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value); | ||
| 622 | + size += srs_amf0_get_object_size(p); | ||
| 623 | + break; | ||
| 624 | + } | ||
| 625 | + case RTMP_AMF0_EcmaArray: { | ||
| 626 | + SrsASrsAmf0EcmaArray* p = srs_amf0_convert<SrsASrsAmf0EcmaArray>(value); | ||
| 627 | + size += srs_amf0_get_ecma_array_size(p); | ||
| 628 | + break; | ||
| 629 | + } | ||
| 630 | + default: { | ||
| 631 | + // TOOD: other AMF0 types. | ||
| 632 | + srs_warn("ignore unkown AMF0 type size."); | ||
| 633 | + break; | ||
| 634 | + } | ||
| 635 | + } | ||
| 636 | + | ||
| 637 | + return size; | ||
| 638 | +} | ||
| 639 | + | ||
| 532 | int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*& value) | 640 | int srs_amf0_read_object_eof(SrsStream* stream, SrsAmf0ObjectEOF*& value) |
| 533 | { | 641 | { |
| 534 | int ret = ERROR_SUCCESS; | 642 | int ret = ERROR_SUCCESS; |
| @@ -699,6 +807,125 @@ int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value) | @@ -699,6 +807,125 @@ int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value) | ||
| 699 | return ret; | 807 | return ret; |
| 700 | } | 808 | } |
| 701 | 809 | ||
| 810 | +int srs_amf0_read_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray*& value) | ||
| 811 | +{ | ||
| 812 | + int ret = ERROR_SUCCESS; | ||
| 813 | + | ||
| 814 | + // marker | ||
| 815 | + if (!stream->require(1)) { | ||
| 816 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
| 817 | + srs_error("amf0 read ecma_array marker failed. ret=%d", ret); | ||
| 818 | + return ret; | ||
| 819 | + } | ||
| 820 | + | ||
| 821 | + char marker = stream->read_1bytes(); | ||
| 822 | + if (marker != RTMP_AMF0_EcmaArray) { | ||
| 823 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
| 824 | + srs_error("amf0 check ecma_array marker failed. " | ||
| 825 | + "marker=%#x, required=%#x, ret=%d", marker, RTMP_AMF0_Object, ret); | ||
| 826 | + return ret; | ||
| 827 | + } | ||
| 828 | + srs_verbose("amf0 read ecma_array marker success"); | ||
| 829 | + | ||
| 830 | + // count | ||
| 831 | + if (!stream->require(4)) { | ||
| 832 | + ret = ERROR_RTMP_AMF0_DECODE; | ||
| 833 | + srs_error("amf0 read ecma_array count failed. ret=%d", ret); | ||
| 834 | + return ret; | ||
| 835 | + } | ||
| 836 | + | ||
| 837 | + int32_t count = stream->read_4bytes(); | ||
| 838 | + srs_verbose("amf0 read ecma_array count success. count=%d", count); | ||
| 839 | + | ||
| 840 | + // value | ||
| 841 | + value = new SrsASrsAmf0EcmaArray(); | ||
| 842 | + value->count = count; | ||
| 843 | + | ||
| 844 | + while (!stream->empty()) { | ||
| 845 | + // property-name: utf8 string | ||
| 846 | + std::string property_name; | ||
| 847 | + if ((ret =srs_amf0_read_utf8(stream, property_name)) != ERROR_SUCCESS) { | ||
| 848 | + srs_error("amf0 ecma_array read property name failed. ret=%d", ret); | ||
| 849 | + return ret; | ||
| 850 | + } | ||
| 851 | + // property-value: any | ||
| 852 | + SrsAmf0Any* property_value = NULL; | ||
| 853 | + if ((ret = srs_amf0_read_any(stream, property_value)) != ERROR_SUCCESS) { | ||
| 854 | + srs_error("amf0 ecma_array read property_value failed. " | ||
| 855 | + "name=%s, ret=%d", property_name.c_str(), ret); | ||
| 856 | + return ret; | ||
| 857 | + } | ||
| 858 | + | ||
| 859 | + // AMF0 Object EOF. | ||
| 860 | + if (property_name.empty() || !property_value || property_value->is_object_eof()) { | ||
| 861 | + if (property_value) { | ||
| 862 | + delete property_value; | ||
| 863 | + } | ||
| 864 | + srs_info("amf0 read ecma_array EOF."); | ||
| 865 | + break; | ||
| 866 | + } | ||
| 867 | + | ||
| 868 | + // add property | ||
| 869 | + value->properties[property_name] = property_value; | ||
| 870 | + } | ||
| 871 | + | ||
| 872 | + return ret; | ||
| 873 | +} | ||
| 874 | +int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* value) | ||
| 875 | +{ | ||
| 876 | + int ret = ERROR_SUCCESS; | ||
| 877 | + | ||
| 878 | + srs_assert(value != NULL); | ||
| 879 | + | ||
| 880 | + // marker | ||
| 881 | + if (!stream->require(1)) { | ||
| 882 | + ret = ERROR_RTMP_AMF0_ENCODE; | ||
| 883 | + srs_error("amf0 write ecma_array marker failed. ret=%d", ret); | ||
| 884 | + return ret; | ||
| 885 | + } | ||
| 886 | + | ||
| 887 | + stream->write_1bytes(RTMP_AMF0_EcmaArray); | ||
| 888 | + srs_verbose("amf0 write ecma_array marker success"); | ||
| 889 | + | ||
| 890 | + // count | ||
| 891 | + if (!stream->require(4)) { | ||
| 892 | + ret = ERROR_RTMP_AMF0_ENCODE; | ||
| 893 | + srs_error("amf0 write ecma_array count failed. ret=%d", ret); | ||
| 894 | + return ret; | ||
| 895 | + } | ||
| 896 | + | ||
| 897 | + stream->write_4bytes(value->count); | ||
| 898 | + srs_verbose("amf0 write ecma_array count success. count=%d", value->count); | ||
| 899 | + | ||
| 900 | + // value | ||
| 901 | + std::map<std::string, SrsAmf0Any*>::iterator it; | ||
| 902 | + for (it = value->properties.begin(); it != value->properties.end(); ++it) { | ||
| 903 | + std::string name = it->first; | ||
| 904 | + SrsAmf0Any* any = it->second; | ||
| 905 | + | ||
| 906 | + if ((ret = srs_amf0_write_utf8(stream, name)) != ERROR_SUCCESS) { | ||
| 907 | + srs_error("write ecma_array property name failed. ret=%d", ret); | ||
| 908 | + return ret; | ||
| 909 | + } | ||
| 910 | + | ||
| 911 | + if ((ret = srs_amf0_write_any(stream, any)) != ERROR_SUCCESS) { | ||
| 912 | + srs_error("write ecma_array property value failed. ret=%d", ret); | ||
| 913 | + return ret; | ||
| 914 | + } | ||
| 915 | + | ||
| 916 | + srs_verbose("write amf0 property success. name=%s", name.c_str()); | ||
| 917 | + } | ||
| 918 | + | ||
| 919 | + if ((ret = srs_amf0_write_object_eof(stream, &value->eof)) != ERROR_SUCCESS) { | ||
| 920 | + srs_error("write ecma_array eof failed. ret=%d", ret); | ||
| 921 | + return ret; | ||
| 922 | + } | ||
| 923 | + | ||
| 924 | + srs_verbose("write ecma_array object success."); | ||
| 925 | + | ||
| 926 | + return ret; | ||
| 927 | +} | ||
| 928 | + | ||
| 702 | int srs_amf0_get_utf8_size(std::string value) | 929 | int srs_amf0_get_utf8_size(std::string value) |
| 703 | { | 930 | { |
| 704 | return 2 + value.length(); | 931 | return 2 + value.length(); |
| @@ -733,21 +960,29 @@ int srs_amf0_get_object_size(SrsAmf0Object* obj) | @@ -733,21 +960,29 @@ int srs_amf0_get_object_size(SrsAmf0Object* obj) | ||
| 733 | SrsAmf0Any* value = it->second; | 960 | SrsAmf0Any* value = it->second; |
| 734 | 961 | ||
| 735 | size += srs_amf0_get_utf8_size(name); | 962 | size += srs_amf0_get_utf8_size(name); |
| 963 | + size += srs_amf0_get_any_size(value); | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + size += srs_amf0_get_object_eof_size(); | ||
| 967 | + | ||
| 968 | + return size; | ||
| 969 | +} | ||
| 970 | + | ||
| 971 | +int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr) | ||
| 972 | +{ | ||
| 973 | + if (!arr) { | ||
| 974 | + return 0; | ||
| 975 | + } | ||
| 976 | + | ||
| 977 | + int size = 1 + 4; | ||
| 978 | + | ||
| 979 | + std::map<std::string, SrsAmf0Any*>::iterator it; | ||
| 980 | + for (it = arr->properties.begin(); it != arr->properties.end(); ++it) { | ||
| 981 | + std::string name = it->first; | ||
| 982 | + SrsAmf0Any* value = it->second; | ||
| 736 | 983 | ||
| 737 | - if (value->is_boolean()) { | ||
| 738 | - size += srs_amf0_get_boolean_size(); | ||
| 739 | - } else if (value->is_number()) { | ||
| 740 | - size += srs_amf0_get_number_size(); | ||
| 741 | - } else if (value->is_string()) { | ||
| 742 | - SrsAmf0String* p = srs_amf0_convert<SrsAmf0String>(value); | ||
| 743 | - size += srs_amf0_get_string_size(p->value); | ||
| 744 | - } else if (value->is_object()) { | ||
| 745 | - SrsAmf0Object* p = srs_amf0_convert<SrsAmf0Object>(value); | ||
| 746 | - size += srs_amf0_get_object_size(p); | ||
| 747 | - } else { | ||
| 748 | - // TOOD: other AMF0 types. | ||
| 749 | - srs_warn("ignore unkown AMF0 type size."); | ||
| 750 | - } | 984 | + size += srs_amf0_get_utf8_size(name); |
| 985 | + size += srs_amf0_get_any_size(value); | ||
| 751 | } | 986 | } |
| 752 | 987 | ||
| 753 | size += srs_amf0_get_object_eof_size(); | 988 | size += srs_amf0_get_object_eof_size(); |
| @@ -56,6 +56,7 @@ struct SrsAmf0Any | @@ -56,6 +56,7 @@ struct SrsAmf0Any | ||
| 56 | virtual bool is_number(); | 56 | virtual bool is_number(); |
| 57 | virtual bool is_object(); | 57 | virtual bool is_object(); |
| 58 | virtual bool is_object_eof(); | 58 | virtual bool is_object_eof(); |
| 59 | + virtual bool is_ecma_array(); | ||
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | /** | 62 | /** |
| @@ -68,7 +69,7 @@ struct SrsAmf0String : public SrsAmf0Any | @@ -68,7 +69,7 @@ struct SrsAmf0String : public SrsAmf0Any | ||
| 68 | { | 69 | { |
| 69 | std::string value; | 70 | std::string value; |
| 70 | 71 | ||
| 71 | - SrsAmf0String(); | 72 | + SrsAmf0String(const char* _value = NULL); |
| 72 | virtual ~SrsAmf0String(); | 73 | virtual ~SrsAmf0String(); |
| 73 | }; | 74 | }; |
| 74 | 75 | ||
| @@ -83,7 +84,7 @@ struct SrsAmf0Boolean : public SrsAmf0Any | @@ -83,7 +84,7 @@ struct SrsAmf0Boolean : public SrsAmf0Any | ||
| 83 | { | 84 | { |
| 84 | bool value; | 85 | bool value; |
| 85 | 86 | ||
| 86 | - SrsAmf0Boolean(); | 87 | + SrsAmf0Boolean(bool _value = false); |
| 87 | virtual ~SrsAmf0Boolean(); | 88 | virtual ~SrsAmf0Boolean(); |
| 88 | }; | 89 | }; |
| 89 | 90 | ||
| @@ -97,7 +98,7 @@ struct SrsAmf0Number : public SrsAmf0Any | @@ -97,7 +98,7 @@ struct SrsAmf0Number : public SrsAmf0Any | ||
| 97 | { | 98 | { |
| 98 | double value; | 99 | double value; |
| 99 | 100 | ||
| 100 | - SrsAmf0Number(); | 101 | + SrsAmf0Number(double _value = 0.0); |
| 101 | virtual ~SrsAmf0Number(); | 102 | virtual ~SrsAmf0Number(); |
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| @@ -132,6 +133,25 @@ struct SrsAmf0Object : public SrsAmf0Any | @@ -132,6 +133,25 @@ struct SrsAmf0Object : public SrsAmf0Any | ||
| 132 | }; | 133 | }; |
| 133 | 134 | ||
| 134 | /** | 135 | /** |
| 136 | +* 2.10 ECMA Array Type | ||
| 137 | +* ecma-array-type = associative-count *(object-property) | ||
| 138 | +* associative-count = U32 | ||
| 139 | +* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker) | ||
| 140 | +*/ | ||
| 141 | +struct SrsASrsAmf0EcmaArray : public SrsAmf0Any | ||
| 142 | +{ | ||
| 143 | + int32_t count; | ||
| 144 | + std::map<std::string, SrsAmf0Any*> properties; | ||
| 145 | + SrsAmf0ObjectEOF eof; | ||
| 146 | + | ||
| 147 | + SrsASrsAmf0EcmaArray(); | ||
| 148 | + virtual ~SrsASrsAmf0EcmaArray(); | ||
| 149 | + | ||
| 150 | + virtual SrsAmf0Any* get_property(std::string name); | ||
| 151 | + virtual SrsAmf0Any* ensure_property_string(std::string name); | ||
| 152 | +}; | ||
| 153 | + | ||
| 154 | +/** | ||
| 135 | * read amf0 utf8 string from stream. | 155 | * read amf0 utf8 string from stream. |
| 136 | * 1.3.1 Strings and UTF-8 | 156 | * 1.3.1 Strings and UTF-8 |
| 137 | * UTF-8 = U16 *(UTF8-char) | 157 | * UTF-8 = U16 *(UTF8-char) |
| @@ -177,6 +197,16 @@ extern int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value); | @@ -177,6 +197,16 @@ extern int srs_amf0_read_object(SrsStream* stream, SrsAmf0Object*& value); | ||
| 177 | extern int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value); | 197 | extern int srs_amf0_write_object(SrsStream* stream, SrsAmf0Object* value); |
| 178 | 198 | ||
| 179 | /** | 199 | /** |
| 200 | +* read amf0 object from stream. | ||
| 201 | +* 2.10 ECMA Array Type | ||
| 202 | +* ecma-array-type = associative-count *(object-property) | ||
| 203 | +* associative-count = U32 | ||
| 204 | +* object-property = (UTF-8 value-type) | (UTF-8-empty object-end-marker) | ||
| 205 | +*/ | ||
| 206 | +extern int srs_amf0_read_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray*& value); | ||
| 207 | +extern int srs_amf0_write_ecma_array(SrsStream* stream, SrsASrsAmf0EcmaArray* value); | ||
| 208 | + | ||
| 209 | +/** | ||
| 180 | * get amf0 objects size. | 210 | * get amf0 objects size. |
| 181 | */ | 211 | */ |
| 182 | extern int srs_amf0_get_utf8_size(std::string value); | 212 | extern int srs_amf0_get_utf8_size(std::string value); |
| @@ -184,7 +214,8 @@ extern int srs_amf0_get_string_size(std::string value); | @@ -184,7 +214,8 @@ extern int srs_amf0_get_string_size(std::string value); | ||
| 184 | extern int srs_amf0_get_number_size(); | 214 | extern int srs_amf0_get_number_size(); |
| 185 | extern int srs_amf0_get_boolean_size(); | 215 | extern int srs_amf0_get_boolean_size(); |
| 186 | extern int srs_amf0_get_object_size(SrsAmf0Object* obj); | 216 | extern int srs_amf0_get_object_size(SrsAmf0Object* obj); |
| 187 | - | 217 | +extern int srs_amf0_get_ecma_array_size(SrsASrsAmf0EcmaArray* arr); |
| 218 | + | ||
| 188 | /** | 219 | /** |
| 189 | * convert the any to specified object. | 220 | * convert the any to specified object. |
| 190 | * @return T*, the converted object. never NULL. | 221 | * @return T*, the converted object. never NULL. |
| @@ -92,6 +92,12 @@ int SrsClient::do_cycle() | @@ -92,6 +92,12 @@ int SrsClient::do_cycle() | ||
| 92 | return ret; | 92 | return ret; |
| 93 | } | 93 | } |
| 94 | srs_verbose("set peer bandwidth success"); | 94 | srs_verbose("set peer bandwidth success"); |
| 95 | + | ||
| 96 | + if ((ret = rtmp->response_connect_app()) != ERROR_SUCCESS) { | ||
| 97 | + srs_error("response connect app failed. ret=%d", ret); | ||
| 98 | + return ret; | ||
| 99 | + } | ||
| 100 | + srs_verbose("response connect app success"); | ||
| 95 | 101 | ||
| 96 | return ret; | 102 | return ret; |
| 97 | } | 103 | } |
| @@ -1061,8 +1061,8 @@ SrsConnectAppResPacket::SrsConnectAppResPacket() | @@ -1061,8 +1061,8 @@ SrsConnectAppResPacket::SrsConnectAppResPacket() | ||
| 1061 | { | 1061 | { |
| 1062 | command_name = RTMP_AMF0_COMMAND_CONNECT; | 1062 | command_name = RTMP_AMF0_COMMAND_CONNECT; |
| 1063 | transaction_id = 1; | 1063 | transaction_id = 1; |
| 1064 | - props = NULL; | ||
| 1065 | - info = NULL; | 1064 | + props = new SrsAmf0Object(); |
| 1065 | + info = new SrsAmf0Object(); | ||
| 1066 | } | 1066 | } |
| 1067 | 1067 | ||
| 1068 | SrsConnectAppResPacket::~SrsConnectAppResPacket() | 1068 | SrsConnectAppResPacket::~SrsConnectAppResPacket() |
| @@ -30,6 +30,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -30,6 +30,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 30 | #include <srs_core_auto_free.hpp> | 30 | #include <srs_core_auto_free.hpp> |
| 31 | #include <srs_core_amf0.hpp> | 31 | #include <srs_core_amf0.hpp> |
| 32 | 32 | ||
| 33 | +/** | ||
| 34 | +* the signature for packets to client. | ||
| 35 | +*/ | ||
| 36 | +#define RTMP_SIG_FMS_VER "3,5,3,888" | ||
| 37 | +#define RTMP_SIG_AMF0_VER 3 | ||
| 38 | +#define RTMP_SIG_SRS_NAME "srs(simple rtmp server)" | ||
| 39 | +#define RTMP_SIG_SRS_URL "https://github.com/winlinvip/simple-rtmp-server" | ||
| 40 | +#define RTMP_SIG_SRS_VERSION "0.1" | ||
| 41 | + | ||
| 33 | int SrsRequest::discovery_app() | 42 | int SrsRequest::discovery_app() |
| 34 | { | 43 | { |
| 35 | int ret = ERROR_SUCCESS; | 44 | int ret = ERROR_SUCCESS; |
| @@ -205,3 +214,39 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | @@ -205,3 +214,39 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) | ||
| 205 | return ret; | 214 | return ret; |
| 206 | } | 215 | } |
| 207 | 216 | ||
| 217 | +int SrsRtmp::response_connect_app() | ||
| 218 | +{ | ||
| 219 | + int ret = ERROR_SUCCESS; | ||
| 220 | + | ||
| 221 | + SrsMessage* msg = new SrsMessage(); | ||
| 222 | + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket(); | ||
| 223 | + | ||
| 224 | + pkt->command_name = "_result"; | ||
| 225 | + | ||
| 226 | + pkt->props->properties["fmsVer"] = new SrsAmf0String("FMS/"RTMP_SIG_FMS_VER); | ||
| 227 | + pkt->props->properties["capabilities"] = new SrsAmf0Number(123); | ||
| 228 | + pkt->props->properties["mode"] = new SrsAmf0Number(1); | ||
| 229 | + | ||
| 230 | + pkt->info->properties["level"] = new SrsAmf0String("status"); | ||
| 231 | + pkt->info->properties["code"] = new SrsAmf0String("NetConnection.Connect.Success"); | ||
| 232 | + pkt->info->properties["description"] = new SrsAmf0String("Connection succeeded"); | ||
| 233 | + pkt->info->properties["objectEncoding"] = new SrsAmf0Number(RTMP_SIG_AMF0_VER); | ||
| 234 | + SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); | ||
| 235 | + pkt->info->properties["data"] = data; | ||
| 236 | + | ||
| 237 | + data->properties["version"] = new SrsAmf0String(RTMP_SIG_FMS_VER); | ||
| 238 | + data->properties["server"] = new SrsAmf0String(RTMP_SIG_SRS_NAME); | ||
| 239 | + data->properties["srs_url"] = new SrsAmf0String(RTMP_SIG_SRS_URL); | ||
| 240 | + data->properties["srs_version"] = new SrsAmf0String(RTMP_SIG_SRS_VERSION); | ||
| 241 | + | ||
| 242 | + msg->set_packet(pkt); | ||
| 243 | + | ||
| 244 | + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) { | ||
| 245 | + srs_error("send connect app response message failed. ret=%d", ret); | ||
| 246 | + return ret; | ||
| 247 | + } | ||
| 248 | + srs_info("send connect app response message success."); | ||
| 249 | + | ||
| 250 | + return ret; | ||
| 251 | +} | ||
| 252 | + |
| @@ -79,6 +79,7 @@ public: | @@ -79,6 +79,7 @@ public: | ||
| 79 | * using the Limit type field. | 79 | * using the Limit type field. |
| 80 | */ | 80 | */ |
| 81 | virtual int set_peer_bandwidth(int bandwidth, int type); | 81 | virtual int set_peer_bandwidth(int bandwidth, int type); |
| 82 | + virtual int response_connect_app(); | ||
| 82 | }; | 83 | }; |
| 83 | 84 | ||
| 84 | #endif | 85 | #endif |
-
请 注册 或 登录 后发表评论