winlin

for #293, add aac encoder for http aac stream.

@@ -365,7 +365,7 @@ MODULE_DEPENDS=("CORE") @@ -365,7 +365,7 @@ MODULE_DEPENDS=("CORE")
365 ModuleLibIncs=(${SRS_OBJS_DIR}) 365 ModuleLibIncs=(${SRS_OBJS_DIR})
366 MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream" 366 MODULE_FILES=("srs_kernel_error" "srs_kernel_log" "srs_kernel_stream"
367 "srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_file" 367 "srs_kernel_utility" "srs_kernel_flv" "srs_kernel_codec" "srs_kernel_file"
368 - "srs_kernel_consts") 368 + "srs_kernel_consts" "srs_kernel_aac")
369 KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh 369 KERNEL_INCS="src/kernel"; MODULE_DIR=${KERNEL_INCS} . auto/modules.sh
370 KERNEL_OBJS="${MODULE_OBJS[@]}" 370 KERNEL_OBJS="${MODULE_OBJS[@]}"
371 # 371 #
@@ -371,7 +371,7 @@ int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -371,7 +371,7 @@ int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
371 } 371 }
372 372
373 if (true) { 373 if (true) {
374 - ssize_t pos; 374 + size_t pos;
375 std::string ext = fullpath; 375 std::string ext = fullpath;
376 if ((pos = ext.rfind(".")) != string::npos) { 376 if ((pos = ext.rfind(".")) != string::npos) {
377 ext = ext.substr(pos); 377 ext = ext.substr(pos);
@@ -44,6 +44,7 @@ using namespace std; @@ -44,6 +44,7 @@ using namespace std;
44 #include <srs_protocol_rtmp.hpp> 44 #include <srs_protocol_rtmp.hpp>
45 #include <srs_app_source.hpp> 45 #include <srs_app_source.hpp>
46 #include <srs_protocol_msg_array.hpp> 46 #include <srs_protocol_msg_array.hpp>
  47 +#include <srs_kernel_aac.hpp>
47 48
48 SrsVodStream::SrsVodStream(string root_dir) 49 SrsVodStream::SrsVodStream(string root_dir)
49 : SrsGoHttpFileServer(root_dir) 50 : SrsGoHttpFileServer(root_dir)
@@ -138,35 +139,120 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* @@ -138,35 +139,120 @@ int SrsVodStream::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage*
138 return ret; 139 return ret;
139 } 140 }
140 141
141 -SrsFlvStreamWriter::SrsFlvStreamWriter(ISrsGoHttpResponseWriter* w) 142 +ISrsStreamEncoder::ISrsStreamEncoder()
  143 +{
  144 +}
  145 +
  146 +ISrsStreamEncoder::~ISrsStreamEncoder()
  147 +{
  148 +}
  149 +
  150 +SrsFlvStreamEncoder::SrsFlvStreamEncoder()
  151 +{
  152 + enc = new SrsFlvEncoder();
  153 +}
  154 +
  155 +SrsFlvStreamEncoder::~SrsFlvStreamEncoder()
  156 +{
  157 + srs_freep(enc);
  158 +}
  159 +
  160 +int SrsFlvStreamEncoder::initialize(SrsFileWriter* w)
  161 +{
  162 + int ret = ERROR_SUCCESS;
  163 +
  164 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  165 + return ret;
  166 + }
  167 +
  168 + // write flv header.
  169 + if ((ret = enc->write_header()) != ERROR_SUCCESS) {
  170 + return ret;
  171 + }
  172 +
  173 + return ret;
  174 +}
  175 +
  176 +int SrsFlvStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  177 +{
  178 + return enc->write_audio(timestamp, data, size);
  179 +}
  180 +
  181 +int SrsFlvStreamEncoder::write_video(int64_t timestamp, char* data, int size)
  182 +{
  183 + return enc->write_video(timestamp, data, size);
  184 +}
  185 +
  186 +int SrsFlvStreamEncoder::write_metadata(int64_t timestamp, char* data, int size)
  187 +{
  188 + return enc->write_metadata(timestamp, data, size);
  189 +}
  190 +
  191 +SrsAacStreamEncoder::SrsAacStreamEncoder()
  192 +{
  193 + enc = new SrsAacEncoder();
  194 +}
  195 +
  196 +SrsAacStreamEncoder::~SrsAacStreamEncoder()
  197 +{
  198 + srs_freep(enc);
  199 +}
  200 +
  201 +int SrsAacStreamEncoder::initialize(SrsFileWriter* w)
  202 +{
  203 + int ret = ERROR_SUCCESS;
  204 +
  205 + if ((ret = enc->initialize(w)) != ERROR_SUCCESS) {
  206 + return ret;
  207 + }
  208 +
  209 + return ret;
  210 +}
  211 +
  212 +int SrsAacStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
  213 +{
  214 + return enc->write_audio(timestamp, data, size);
  215 +}
  216 +
  217 +int SrsAacStreamEncoder::write_video(int64_t timestamp, char* data, int size)
  218 +{
  219 + return enc->write_video(timestamp, data, size);
  220 +}
  221 +
  222 +int SrsAacStreamEncoder::write_metadata(int64_t timestamp, char* data, int size)
  223 +{
  224 + return enc->write_metadata(timestamp, data, size);
  225 +}
  226 +
  227 +SrsStreamWriter::SrsStreamWriter(ISrsGoHttpResponseWriter* w)
142 { 228 {
143 writer = w; 229 writer = w;
144 } 230 }
145 231
146 -SrsFlvStreamWriter::~SrsFlvStreamWriter() 232 +SrsStreamWriter::~SrsStreamWriter()
147 { 233 {
148 } 234 }
149 235
150 -int SrsFlvStreamWriter::open(std::string /*file*/) 236 +int SrsStreamWriter::open(std::string /*file*/)
151 { 237 {
152 return ERROR_SUCCESS; 238 return ERROR_SUCCESS;
153 } 239 }
154 240
155 -void SrsFlvStreamWriter::close() 241 +void SrsStreamWriter::close()
156 { 242 {
157 } 243 }
158 244
159 -bool SrsFlvStreamWriter::is_open() 245 +bool SrsStreamWriter::is_open()
160 { 246 {
161 return true; 247 return true;
162 } 248 }
163 249
164 -int64_t SrsFlvStreamWriter::tellg() 250 +int64_t SrsStreamWriter::tellg()
165 { 251 {
166 return 0; 252 return 0;
167 } 253 }
168 254
169 -int SrsFlvStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite) 255 +int SrsStreamWriter::write(void* buf, size_t count, ssize_t* pnwrite)
170 { 256 {
171 if (pnwrite) { 257 if (pnwrite) {
172 *pnwrite = count; 258 *pnwrite = count;
@@ -189,6 +275,20 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -189,6 +275,20 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
189 { 275 {
190 int ret = ERROR_SUCCESS; 276 int ret = ERROR_SUCCESS;
191 277
  278 + bool serve_flv_streaming = false;
  279 + bool serve_aac_streaming = false;
  280 +
  281 + srs_assert(entry);
  282 + if (srs_string_ends_with(entry->pattern, ".flv")) {
  283 + serve_flv_streaming = true;
  284 + } else if (srs_string_ends_with(entry->pattern, ".aac")) {
  285 + serve_aac_streaming = true;
  286 + } else {
  287 + ret = ERROR_HTTP_LIVE_STREAM_EXT;
  288 + srs_error("http: unsupported pattern %s", entry->pattern.c_str());
  289 + return ret;
  290 + }
  291 +
192 // create consumer of souce. 292 // create consumer of souce.
193 SrsConsumer* consumer = NULL; 293 SrsConsumer* consumer = NULL;
194 if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) { 294 if ((ret = source->create_consumer(consumer)) != ERROR_SUCCESS) {
@@ -201,20 +301,25 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -201,20 +301,25 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
201 SrsMessageArray msgs(SRS_PERF_MW_MSGS); 301 SrsMessageArray msgs(SRS_PERF_MW_MSGS);
202 // TODO: FIMXE: add pithy print. 302 // TODO: FIMXE: add pithy print.
203 303
204 - // write http header for ts. 304 + // write http header for streaming.
205 w->header()->set_content_length((int64_t)2 * 1024 * 1024 * 1024); 305 w->header()->set_content_length((int64_t)2 * 1024 * 1024 * 1024);
206 - w->header()->set_content_type("video/x-flv"); 306 + if (serve_flv_streaming) {
  307 + w->header()->set_content_type("video/x-flv");
  308 + }
  309 + if (serve_aac_streaming) {
  310 + w->header()->set_content_type("audio/x-aac");
  311 + }
207 312
208 // the memory writer. 313 // the memory writer.
209 - SrsFlvStreamWriter writer(w); 314 + SrsStreamWriter writer(w);
210 315
211 - SrsFlvEncoder enc;  
212 - if ((ret = enc.initialize(&writer)) != ERROR_SUCCESS) {  
213 - return ret; 316 + ISrsStreamEncoder* enc = NULL;
  317 + if (serve_flv_streaming) {
  318 + enc = new SrsFlvStreamEncoder();
214 } 319 }
  320 + SrsAutoFree(ISrsStreamEncoder, enc);
215 321
216 - // write flv header.  
217 - if ((ret = enc.write_header()) != ERROR_SUCCESS) { 322 + if ((ret = enc->initialize(&writer)) != ERROR_SUCCESS) {
218 return ret; 323 return ret;
219 } 324 }
220 325
@@ -223,23 +328,23 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -223,23 +328,23 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
223 // each msg in msgs.msgs must be free, for the SrsMessageArray never free them. 328 // each msg in msgs.msgs must be free, for the SrsMessageArray never free them.
224 int count = 0; 329 int count = 0;
225 if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) { 330 if ((ret = consumer->dump_packets(&msgs, count)) != ERROR_SUCCESS) {
226 - srs_error("get messages from consumer failed. ret=%d", ret); 331 + srs_error("http: get messages from consumer failed. ret=%d", ret);
227 return ret; 332 return ret;
228 } 333 }
229 334
230 if (count <= 0) { 335 if (count <= 0) {
231 - srs_info("mw sleep %dms for no msg", mw_sleep); 336 + srs_info("http: mw sleep %dms for no msg", mw_sleep);
232 // directly use sleep, donot use consumer wait. 337 // directly use sleep, donot use consumer wait.
233 st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US); 338 st_usleep(SRS_CONSTS_RTMP_PULSE_TIMEOUT_US);
234 339
235 // ignore when nothing got. 340 // ignore when nothing got.
236 continue; 341 continue;
237 } 342 }
238 - srs_info("got %d msgs, min=%d, mw=%d", count, 343 + srs_info("http: got %d msgs, min=%d, mw=%d", count,
239 SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000); 344 SRS_PERF_MW_MIN_MSGS, SRS_CONSTS_RTMP_PULSE_TIMEOUT_US / 1000);
240 345
241 // sendout all messages. 346 // sendout all messages.
242 - ret = send_messages(&enc, msgs.msgs, count); 347 + ret = streaming_send_messages(enc, msgs.msgs, count);
243 348
244 // free the messages. 349 // free the messages.
245 for (int i = 0; i < count; i++) { 350 for (int i = 0; i < count; i++) {
@@ -250,7 +355,7 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -250,7 +355,7 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
250 // check send error code. 355 // check send error code.
251 if (ret != ERROR_SUCCESS) { 356 if (ret != ERROR_SUCCESS) {
252 if (!srs_is_client_gracefully_close(ret)) { 357 if (!srs_is_client_gracefully_close(ret)) {
253 - srs_error("send messages to client failed. ret=%d", ret); 358 + srs_error("http: send messages to client failed. ret=%d", ret);
254 } 359 }
255 return ret; 360 return ret;
256 } 361 }
@@ -259,7 +364,7 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -259,7 +364,7 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
259 return ret; 364 return ret;
260 } 365 }
261 366
262 -int SrsLiveStream::send_messages(SrsFlvEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs) 367 +int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs)
263 { 368 {
264 int ret = ERROR_SUCCESS; 369 int ret = ERROR_SUCCESS;
265 370
@@ -41,6 +41,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -41,6 +41,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 class SrsSource; 41 class SrsSource;
42 class SrsRequest; 42 class SrsRequest;
43 class SrsStSocket; 43 class SrsStSocket;
  44 +class SrsAacEncoder;
44 class SrsFlvEncoder; 45 class SrsFlvEncoder;
45 class SrsHttpParser; 46 class SrsHttpParser;
46 class SrsHttpMessage; 47 class SrsHttpMessage;
@@ -63,15 +64,64 @@ protected: @@ -63,15 +64,64 @@ protected:
63 }; 64 };
64 65
65 /** 66 /**
  67 +* the stream encoder in some codec, for example, flv or aac.
  68 +*/
  69 +class ISrsStreamEncoder
  70 +{
  71 +public:
  72 + ISrsStreamEncoder();
  73 + virtual ~ISrsStreamEncoder();
  74 +public:
  75 + virtual int initialize(SrsFileWriter* w) = 0;
  76 + virtual int write_audio(int64_t timestamp, char* data, int size) = 0;
  77 + virtual int write_video(int64_t timestamp, char* data, int size) = 0;
  78 + virtual int write_metadata(int64_t timestamp, char* data, int size) = 0;
  79 +};
  80 +
  81 +/**
  82 +* the flv stream encoder, remux rtmp stream to flv stream.
  83 +*/
  84 +class SrsFlvStreamEncoder : public ISrsStreamEncoder
  85 +{
  86 +private:
  87 + SrsFlvEncoder* enc;
  88 +public:
  89 + SrsFlvStreamEncoder();
  90 + virtual ~SrsFlvStreamEncoder();
  91 +public:
  92 + virtual int initialize(SrsFileWriter* w);
  93 + virtual int write_audio(int64_t timestamp, char* data, int size);
  94 + virtual int write_video(int64_t timestamp, char* data, int size);
  95 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  96 +};
  97 +
  98 +/**
  99 +* the aac stream encoder, remux rtmp stream to aac stream.
  100 +*/
  101 +class SrsAacStreamEncoder : public ISrsStreamEncoder
  102 +{
  103 +private:
  104 + SrsAacEncoder* enc;
  105 +public:
  106 + SrsAacStreamEncoder();
  107 + virtual ~SrsAacStreamEncoder();
  108 +public:
  109 + virtual int initialize(SrsFileWriter* w);
  110 + virtual int write_audio(int64_t timestamp, char* data, int size);
  111 + virtual int write_video(int64_t timestamp, char* data, int size);
  112 + virtual int write_metadata(int64_t timestamp, char* data, int size);
  113 +};
  114 +
  115 +/**
66 * write stream to http response direclty. 116 * write stream to http response direclty.
67 */ 117 */
68 -class SrsFlvStreamWriter : public SrsFileWriter 118 +class SrsStreamWriter : public SrsFileWriter
69 { 119 {
70 private: 120 private:
71 ISrsGoHttpResponseWriter* writer; 121 ISrsGoHttpResponseWriter* writer;
72 public: 122 public:
73 - SrsFlvStreamWriter(ISrsGoHttpResponseWriter* w);  
74 - virtual ~SrsFlvStreamWriter(); 123 + SrsStreamWriter(ISrsGoHttpResponseWriter* w);
  124 + virtual ~SrsStreamWriter();
75 public: 125 public:
76 virtual int open(std::string file); 126 virtual int open(std::string file);
77 virtual void close(); 127 virtual void close();
@@ -97,7 +147,7 @@ public: @@ -97,7 +147,7 @@ public:
97 public: 147 public:
98 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r); 148 virtual int serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r);
99 private: 149 private:
100 - virtual int send_messages(SrsFlvEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs); 150 + virtual int streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrMessage** msgs, int nb_msgs);
101 }; 151 };
102 152
103 /** 153 /**
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_kernel_aac.hpp>
  25 +
  26 +// for srs-librtmp, @see https://github.com/winlinvip/simple-rtmp-server/issues/213
  27 +#ifndef _WIN32
  28 +#include <unistd.h>
  29 +#endif
  30 +
  31 +#include <fcntl.h>
  32 +#include <sstream>
  33 +using namespace std;
  34 +
  35 +#include <srs_kernel_log.hpp>
  36 +#include <srs_kernel_error.hpp>
  37 +#include <srs_kernel_stream.hpp>
  38 +#include <srs_kernel_file.hpp>
  39 +
  40 +#define SRS_FLV_TAG_HEADER_SIZE 11
  41 +#define SRS_FLV_PREVIOUS_TAG_SIZE 4
  42 +
  43 +SrsAacEncoder::SrsAacEncoder()
  44 +{
  45 + _fs = NULL;
  46 + tag_stream = new SrsStream();
  47 +}
  48 +
  49 +SrsAacEncoder::~SrsAacEncoder()
  50 +{
  51 + srs_freep(tag_stream);
  52 +}
  53 +
  54 +int SrsAacEncoder::initialize(SrsFileWriter* fs)
  55 +{
  56 + int ret = ERROR_SUCCESS;
  57 +
  58 + srs_assert(fs);
  59 +
  60 + if (!fs->is_open()) {
  61 + ret = ERROR_KERNEL_FLV_STREAM_CLOSED;
  62 + srs_warn("stream is not open for decoder. ret=%d", ret);
  63 + return ret;
  64 + }
  65 +
  66 + _fs = fs;
  67 +
  68 + return ret;
  69 +}
  70 +
  71 +int SrsAacEncoder::write_header()
  72 +{
  73 + int ret = ERROR_SUCCESS;
  74 +
  75 + // 9bytes header and 4bytes first previous-tag-size
  76 + static char flv_header[] = {
  77 + 'F', 'L', 'V', // Signatures "FLV"
  78 + (char)0x01, // File version (for example, 0x01 for FLV version 1)
  79 + (char)0x00, // 4, audio; 1, video; 5 audio+video.
  80 + (char)0x00, (char)0x00, (char)0x00, (char)0x09 // DataOffset UI32 The length of this header in bytes
  81 + };
  82 +
  83 + // flv specification should set the audio and video flag,
  84 + // actually in practise, application generally ignore this flag,
  85 + // so we generally set the audio/video to 0.
  86 +
  87 + // write 9bytes header.
  88 + if ((ret = write_header(flv_header)) != ERROR_SUCCESS) {
  89 + return ret;
  90 + }
  91 +
  92 + return ret;
  93 +}
  94 +
  95 +int SrsAacEncoder::write_header(char flv_header[9])
  96 +{
  97 + int ret = ERROR_SUCCESS;
  98 +
  99 + // write data.
  100 + if ((ret = _fs->write(flv_header, 9, NULL)) != ERROR_SUCCESS) {
  101 + srs_error("write flv header failed. ret=%d", ret);
  102 + return ret;
  103 + }
  104 +
  105 + char pts[] = { (char)0x00, (char)0x00, (char)0x00, (char)0x00 };
  106 + if ((ret = _fs->write(pts, 4, NULL)) != ERROR_SUCCESS) {
  107 + return ret;
  108 + }
  109 +
  110 + return ret;
  111 +}
  112 +
  113 +int SrsAacEncoder::write_metadata(char type, char* data, int size)
  114 +{
  115 + int ret = ERROR_SUCCESS;
  116 +
  117 + srs_assert(data);
  118 +
  119 + // 11 bytes tag header
  120 + static char tag_header[] = {
  121 + (char)type, // TagType UB [5], 18 = script data
  122 + (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
  123 + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
  124 + (char)0x00, // TimestampExtended UI8
  125 + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
  126 + };
  127 +
  128 + // write data size.
  129 + if ((ret = tag_stream->initialize(tag_header + 1, 3)) != ERROR_SUCCESS) {
  130 + return ret;
  131 + }
  132 + tag_stream->write_3bytes(size);
  133 +
  134 + if ((ret = write_tag(tag_header, sizeof(tag_header), data, size)) != ERROR_SUCCESS) {
  135 + srs_error("write flv data tag failed. ret=%d", ret);
  136 + return ret;
  137 + }
  138 +
  139 + return ret;
  140 +}
  141 +
  142 +int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
  143 +{
  144 + int ret = ERROR_SUCCESS;
  145 +
  146 + srs_assert(data);
  147 +
  148 + timestamp &= 0x7fffffff;
  149 +
  150 + // 11bytes tag header
  151 + static char tag_header[] = {
  152 + (char)8, // TagType UB [5], 8 = audio
  153 + (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
  154 + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
  155 + (char)0x00, // TimestampExtended UI8
  156 + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
  157 + };
  158 +
  159 + // write data size.
  160 + if ((ret = tag_stream->initialize(tag_header + 1, 7)) != ERROR_SUCCESS) {
  161 + return ret;
  162 + }
  163 + tag_stream->write_3bytes(size);
  164 + tag_stream->write_3bytes((int32_t)timestamp);
  165 + // default to little-endian
  166 + tag_stream->write_1bytes((timestamp >> 24) & 0xFF);
  167 +
  168 + if ((ret = write_tag(tag_header, sizeof(tag_header), data, size)) != ERROR_SUCCESS) {
  169 + srs_error("write flv audio tag failed. ret=%d", ret);
  170 + return ret;
  171 + }
  172 +
  173 + return ret;
  174 +}
  175 +
  176 +int SrsAacEncoder::write_video(int64_t timestamp, char* data, int size)
  177 +{
  178 + int ret = ERROR_SUCCESS;
  179 +
  180 + srs_assert(data);
  181 +
  182 + timestamp &= 0x7fffffff;
  183 +
  184 + // 11bytes tag header
  185 + static char tag_header[] = {
  186 + (char)9, // TagType UB [5], 9 = video
  187 + (char)0x00, (char)0x00, (char)0x00, // DataSize UI24 Length of the message.
  188 + (char)0x00, (char)0x00, (char)0x00, // Timestamp UI24 Time in milliseconds at which the data in this tag applies.
  189 + (char)0x00, // TimestampExtended UI8
  190 + (char)0x00, (char)0x00, (char)0x00, // StreamID UI24 Always 0.
  191 + };
  192 +
  193 + // write data size.
  194 + if ((ret = tag_stream->initialize(tag_header + 1, 7)) != ERROR_SUCCESS) {
  195 + return ret;
  196 + }
  197 + tag_stream->write_3bytes(size);
  198 + tag_stream->write_3bytes((int32_t)timestamp);
  199 + // default to little-endian
  200 + tag_stream->write_1bytes((timestamp >> 24) & 0xFF);
  201 +
  202 + if ((ret = write_tag(tag_header, sizeof(tag_header), data, size)) != ERROR_SUCCESS) {
  203 + srs_error("write flv video tag failed. ret=%d", ret);
  204 + return ret;
  205 + }
  206 +
  207 + return ret;
  208 +}
  209 +
  210 +int SrsAacEncoder::size_tag(int data_size)
  211 +{
  212 + srs_assert(data_size >= 0);
  213 + return SRS_FLV_TAG_HEADER_SIZE + data_size + SRS_FLV_PREVIOUS_TAG_SIZE;
  214 +}
  215 +
  216 +int SrsAacEncoder::write_tag(char* header, int header_size, char* tag, int tag_size)
  217 +{
  218 + int ret = ERROR_SUCCESS;
  219 +
  220 + // write tag header.
  221 + if ((ret = _fs->write(header, header_size, NULL)) != ERROR_SUCCESS) {
  222 + srs_error("write flv tag header failed. ret=%d", ret);
  223 + return ret;
  224 + }
  225 +
  226 + // write tag data.
  227 + if ((ret = _fs->write(tag, tag_size, NULL)) != ERROR_SUCCESS) {
  228 + srs_error("write flv tag failed. ret=%d", ret);
  229 + return ret;
  230 + }
  231 +
  232 + // PreviousTagSizeN UI32 Size of last tag, including its header, in bytes.
  233 + static char pre_size[SRS_FLV_PREVIOUS_TAG_SIZE];
  234 + if ((ret = tag_stream->initialize(pre_size, SRS_FLV_PREVIOUS_TAG_SIZE)) != ERROR_SUCCESS) {
  235 + return ret;
  236 + }
  237 + tag_stream->write_4bytes(tag_size + header_size);
  238 + if ((ret = _fs->write(pre_size, sizeof(pre_size), NULL)) != ERROR_SUCCESS) {
  239 + srs_error("write flv previous tag size failed. ret=%d", ret);
  240 + return ret;
  241 + }
  242 +
  243 + return ret;
  244 +}
  245 +
  246 +
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2015 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_KERNEL_AAC_HPP
  25 +#define SRS_KERNEL_AAC_HPP
  26 +
  27 +/*
  28 +#include <srs_kernel_aac.hpp>
  29 +*/
  30 +#include <srs_core.hpp>
  31 +
  32 +#include <string>
  33 +
  34 +class SrsStream;
  35 +class SrsFileWriter;
  36 +class SrsFileReader;
  37 +
  38 +/**
  39 +* encode data to flv file.
  40 +*/
  41 +class SrsAacEncoder
  42 +{
  43 +private:
  44 + SrsFileWriter* _fs;
  45 +private:
  46 + SrsStream* tag_stream;
  47 +public:
  48 + SrsAacEncoder();
  49 + virtual ~SrsAacEncoder();
  50 +public:
  51 + /**
  52 + * initialize the underlayer file stream.
  53 + * @remark user can initialize multiple times to encode multiple flv files.
  54 + * @remark, user must free the fs, flv encoder never close/free it.
  55 + */
  56 + virtual int initialize(SrsFileWriter* fs);
  57 +public:
  58 + /**
  59 + * write flv header.
  60 + * write following:
  61 + * 1. E.2 The FLV header
  62 + * 2. PreviousTagSize0 UI32 Always 0
  63 + * that is, 9+4=13bytes.
  64 + */
  65 + virtual int write_header();
  66 + virtual int write_header(char flv_header[9]);
  67 + /**
  68 + * write flv metadata.
  69 + * @param type, the type of data, or other message type.
  70 + * @param data, the amf0 metadata which serialize from:
  71 + * AMF0 string: onMetaData,
  72 + * AMF0 object: the metadata object.
  73 + * @remark assert data is not NULL.
  74 + */
  75 + virtual int write_metadata(char type, char* data, int size);
  76 + /**
  77 + * write audio/video packet.
  78 + * @remark assert data is not NULL.
  79 + */
  80 + virtual int write_audio(int64_t timestamp, char* data, int size);
  81 + virtual int write_video(int64_t timestamp, char* data, int size);
  82 +public:
  83 + /**
  84 + * get the tag size,
  85 + * including the tag header, body, and 4bytes previous tag size.
  86 + * @remark assert data_size is not negative.
  87 + */
  88 + static int size_tag(int data_size);
  89 +private:
  90 + virtual int write_tag(char* header, int header_size, char* tag, int tag_size);
  91 +};
  92 +
  93 +#endif
  94 +
@@ -211,6 +211,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -211,6 +211,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
211 #define ERROR_HTTP_PATTERN_DUPLICATED 4001 211 #define ERROR_HTTP_PATTERN_DUPLICATED 4001
212 #define ERROR_HTTP_URL_NOT_CLEAN 4002 212 #define ERROR_HTTP_URL_NOT_CLEAN 4002
213 #define ERROR_HTTP_CONTENT_LENGTH 4003 213 #define ERROR_HTTP_CONTENT_LENGTH 4003
  214 +#define ERROR_HTTP_LIVE_STREAM_EXT 4004
214 215
215 /** 216 /**
216 * whether the error code is an system control error. 217 * whether the error code is an system control error.
@@ -18,6 +18,8 @@ file @@ -18,6 +18,8 @@ file
18 ..\core\srs_core_performance.hpp, 18 ..\core\srs_core_performance.hpp,
19 ..\core\srs_core_performance.cpp, 19 ..\core\srs_core_performance.cpp,
20 kernel readonly separator, 20 kernel readonly separator,
  21 + ..\kernel\srs_kernel_aac.hpp,
  22 + ..\kernel\srs_kernel_aac.cpp,
21 ..\kernel\srs_kernel_codec.hpp, 23 ..\kernel\srs_kernel_codec.hpp,
22 ..\kernel\srs_kernel_codec.cpp, 24 ..\kernel\srs_kernel_codec.cpp,
23 ..\kernel\srs_kernel_consts.hpp, 25 ..\kernel\srs_kernel_consts.hpp,