正在显示
4 个修改的文件
包含
148 行增加
和
10 行删除
| @@ -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 | ||
| 79 | - return ret; | ||
| 80 | -} | 81 | + SrsStream* stream = tag_stream; |
| 82 | + if ((ret = stream->initialize(data, size)) != ERROR_SUCCESS) { | ||
| 83 | + return ret; | ||
| 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. |
-
请 注册 或 登录 后发表评论