winlin

add miss files. fix bug #60: support aggregate message

@@ -690,4 +690,4 @@ echo "" >> $SRS_AUTO_HEADERS_H @@ -690,4 +690,4 @@ echo "" >> $SRS_AUTO_HEADERS_H
690 ##################################################################################### 690 #####################################################################################
691 # generated the test script 691 # generated the test script
692 ##################################################################################### 692 #####################################################################################
693 -rm -rf ${SRS_OBJS}/srs.test && ln -sf `pwd`/scripts/test_configure.sh objs/srs.test 693 +rm -rf ${SRS_OBJS}/srs.test && ln -sf `pwd`/scripts/srs.test objs/srs.test
  1 +#!/usr/bin/python
  2 +'''
  3 +The MIT License (MIT)
  4 +
  5 +Copyright (c) 2013-2014 winlin
  6 +
  7 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  8 +this software and associated documentation files (the "Software"), to deal in
  9 +the Software without restriction, including without limitation the rights to
  10 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  11 +the Software, and to permit persons to whom the Software is furnished to do so,
  12 +subject to the following conditions:
  13 +
  14 +The above copyright notice and this permission notice shall be included in all
  15 +copies or substantial portions of the Software.
  16 +
  17 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  19 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  21 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23 +'''
  24 +
  25 +#################################################################################
  26 +# to stat the code and comments lines
  27 +#################################################################################
  28 +import sys, os, cs
  29 +from cs import info, trace
  30 +
  31 +if __name__ != "__main__":
  32 + print "donot support lib"
  33 + sys.exit(-1)
  34 +
  35 +filters="*.*pp,*.h,*.c,*.cc"
  36 +except_filters="utest,doc"
  37 +if len(sys.argv) <= 1:
  38 + print "to stat the code and comments lines"
  39 + print "Usage: python %s <dir> [filters] [except_filters]"%(sys.argv[0])
  40 + print " dir: the dir contains the files to stat"
  41 + print " filters: the file filters, default: *.*pp,*.h,*.c,*.cc"
  42 + print " filters: the except file filters, default: utest,doc"
  43 + print "Example:"
  44 + print " python %s src"%(sys.argv[0])
  45 + print " python %s src *.*pp,*.cc utest"%(sys.argv[0])
  46 + sys.exit(-1)
  47 +
  48 +dir = sys.argv[1]
  49 +if len(sys.argv) > 2:
  50 + filters = sys.argv[2]
  51 +if len(sys.argv) > 3:
  52 + except_filters = sys.argv[3]
  53 +info("stat dir:%s, filters:%s, except_filters:%s"%(dir, filters, except_filters))
  54 +
  55 +# filters to array
  56 +filters = filters.split(",")
  57 +except_filters = except_filters.split(",")
  58 +
  59 +# find src -name "*.*pp"|grep -v utest
  60 +(totals, stat_codes, commentss, stat_block_commentss, stat_line_commentss) = (0, 0, 0, 0, 0)
  61 +for filter in filters:
  62 + cmd = 'find %s -name "%s"'%(dir, filter)
  63 + for ef in except_filters:
  64 + cmd = '%s|%s'%(cmd, 'grep -v "%s"'%(ef))
  65 + cmd = "%s 2>&1"%(cmd)
  66 + info("scan dir, cmd:%s"%cmd)
  67 +
  68 + pipe = os.popen(cmd)
  69 + files = pipe.read()
  70 + info("scan dir, files:%s"%files)
  71 + pipe.close()
  72 +
  73 + files = files.split("\n")
  74 + for file in files:
  75 + file = file.strip()
  76 + if len(file) == 0:
  77 + continue;
  78 + info("start stat file:%s"%file)
  79 + (code, total, stat_code, comments, stat_block_comments, stat_line_comments, code_file) = cs.do_stat(file)
  80 + if code != 0:
  81 + continue;
  82 + totals += total
  83 + stat_codes += stat_code
  84 + commentss += comments
  85 + stat_block_commentss += stat_block_comments
  86 + stat_line_commentss += stat_line_comments
  87 +
  88 +if totals == 0:
  89 + trace("no code or comments found.")
  90 +else:
  91 + trace("total:%s code:%s comments:%s(%.2f%%) block:%s line:%s"%(
  92 + totals, stat_codes, commentss, commentss * 100.0 / totals, stat_block_commentss, stat_line_commentss
  93 + ))
  1 +#!/bin/bash
  2 +
  3 +bash scripts/test_configure.sh && ./objs/srs_utest
  4 +ret=$?; if [[ 0 -ne $ret ]]; then echo "configure test and utest failed."; exit $ret; fi
  5 +echo "configure test and utest success";
@@ -215,6 +215,15 @@ int SrsEdgeIngester::process_publish_message(SrsMessage* msg) @@ -215,6 +215,15 @@ int SrsEdgeIngester::process_publish_message(SrsMessage* msg)
215 } 215 }
216 } 216 }
217 217
  218 + // process aggregate packet
  219 + if (msg->header.is_aggregate()) {
  220 + if ((ret = source->on_aggregate(msg)) != ERROR_SUCCESS) {
  221 + srs_error("source process aggregate message failed. ret=%d", ret);
  222 + return ret;
  223 + }
  224 + return ret;
  225 + }
  226 +
218 // process onMetaData 227 // process onMetaData
219 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { 228 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
220 SrsPacket* pkt = NULL; 229 SrsPacket* pkt = NULL;
@@ -724,6 +724,15 @@ int SrsRtmpConn::process_publish_message(SrsSource* source, SrsMessage* msg, boo @@ -724,6 +724,15 @@ int SrsRtmpConn::process_publish_message(SrsSource* source, SrsMessage* msg, boo
724 return ret; 724 return ret;
725 } 725 }
726 726
  727 + // process aggregate packet
  728 + if (msg->header.is_aggregate()) {
  729 + if ((ret = source->on_aggregate(msg)) != ERROR_SUCCESS) {
  730 + srs_error("source process aggregate message failed. ret=%d", ret);
  731 + return ret;
  732 + }
  733 + return ret;
  734 + }
  735 +
727 // process onMetaData 736 // process onMetaData
728 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) { 737 if (msg->header.is_amf0_data() || msg->header.is_amf3_data()) {
729 SrsPacket* pkt = NULL; 738 SrsPacket* pkt = NULL;
@@ -469,6 +469,7 @@ SrsSource::SrsSource(SrsRequest* req) @@ -469,6 +469,7 @@ SrsSource::SrsSource(SrsRequest* req)
469 play_edge = new SrsPlayEdge(); 469 play_edge = new SrsPlayEdge();
470 publish_edge = new SrsPublishEdge(); 470 publish_edge = new SrsPublishEdge();
471 gop_cache = new SrsGopCache(); 471 gop_cache = new SrsGopCache();
  472 + aggregate_stream = new SrsStream();
472 473
473 _srs_config->subscribe(this); 474 _srs_config->subscribe(this);
474 atc = _srs_config->get_atc(_req->vhost); 475 atc = _srs_config->get_atc(_req->vhost);
@@ -498,6 +499,7 @@ SrsSource::~SrsSource() @@ -498,6 +499,7 @@ SrsSource::~SrsSource()
498 srs_freep(play_edge); 499 srs_freep(play_edge);
499 srs_freep(publish_edge); 500 srs_freep(publish_edge);
500 srs_freep(gop_cache); 501 srs_freep(gop_cache);
  502 + srs_freep(aggregate_stream);
501 503
502 #ifdef SRS_AUTO_HLS 504 #ifdef SRS_AUTO_HLS
503 srs_freep(hls); 505 srs_freep(hls);
@@ -1069,6 +1071,105 @@ int SrsSource::on_video(SrsMessage* video) @@ -1069,6 +1071,105 @@ int SrsSource::on_video(SrsMessage* video)
1069 return ret; 1071 return ret;
1070 } 1072 }
1071 1073
  1074 +int SrsSource::on_aggregate(SrsMessage* msg)
  1075 +{
  1076 + int ret = ERROR_SUCCESS;
  1077 +
  1078 + SrsStream* stream = aggregate_stream;
  1079 + if ((ret = stream->initialize((char*)msg->payload, msg->size)) != ERROR_SUCCESS) {
  1080 + return ret;
  1081 + }
  1082 +
  1083 + while (!stream->empty()) {
  1084 + if (!stream->require(1)) {
  1085 + ret = ERROR_RTMP_AGGREGATE;
  1086 + srs_error("invalid aggregate message type. ret=%d", ret);
  1087 + return ret;
  1088 + }
  1089 + int8_t type = stream->read_1bytes();
  1090 +
  1091 + if (!stream->require(3)) {
  1092 + ret = ERROR_RTMP_AGGREGATE;
  1093 + srs_error("invalid aggregate message size. ret=%d", ret);
  1094 + return ret;
  1095 + }
  1096 + int32_t data_size = stream->read_3bytes();
  1097 +
  1098 + if (data_size < 0) {
  1099 + ret = ERROR_RTMP_AGGREGATE;
  1100 + srs_error("invalid aggregate message size(negative). ret=%d", ret);
  1101 + return ret;
  1102 + }
  1103 +
  1104 + if (!stream->require(3)) {
  1105 + ret = ERROR_RTMP_AGGREGATE;
  1106 + srs_error("invalid aggregate message time. ret=%d", ret);
  1107 + return ret;
  1108 + }
  1109 + int32_t timestamp = stream->read_3bytes();
  1110 +
  1111 + if (!stream->require(1)) {
  1112 + ret = ERROR_RTMP_AGGREGATE;
  1113 + srs_error("invalid aggregate message time(high). ret=%d", ret);
  1114 + return ret;
  1115 + }
  1116 + int32_t time_h = stream->read_1bytes();
  1117 +
  1118 + timestamp |= time_h<<24;
  1119 + timestamp &= 0x7FFFFFFF;
  1120 +
  1121 + if (!stream->require(3)) {
  1122 + ret = ERROR_RTMP_AGGREGATE;
  1123 + srs_error("invalid aggregate message stream_id. ret=%d", ret);
  1124 + return ret;
  1125 + }
  1126 + int32_t stream_id = stream->read_3bytes();
  1127 +
  1128 + if (data_size > 0 && !stream->require(data_size)) {
  1129 + ret = ERROR_RTMP_AGGREGATE;
  1130 + srs_error("invalid aggregate message data. ret=%d", ret);
  1131 + return ret;
  1132 + }
  1133 +
  1134 + // to common message.
  1135 + SrsCommonMessage __o;
  1136 + SrsMessage& o = __o;
  1137 +
  1138 + o.header.message_type = type;
  1139 + o.header.payload_length = data_size;
  1140 + o.header.timestamp_delta = timestamp;
  1141 + o.header.timestamp = timestamp;
  1142 + o.header.stream_id = stream_id;
  1143 + o.header.perfer_cid = msg->header.perfer_cid;
  1144 +
  1145 + if (data_size > 0) {
  1146 + o.size = data_size;
  1147 + o.payload = new int8_t[o.size];
  1148 + stream->read_bytes((char*)o.payload, o.size);
  1149 + }
  1150 +
  1151 + if (!stream->require(4)) {
  1152 + ret = ERROR_RTMP_AGGREGATE;
  1153 + srs_error("invalid aggregate message previous tag size. ret=%d", ret);
  1154 + return ret;
  1155 + }
  1156 + stream->read_4bytes();
  1157 +
  1158 + // process parsed message
  1159 + if (o.header.is_audio()) {
  1160 + if ((ret = on_audio(&o)) != ERROR_SUCCESS) {
  1161 + return ret;
  1162 + }
  1163 + } else if (o.header.is_video()) {
  1164 + if ((ret = on_video(&o)) != ERROR_SUCCESS) {
  1165 + return ret;
  1166 + }
  1167 + }
  1168 + }
  1169 +
  1170 + return ret;
  1171 +}
  1172 +
1072 int SrsSource::on_publish() 1173 int SrsSource::on_publish()
1073 { 1174 {
1074 int ret = ERROR_SUCCESS; 1175 int ret = ERROR_SUCCESS;
@@ -57,6 +57,7 @@ class SrsDvr; @@ -57,6 +57,7 @@ class SrsDvr;
57 #ifdef SRS_AUTO_TRANSCODE 57 #ifdef SRS_AUTO_TRANSCODE
58 class SrsEncoder; 58 class SrsEncoder;
59 #endif 59 #endif
  60 +class SrsStream;
60 61
61 /** 62 /**
62 * time jitter detect and correct, 63 * time jitter detect and correct,
@@ -251,6 +252,8 @@ private: @@ -251,6 +252,8 @@ private:
251 SrsGopCache* gop_cache; 252 SrsGopCache* gop_cache;
252 // to forward stream to other servers 253 // to forward stream to other servers
253 std::vector<SrsForwarder*> forwarders; 254 std::vector<SrsForwarder*> forwarders;
  255 + // for aggregate message
  256 + SrsStream* aggregate_stream;
254 private: 257 private:
255 /** 258 /**
256 * the sample rate of audio in metadata. 259 * the sample rate of audio in metadata.
@@ -307,6 +310,7 @@ public: @@ -307,6 +310,7 @@ public:
307 virtual int on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata); 310 virtual int on_meta_data(SrsMessage* msg, SrsOnMetaDataPacket* metadata);
308 virtual int on_audio(SrsMessage* audio); 311 virtual int on_audio(SrsMessage* audio);
309 virtual int on_video(SrsMessage* video); 312 virtual int on_video(SrsMessage* video);
  313 + virtual int on_aggregate(SrsMessage* msg);
310 /** 314 /**
311 * publish stream event notify. 315 * publish stream event notify.
312 * @param _req the request from client, the source will deep copy it, 316 * @param _req the request from client, the source will deep copy it,
@@ -83,6 +83,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -83,6 +83,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
83 #define ERROR_RTMP_EDGE_PUBLISH_STATE 321 83 #define ERROR_RTMP_EDGE_PUBLISH_STATE 321
84 #define ERROR_RTMP_EDGE_PROXY_PULL 322 84 #define ERROR_RTMP_EDGE_PROXY_PULL 322
85 #define ERROR_RTMP_EDGE_RELOAD 323 85 #define ERROR_RTMP_EDGE_RELOAD 323
  86 +// aggregate message parse failed.
  87 +#define ERROR_RTMP_AGGREGATE 324
86 88
87 #define ERROR_SYSTEM_STREAM_INIT 400 89 #define ERROR_SYSTEM_STREAM_INIT 400
88 #define ERROR_SYSTEM_PACKET_INVALID 401 90 #define ERROR_SYSTEM_PACKET_INVALID 401
@@ -23,6 +23,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -23,6 +23,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 23
24 #include <srs_kernel_stream.hpp> 24 #include <srs_kernel_stream.hpp>
25 25
  26 +using namespace std;
  27 +
26 #include <srs_kernel_log.hpp> 28 #include <srs_kernel_log.hpp>
27 #include <srs_kernel_error.hpp> 29 #include <srs_kernel_error.hpp>
28 30
@@ -160,7 +162,7 @@ int64_t SrsStream::read_8bytes() @@ -160,7 +162,7 @@ int64_t SrsStream::read_8bytes()
160 return value; 162 return value;
161 } 163 }
162 164
163 -std::string SrsStream::read_string(int len) 165 +string SrsStream::read_string(int len)
164 { 166 {
165 srs_assert(require(len)); 167 srs_assert(require(len));
166 168
@@ -172,6 +174,15 @@ std::string SrsStream::read_string(int len) @@ -172,6 +174,15 @@ std::string SrsStream::read_string(int len)
172 return value; 174 return value;
173 } 175 }
174 176
  177 +void SrsStream::read_bytes(char* data, int size)
  178 +{
  179 + srs_assert(require(size));
  180 +
  181 + memcpy(data, p, size);
  182 +
  183 + p += size;
  184 +}
  185 +
175 void SrsStream::write_1bytes(int8_t value) 186 void SrsStream::write_1bytes(int8_t value)
176 { 187 {
177 srs_assert(require(1)); 188 srs_assert(require(1));
@@ -224,7 +235,7 @@ void SrsStream::write_8bytes(int64_t value) @@ -224,7 +235,7 @@ void SrsStream::write_8bytes(int64_t value)
224 *p++ = pp[0]; 235 *p++ = pp[0];
225 } 236 }
226 237
227 -void SrsStream::write_string(std::string value) 238 +void SrsStream::write_string(string value)
228 { 239 {
229 srs_assert(require(value.length())); 240 srs_assert(require(value.length()));
230 241
@@ -104,6 +104,10 @@ public: @@ -104,6 +104,10 @@ public:
104 * get string from stream, length specifies by param len. 104 * get string from stream, length specifies by param len.
105 */ 105 */
106 virtual std::string read_string(int len); 106 virtual std::string read_string(int len);
  107 + /**
  108 + * get bytes from stream, length specifies by param len.
  109 + */
  110 + virtual void read_bytes(char* data, int size);
107 public: 111 public:
108 /** 112 /**
109 * write 1bytes char to stream. 113 * write 1bytes char to stream.
@@ -1477,6 +1477,11 @@ bool SrsMessageHeader::is_user_control_message() @@ -1477,6 +1477,11 @@ bool SrsMessageHeader::is_user_control_message()
1477 return message_type == RTMP_MSG_UserControlMessage; 1477 return message_type == RTMP_MSG_UserControlMessage;
1478 } 1478 }
1479 1479
  1480 +bool SrsMessageHeader::is_aggregate()
  1481 +{
  1482 + return message_type == RTMP_MSG_AggregateMessage;
  1483 +}
  1484 +
1480 void SrsMessageHeader::initialize_amf0_script(int size, int stream) 1485 void SrsMessageHeader::initialize_amf0_script(int size, int stream)
1481 { 1486 {
1482 message_type = RTMP_MSG_AMF0DataMessage; 1487 message_type = RTMP_MSG_AMF0DataMessage;
@@ -277,6 +277,7 @@ public: @@ -277,6 +277,7 @@ public:
277 bool is_ackledgement(); 277 bool is_ackledgement();
278 bool is_set_chunk_size(); 278 bool is_set_chunk_size();
279 bool is_user_control_message(); 279 bool is_user_control_message();
  280 + bool is_aggregate();
280 281
281 void initialize_amf0_script(int size, int stream); 282 void initialize_amf0_script(int size, int stream);
282 void initialize_audio(int size, u_int32_t time, int stream); 283 void initialize_audio(int size, u_int32_t time, int stream);