winlin

for bug #293, support http aac stream

@@ -214,9 +214,10 @@ int SrsAacStreamEncoder::write_audio(int64_t timestamp, char* data, int size) @@ -214,9 +214,10 @@ int SrsAacStreamEncoder::write_audio(int64_t timestamp, char* data, int size)
214 return enc->write_audio(timestamp, data, size); 214 return enc->write_audio(timestamp, data, size);
215 } 215 }
216 216
217 -int SrsAacStreamEncoder::write_video(int64_t timestamp, char* data, int size) 217 +int SrsAacStreamEncoder::write_video(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
218 { 218 {
219 - return enc->write_video(timestamp, data, size); 219 + // aac ignore any flv video.
  220 + return ERROR_SUCCESS;
220 } 221 }
221 222
222 int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/) 223 int SrsAacStreamEncoder::write_metadata(int64_t /*timestamp*/, char* /*data*/, int /*size*/)
@@ -318,6 +319,9 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) @@ -318,6 +319,9 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r)
318 if (serve_flv_streaming) { 319 if (serve_flv_streaming) {
319 enc = new SrsFlvStreamEncoder(); 320 enc = new SrsFlvStreamEncoder();
320 } 321 }
  322 + if (serve_aac_streaming) {
  323 + enc = new SrsAacStreamEncoder();
  324 + }
321 SrsAutoFree(ISrsStreamEncoder, enc); 325 SrsAutoFree(ISrsStreamEncoder, enc);
322 326
323 if ((ret = enc->initialize(&writer)) != ERROR_SUCCESS) { 327 if ((ret = enc->initialize(&writer)) != ERROR_SUCCESS) {
@@ -36,6 +36,7 @@ using namespace std; @@ -36,6 +36,7 @@ using namespace std;
36 #include <srs_kernel_error.hpp> 36 #include <srs_kernel_error.hpp>
37 #include <srs_kernel_stream.hpp> 37 #include <srs_kernel_stream.hpp>
38 #include <srs_kernel_file.hpp> 38 #include <srs_kernel_file.hpp>
  39 +#include <srs_kernel_codec.hpp>
39 40
40 #define SRS_FLV_TAG_HEADER_SIZE 11 41 #define SRS_FLV_TAG_HEADER_SIZE 11
41 #define SRS_FLV_PREVIOUS_TAG_SIZE 4 42 #define SRS_FLV_PREVIOUS_TAG_SIZE 4
@@ -43,6 +44,7 @@ using namespace std; @@ -43,6 +44,7 @@ using namespace std;
43 SrsAacEncoder::SrsAacEncoder() 44 SrsAacEncoder::SrsAacEncoder()
44 { 45 {
45 _fs = NULL; 46 _fs = NULL;
  47 + got_sequence_header = false;
46 tag_stream = new SrsStream(); 48 tag_stream = new SrsStream();
47 } 49 }
48 50
@@ -76,16 +78,143 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size) @@ -76,16 +78,143 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
76 78
77 timestamp &= 0x7fffffff; 79 timestamp &= 0x7fffffff;
78 80
  81 + SrsStream* stream = tag_stream;
  82 + if ((ret = stream->initialize(data, size)) != ERROR_SUCCESS) {
79 return ret; 83 return ret;
80 -} 84 + }
81 85
82 -int SrsAacEncoder::write_video(int64_t timestamp, char* data, int size)  
83 -{  
84 - int ret = ERROR_SUCCESS; 86 + // audio decode
  87 + if (!stream->require(1)) {
  88 + ret = ERROR_AAC_DECODE_ERROR;
  89 + srs_error("aac decode audio sound_format failed. ret=%d", ret);
  90 + return ret;
  91 + }
85 92
86 - srs_assert(data); 93 + // @see: E.4.2 Audio Tags, video_file_format_spec_v10_1.pdf, page 76
  94 + int8_t sound_format = stream->read_1bytes();
87 95
88 - timestamp &= 0x7fffffff; 96 + // @see: SrsAvcAacCodec::audio_aac_demux
  97 + //int8_t sound_type = sound_format & 0x01;
  98 + //int8_t sound_size = (sound_format >> 1) & 0x01;
  99 + //int8_t sound_rate = (sound_format >> 2) & 0x03;
  100 + sound_format = (sound_format >> 4) & 0x0f;
  101 +
  102 + if ((SrsCodecAudio)sound_format != SrsCodecAudioAAC) {
  103 + ret = ERROR_AAC_DECODE_ERROR;
  104 + srs_error("aac required, format=%d. ret=%d", sound_format, ret);
  105 + return ret;
  106 + }
  107 +
  108 + if (!stream->require(1)) {
  109 + ret = ERROR_AAC_DECODE_ERROR;
  110 + srs_error("aac decode aac_packet_type failed. ret=%d", ret);
  111 + return ret;
  112 + }
  113 +
  114 + SrsCodecAudioType aac_packet_type = (SrsCodecAudioType)stream->read_1bytes();
  115 + if (aac_packet_type == SrsCodecAudioTypeSequenceHeader) {
  116 + // AudioSpecificConfig
  117 + // 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
  118 + //
  119 + // only need to decode the first 2bytes:
  120 + // audioObjectType, aac_profile, 5bits.
  121 + // samplingFrequencyIndex, aac_sample_rate, 4bits.
  122 + // channelConfiguration, aac_channels, 4bits
  123 + if (!stream->require(2)) {
  124 + ret = ERROR_AAC_DECODE_ERROR;
  125 + srs_error("aac decode sequence header failed. ret=%d", ret);
  126 + return ret;
  127 + }
  128 +
  129 + aac_profile = stream->read_1bytes();
  130 + aac_sample_rate = stream->read_1bytes();
  131 +
  132 + aac_channels = (aac_sample_rate >> 3) & 0x0f;
  133 + aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
  134 + aac_profile = (aac_profile >> 3) & 0x1f;
  135 +
  136 + got_sequence_header = true;
  137 +
  138 + return ret;
  139 + }
  140 +
  141 + if (!got_sequence_header) {
  142 + ret = ERROR_AAC_DECODE_ERROR;
  143 + srs_error("aac no sequence header. ret=%d", ret);
  144 + return ret;
  145 + }
  146 +
  147 + // the left is the aac raw frame data.
  148 + int16_t aac_frame_length = stream->size() - stream->pos();
  149 +
  150 + // write the ADTS header.
  151 + // @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75,
  152 + // 1.A.2.2 Audio_Data_Transport_Stream frame, ADTS
  153 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64145885
  154 + // byte_alignment()
  155 +
  156 + // adts_fixed_header:
  157 + // 12bits syncword,
  158 + // 16bits left.
  159 + // adts_variable_header:
  160 + // 28bits
  161 + // 12+16+28=56bits
  162 + // adts_error_check:
  163 + // 16bits if protection_absent
  164 + // 56+16=72bits
  165 + // if protection_absent:
  166 + // require(7bytes)=56bits
  167 + // else
  168 + // require(9bytes)=72bits
  169 + char aac_fixed_header[7];
  170 + if(true) {
  171 + char* pp = aac_fixed_header;
  172 +
  173 + // Syncword 12 bslbf
  174 + *pp++ = 0xff;
  175 + // 4bits left.
  176 + // adts_fixed_header(), 1.A.2.2.1 Fixed Header of ADTS
  177 + // ID 1 bslbf
  178 + // Layer 2 uimsbf
  179 + // protection_absent 1 bslbf
  180 + *pp++ = 0xf1;
  181 +
  182 + // Profile_ObjectType 2 uimsbf
  183 + // sampling_frequency_index 4 uimsbf
  184 + // private_bit 1 bslbf
  185 + // channel_configuration 3 uimsbf
  186 + // original/copy 1 bslbf
  187 + // home 1 bslbf
  188 + int8_t fh_Profile_ObjectType = aac_profile - 1;
  189 + *pp++ = ((fh_Profile_ObjectType << 6) & 0xc0) | ((aac_sample_rate << 2) & 0x3c) | ((aac_channels >> 2) & 0x01);
  190 + // @remark, Emphasis is removed,
  191 + // @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736
  192 + // 4bits left.
  193 + // adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
  194 + // copyright_identification_bit 1 bslbf
  195 + // copyright_identification_start 1 bslbf
  196 + *pp++ = ((aac_channels << 6) & 0xc0) | ((aac_frame_length >> 11) & 0x03);
  197 +
  198 + // aac_frame_length 13 bslbf: Length of the frame including headers and error_check in bytes.
  199 + // use the left 2bits as the 13 and 12 bit,
  200 + // the aac_frame_length is 13bits, so we move 13-2=11.
  201 + *pp++ = aac_frame_length >> 3;
  202 + // adts_buffer_fullness 11 bslbf
  203 + *pp++ = (aac_frame_length << 5) & 0xe0;
  204 +
  205 + // no_raw_data_blocks_in_frame 2 uimsbf
  206 + *pp++ = 0xfc;
  207 + }
  208 +
  209 + // write 7bytes fixed header.
  210 + if ((ret = _fs->write(aac_fixed_header, 7, NULL)) != ERROR_SUCCESS) {
  211 + return ret;
  212 + }
  213 +
  214 + // write aac frame body.
  215 + if ((ret = _fs->write(data + stream->pos(), aac_frame_length, NULL)) != ERROR_SUCCESS) {
  216 + return ret;
  217 + }
89 218
90 return ret; 219 return ret;
91 } 220 }
@@ -43,6 +43,11 @@ class SrsAacEncoder @@ -43,6 +43,11 @@ class SrsAacEncoder
43 private: 43 private:
44 SrsFileWriter* _fs; 44 SrsFileWriter* _fs;
45 private: 45 private:
  46 + int8_t aac_profile;
  47 + int8_t aac_sample_rate;
  48 + int8_t aac_channels;
  49 + bool got_sequence_header;
  50 +private:
46 SrsStream* tag_stream; 51 SrsStream* tag_stream;
47 public: 52 public:
48 SrsAacEncoder(); 53 SrsAacEncoder();
@@ -60,7 +65,6 @@ public: @@ -60,7 +65,6 @@ public:
60 * @remark assert data is not NULL. 65 * @remark assert data is not NULL.
61 */ 66 */
62 virtual int write_audio(int64_t timestamp, char* data, int size); 67 virtual int write_audio(int64_t timestamp, char* data, int size);
63 - virtual int write_video(int64_t timestamp, char* data, int size);  
64 }; 68 };
65 69
66 #endif 70 #endif
@@ -204,6 +204,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -204,6 +204,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
204 #define ERROR_AAC_DATA_INVALID 3048 204 #define ERROR_AAC_DATA_INVALID 3048
205 #define ERROR_HTTP_STATUS_INVLIAD 3049 205 #define ERROR_HTTP_STATUS_INVLIAD 3049
206 #define ERROR_KERNEL_AAC_STREAM_CLOSED 3050 206 #define ERROR_KERNEL_AAC_STREAM_CLOSED 3050
  207 +#define ERROR_AAC_DECODE_ERROR 3051
207 208
208 /////////////////////////////////////////////////////// 209 ///////////////////////////////////////////////////////
209 // HTTP protocol error. 210 // HTTP protocol error.