mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
for #310, refine the aac profile for adts and aac object for RTMP sequence header.
This commit is contained in:
parent
04f3f2a8f8
commit
d3e2838fc6
10 changed files with 141 additions and 130 deletions
|
@ -60,7 +60,7 @@ SrsStatisticStream::SrsStatisticStream()
|
||||||
acodec = SrsCodecAudioReserved1;
|
acodec = SrsCodecAudioReserved1;
|
||||||
asample_rate = SrsCodecAudioSampleRateReserved;
|
asample_rate = SrsCodecAudioSampleRateReserved;
|
||||||
asound_type = SrsCodecAudioSoundTypeReserved;
|
asound_type = SrsCodecAudioSoundTypeReserved;
|
||||||
aac_profile = 0;
|
aac_profile = SrsAacProfileReserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsStatisticStream::~SrsStatisticStream()
|
SrsStatisticStream::~SrsStatisticStream()
|
||||||
|
@ -128,7 +128,7 @@ int SrsStatistic::on_video_info(SrsRequest* req,
|
||||||
|
|
||||||
int SrsStatistic::on_audio_info(SrsRequest* req,
|
int SrsStatistic::on_audio_info(SrsRequest* req,
|
||||||
SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
|
SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
|
||||||
u_int8_t aac_profile
|
SrsAacProfile aac_profile
|
||||||
) {
|
) {
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
* 1.5.1.1 Audio object type definition, page 23,
|
* 1.5.1.1 Audio object type definition, page 23,
|
||||||
* in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
|
* in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
|
||||||
*/
|
*/
|
||||||
u_int8_t aac_profile;
|
SrsAacProfile aac_profile;
|
||||||
public:
|
public:
|
||||||
SrsStatisticStream();
|
SrsStatisticStream();
|
||||||
virtual ~SrsStatisticStream();
|
virtual ~SrsStatisticStream();
|
||||||
|
@ -120,7 +120,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual int on_audio_info(SrsRequest* req,
|
virtual int on_audio_info(SrsRequest* req,
|
||||||
SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
|
SrsCodecAudio acodec, SrsCodecAudioSampleRate asample_rate, SrsCodecAudioSoundType asound_type,
|
||||||
u_int8_t aac_profile
|
SrsAacProfile aac_profile
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* when close stream.
|
* when close stream.
|
||||||
|
|
|
@ -43,6 +43,7 @@ SrsAacEncoder::SrsAacEncoder()
|
||||||
_fs = NULL;
|
_fs = NULL;
|
||||||
got_sequence_header = false;
|
got_sequence_header = false;
|
||||||
tag_stream = new SrsStream();
|
tag_stream = new SrsStream();
|
||||||
|
aac_profile = SrsAacProfileReserved;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsAacEncoder::~SrsAacEncoder()
|
SrsAacEncoder::~SrsAacEncoder()
|
||||||
|
@ -114,7 +115,7 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
|
||||||
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
// 1.6.2.1 AudioSpecificConfig, in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33.
|
||||||
//
|
//
|
||||||
// only need to decode the first 2bytes:
|
// only need to decode the first 2bytes:
|
||||||
// audioObjectType, aac_profile, 5bits.
|
// audioObjectType, 5bits.
|
||||||
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
// samplingFrequencyIndex, aac_sample_rate, 4bits.
|
||||||
// channelConfiguration, aac_channels, 4bits
|
// channelConfiguration, aac_channels, 4bits
|
||||||
if (!stream->require(2)) {
|
if (!stream->require(2)) {
|
||||||
|
@ -123,12 +124,14 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
aac_profile = stream->read_1bytes();
|
int8_t audioObjectType = stream->read_1bytes();
|
||||||
aac_sample_rate = stream->read_1bytes();
|
aac_sample_rate = stream->read_1bytes();
|
||||||
|
|
||||||
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
aac_channels = (aac_sample_rate >> 3) & 0x0f;
|
||||||
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
aac_sample_rate = ((audioObjectType << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01);
|
||||||
aac_profile = (aac_profile >> 3) & 0x1f;
|
|
||||||
|
audioObjectType = (audioObjectType >> 3) & 0x1f;
|
||||||
|
aac_profile = srs_codec_aac_rtmp2ts((SrsAacObjectType)audioObjectType);
|
||||||
|
|
||||||
got_sequence_header = true;
|
got_sequence_header = true;
|
||||||
|
|
||||||
|
@ -177,16 +180,13 @@ int SrsAacEncoder::write_audio(int64_t timestamp, char* data, int size)
|
||||||
// protection_absent 1 bslbf
|
// protection_absent 1 bslbf
|
||||||
*pp++ = 0xf1;
|
*pp++ = 0xf1;
|
||||||
|
|
||||||
// Profile_ObjectType 2 uimsbf
|
// profile 2 uimsbf
|
||||||
// sampling_frequency_index 4 uimsbf
|
// sampling_frequency_index 4 uimsbf
|
||||||
// private_bit 1 bslbf
|
// private_bit 1 bslbf
|
||||||
// channel_configuration 3 uimsbf
|
// channel_configuration 3 uimsbf
|
||||||
// original/copy 1 bslbf
|
// original/copy 1 bslbf
|
||||||
// home 1 bslbf
|
// home 1 bslbf
|
||||||
int8_t fh_Profile_ObjectType = aac_profile - 1;
|
*pp++ = ((aac_profile << 6) & 0xc0) | ((aac_sample_rate << 2) & 0x3c) | ((aac_channels >> 2) & 0x01);
|
||||||
*pp++ = ((fh_Profile_ObjectType << 6) & 0xc0) | ((aac_sample_rate << 2) & 0x3c) | ((aac_channels >> 2) & 0x01);
|
|
||||||
// @remark, Emphasis is removed,
|
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736
|
|
||||||
// 4bits left.
|
// 4bits left.
|
||||||
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
||||||
// copyright_identification_bit 1 bslbf
|
// copyright_identification_bit 1 bslbf
|
||||||
|
|
|
@ -31,6 +31,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <srs_kernel_codec.hpp>
|
||||||
|
|
||||||
class SrsStream;
|
class SrsStream;
|
||||||
class SrsFileWriter;
|
class SrsFileWriter;
|
||||||
class SrsFileReader;
|
class SrsFileReader;
|
||||||
|
@ -43,7 +45,7 @@ class SrsAacEncoder
|
||||||
private:
|
private:
|
||||||
SrsFileWriter* _fs;
|
SrsFileWriter* _fs;
|
||||||
private:
|
private:
|
||||||
int8_t aac_profile;
|
SrsAacProfile aac_profile;
|
||||||
int8_t aac_sample_rate;
|
int8_t aac_sample_rate;
|
||||||
int8_t aac_channels;
|
int8_t aac_channels;
|
||||||
bool got_sequence_header;
|
bool got_sequence_header;
|
||||||
|
|
|
@ -77,16 +77,36 @@ string srs_codec_audio2str(SrsCodecAudio codec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string srs_codec_aac_profile2str(u_int8_t aac_profile)
|
string srs_codec_aac_profile2str(SrsAacProfile aac_profile)
|
||||||
{
|
{
|
||||||
switch (aac_profile) {
|
switch (aac_profile) {
|
||||||
case 1: return "Main";
|
case SrsAacProfileMain: return "Main";
|
||||||
case 2: return "LC";
|
case SrsAacProfileLC: return "LC";
|
||||||
case 3: return "SSR";
|
case SrsAacProfileSSR: return "SSR";
|
||||||
default: return "Other";
|
default: return "Other";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile)
|
||||||
|
{
|
||||||
|
switch (profile) {
|
||||||
|
case SrsAacProfileMain: return SrsAacObjectTypeAacMain;
|
||||||
|
case SrsAacProfileLC: return SrsAacObjectTypeAacLC;
|
||||||
|
case SrsAacProfileSSR: return SrsAacObjectTypeAacSSR;
|
||||||
|
default: return SrsAacObjectTypeReserved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type)
|
||||||
|
{
|
||||||
|
switch (object_type) {
|
||||||
|
case SrsAacObjectTypeAacMain: return SrsAacProfileMain;
|
||||||
|
case SrsAacObjectTypeAacLC: return SrsAacProfileLC;
|
||||||
|
case SrsAacObjectTypeAacSSR: return SrsAacProfileSSR;
|
||||||
|
default: return SrsAacProfileReserved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the public data, event HLS disable, others can use it.
|
* the public data, event HLS disable, others can use it.
|
||||||
*/
|
*/
|
||||||
|
@ -260,7 +280,7 @@ SrsAvcAacCodec::SrsAvcAacCodec()
|
||||||
|
|
||||||
avc_profile = 0;
|
avc_profile = 0;
|
||||||
avc_level = 0;
|
avc_level = 0;
|
||||||
aac_profile = 0;
|
aac_profile = SrsAacProfileReserved;
|
||||||
aac_sample_rate = __SRS_AAC_SAMPLE_RATE_UNSET; // sample rate ignored
|
aac_sample_rate = __SRS_AAC_SAMPLE_RATE_UNSET; // sample rate ignored
|
||||||
aac_channels = 0;
|
aac_channels = 0;
|
||||||
avc_extra_size = 0;
|
avc_extra_size = 0;
|
||||||
|
@ -458,20 +478,9 @@ int SrsAvcAacCodec::audio_aac_sequence_header_demux(char* data, int size)
|
||||||
// set the aac sample rate.
|
// set the aac sample rate.
|
||||||
aac_sample_rate = samplingFrequencyIndex;
|
aac_sample_rate = samplingFrequencyIndex;
|
||||||
|
|
||||||
// the profile = object_id + 1
|
// convert the object type in sequence header to aac profile of ADTS.
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
aac_profile = srs_codec_aac_rtmp2ts((SrsAacObjectType)profile_ObjectType);
|
||||||
// Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
if (aac_profile == SrsAacProfileReserved) {
|
||||||
aac_profile = profile_ObjectType + 1;
|
|
||||||
|
|
||||||
// the valid aac profile:
|
|
||||||
// MPEG-2 profile
|
|
||||||
// Main profile (ID == 1)
|
|
||||||
// Low Complexity profile (LC) (ID == 2)
|
|
||||||
// Scalable Sampling Rate profile (SSR) (ID == 3)
|
|
||||||
// (reserved) (ID == 4)
|
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
|
||||||
// Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
|
||||||
if (aac_profile > 4) {
|
|
||||||
ret = ERROR_HLS_DECODE_ERROR;
|
ret = ERROR_HLS_DECODE_ERROR;
|
||||||
srs_error("audio codec decode aac sequence header failed, "
|
srs_error("audio codec decode aac sequence header failed, "
|
||||||
"adts object=%d invalid. ret=%d", profile_ObjectType, ret);
|
"adts object=%d invalid. ret=%d", profile_ObjectType, ret);
|
||||||
|
|
|
@ -375,20 +375,40 @@ enum SrsAvcPayloadFormat
|
||||||
SrsAvcPayloadFormatIbmf,
|
SrsAvcPayloadFormatIbmf,
|
||||||
};
|
};
|
||||||
|
|
||||||
// the profile = object_id + 1
|
/**
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
* the aac profile, for ADTS(HLS/TS)
|
||||||
// Table 1. A.9 C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
* @see https://github.com/winlinvip/simple-rtmp-server/issues/310
|
||||||
// the valid object type:
|
*/
|
||||||
// AAC Main(ID == 0)
|
enum SrsAacProfile
|
||||||
// AAC LC(ID == 1)
|
{
|
||||||
// AAC SSR(ID == 2)
|
SrsAacProfileReserved = 3,
|
||||||
// AAC LTP(ID == 3)
|
|
||||||
// the valid aac profile:
|
// @see 7.1 Profiles, aac-iso-13818-7.pdf, page 40
|
||||||
// Main profile (ID == 1)
|
SrsAacProfileMain = 0,
|
||||||
// Low Complexity profile (LC) (ID == 2)
|
SrsAacProfileLC = 1,
|
||||||
// Scalable Sampling Rate profile (SSR) (ID == 3)
|
SrsAacProfileSSR = 2,
|
||||||
// (reserved) (ID == 4)
|
};
|
||||||
std::string srs_codec_aac_profile2str(u_int8_t aac_profile);
|
std::string srs_codec_aac_profile2str(SrsAacProfile aac_profile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the aac object type, for RTMP sequence header
|
||||||
|
* for AudioSpecificConfig, @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 33
|
||||||
|
* for audioObjectType, @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23
|
||||||
|
*/
|
||||||
|
enum SrsAacObjectType
|
||||||
|
{
|
||||||
|
SrsAacObjectTypeReserved = 0,
|
||||||
|
|
||||||
|
// Table 1.1 – Audio Object Type definition
|
||||||
|
// @see @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 23
|
||||||
|
SrsAacObjectTypeAacMain = 1,
|
||||||
|
SrsAacObjectTypeAacLC = 2,
|
||||||
|
SrsAacObjectTypeAacSSR = 3,
|
||||||
|
};
|
||||||
|
// ts/hls/adts audio header profile to RTMP sequence header object type.
|
||||||
|
SrsAacObjectType srs_codec_aac_ts2rtmp(SrsAacProfile profile);
|
||||||
|
// RTMP sequence header object type to ts/hls/adts audio header profile.
|
||||||
|
SrsAacProfile srs_codec_aac_rtmp2ts(SrsAacObjectType object_type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the h264/avc and aac codec, for media stream.
|
* the h264/avc and aac codec, for media stream.
|
||||||
|
@ -446,7 +466,7 @@ public:
|
||||||
* 1.5.1.1 Audio object type definition, page 23,
|
* 1.5.1.1 Audio object type definition, page 23,
|
||||||
* in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
|
* in aac-mp4a-format-ISO_IEC_14496-3+2001.pdf.
|
||||||
*/
|
*/
|
||||||
u_int8_t aac_profile;
|
SrsAacProfile aac_profile;
|
||||||
/**
|
/**
|
||||||
* samplingFrequencyIndex
|
* samplingFrequencyIndex
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -214,6 +214,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#define ERROR_HTTP_JSON_REQUIRED 3052
|
#define ERROR_HTTP_JSON_REQUIRED 3052
|
||||||
#define ERROR_HTTP_DVR_CREATE_REQUEST 3053
|
#define ERROR_HTTP_DVR_CREATE_REQUEST 3053
|
||||||
#define ERROR_HTTP_DVR_NO_TAEGET 3054
|
#define ERROR_HTTP_DVR_NO_TAEGET 3054
|
||||||
|
#define ERROR_ADTS_ID_NOT_AAC 3055
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// HTTP/StreamCaster protocol error.
|
// HTTP/StreamCaster protocol error.
|
||||||
|
|
|
@ -2765,20 +2765,6 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the profile = object_id + 1
|
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
|
||||||
// Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
|
||||||
// the valid object type:
|
|
||||||
// AAC Main(ID == 0)
|
|
||||||
// AAC LC(ID == 1)
|
|
||||||
// AAC SSR(ID == 2)
|
|
||||||
// AAC LTP(ID == 3)
|
|
||||||
u_int8_t profile_ObjectType = codec->aac_profile - 1;
|
|
||||||
|
|
||||||
// TODO: FIXME: only support Main or LC.
|
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/310
|
|
||||||
profile_ObjectType = srs_min(1, profile_ObjectType);
|
|
||||||
|
|
||||||
// the frame length is the AAC raw data plus the adts header size.
|
// the frame length is the AAC raw data plus the adts header size.
|
||||||
int32_t frame_length = size + 7;
|
int32_t frame_length = size + 7;
|
||||||
|
|
||||||
|
@ -2811,7 +2797,7 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block()
|
int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block()
|
||||||
*/
|
*/
|
||||||
// profile, 2bits
|
// profile, 2bits
|
||||||
adts_header[2] = (profile_ObjectType << 6) & 0xc0;
|
adts_header[2] = (codec->aac_profile << 6) & 0xc0;
|
||||||
// sampling_frequency_index 4bits
|
// sampling_frequency_index 4bits
|
||||||
adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c;
|
adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c;
|
||||||
// channel_configuration 3bits
|
// channel_configuration 3bits
|
||||||
|
|
|
@ -329,8 +329,8 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame
|
||||||
int adts_header_start = stream->pos();
|
int adts_header_start = stream->pos();
|
||||||
|
|
||||||
// decode the ADTS.
|
// decode the ADTS.
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75,
|
// @see aac-iso-13818-7.pdf, page 26
|
||||||
// 1.A.2.2 Audio_Data_Transport_Stream frame, ADTS
|
// 6.2 Audio Data Transport Stream, ADTS
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64145885
|
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64145885
|
||||||
// byte_alignment()
|
// byte_alignment()
|
||||||
|
|
||||||
|
@ -356,55 +356,63 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame
|
||||||
return ERROR_AAC_REQUIRED_ADTS;
|
return ERROR_AAC_REQUIRED_ADTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Syncword 12 bslbf
|
// syncword 12 bslbf
|
||||||
stream->read_1bytes();
|
stream->read_1bytes();
|
||||||
// 4bits left.
|
// 4bits left.
|
||||||
// adts_fixed_header(), 1.A.2.2.1 Fixed Header of ADTS
|
// adts_fixed_header(), 1.A.2.2.1 Fixed Header of ADTS
|
||||||
// ID 1 bslbf
|
// ID 1 bslbf
|
||||||
// Layer 2 uimsbf
|
// layer 2 uimsbf
|
||||||
// protection_absent 1 bslbf
|
// protection_absent 1 bslbf
|
||||||
int8_t fh0 = (stream->read_1bytes() & 0x0f);
|
int8_t pav = (stream->read_1bytes() & 0x0f);
|
||||||
/*int8_t fh_id = (fh0 >> 3) & 0x01;*/
|
int8_t id = (pav >> 3) & 0x01;
|
||||||
/*int8_t fh_layer = (fh0 >> 1) & 0x03;*/
|
/*int8_t layer = (pav >> 1) & 0x03;*/
|
||||||
int8_t fh_protection_absent = fh0 & 0x01;
|
int8_t protection_absent = pav & 0x01;
|
||||||
|
|
||||||
int16_t fh1 = stream->read_2bytes();
|
/**
|
||||||
// Profile_ObjectType 2 uimsbf
|
* ID: MPEG identifier, set to ‘1’ if the audio data in the ADTS stream are MPEG-2 AAC (See ISO/IEC 13818-7)
|
||||||
|
* and set to ‘0’ if the audio data are MPEG-4. See also ISO/IEC 11172-3, subclause 2.4.2.3.
|
||||||
|
*/
|
||||||
|
if (id != 0x01) {
|
||||||
|
ret = ERROR_ADTS_ID_NOT_AAC;
|
||||||
|
srs_warn("adts: id must be 1(aac), actual 0(mp4a). ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t sfiv = stream->read_2bytes();
|
||||||
|
// profile 2 uimsbf
|
||||||
// sampling_frequency_index 4 uimsbf
|
// sampling_frequency_index 4 uimsbf
|
||||||
// private_bit 1 bslbf
|
// private_bit 1 bslbf
|
||||||
// channel_configuration 3 uimsbf
|
// channel_configuration 3 uimsbf
|
||||||
// original/copy 1 bslbf
|
// original/copy 1 bslbf
|
||||||
// home 1 bslbf
|
// home 1 bslbf
|
||||||
int8_t audioObjectType = (fh1 >> 14) & 0x03;
|
int8_t profile = (sfiv >> 14) & 0x03;
|
||||||
int8_t samplingFrequencyIndex = (fh1 >> 10) & 0x0f;
|
int8_t sampling_frequency_index = (sfiv >> 10) & 0x0f;
|
||||||
/*int8_t fh_private_bit = (fh1 >> 9) & 0x01;*/
|
/*int8_t private_bit = (sfiv >> 9) & 0x01;*/
|
||||||
int8_t channelConfiguration = (fh1 >> 6) & 0x07;
|
int8_t channel_configuration = (sfiv >> 6) & 0x07;
|
||||||
/*int8_t fh_original = (fh1 >> 5) & 0x01;*/
|
/*int8_t original = (sfiv >> 5) & 0x01;*/
|
||||||
/*int8_t fh_home = (fh1 >> 4) & 0x01;*/
|
/*int8_t home = (sfiv >> 4) & 0x01;*/
|
||||||
// @remark, Emphasis is removed,
|
//int8_t Emphasis; @remark, Emphasis is removed, @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64154736
|
|
||||||
//int8_t fh_Emphasis = (fh1 >> 2) & 0x03;
|
|
||||||
// 4bits left.
|
// 4bits left.
|
||||||
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
// adts_variable_header(), 1.A.2.2.2 Variable Header of ADTS
|
||||||
// copyright_identification_bit 1 bslbf
|
// copyright_identification_bit 1 bslbf
|
||||||
// copyright_identification_start 1 bslbf
|
// copyright_identification_start 1 bslbf
|
||||||
/*int8_t fh_copyright_identification_bit = (fh1 >> 3) & 0x01;*/
|
/*int8_t fh_copyright_identification_bit = (fh1 >> 3) & 0x01;*/
|
||||||
/*int8_t fh_copyright_identification_start = (fh1 >> 2) & 0x01;*/
|
/*int8_t fh_copyright_identification_start = (fh1 >> 2) & 0x01;*/
|
||||||
// aac_frame_length 13 bslbf: Length of the frame including headers and error_check in bytes.
|
// frame_length 13 bslbf: Length of the frame including headers and error_check in bytes.
|
||||||
// use the left 2bits as the 13 and 12 bit,
|
// use the left 2bits as the 13 and 12 bit,
|
||||||
// the aac_frame_length is 13bits, so we move 13-2=11.
|
// the frame_length is 13bits, so we move 13-2=11.
|
||||||
int16_t fh_aac_frame_length = (fh1 << 11) & 0x1800;
|
int16_t frame_length = (sfiv << 11) & 0x1800;
|
||||||
|
|
||||||
int32_t fh2 = stream->read_3bytes();
|
int32_t abfv = stream->read_3bytes();
|
||||||
// aac_frame_length 13 bslbf: consume the first 13-2=11bits
|
// frame_length 13 bslbf: consume the first 13-2=11bits
|
||||||
// the fh2 is 24bits, so we move right 24-11=13.
|
// the fh2 is 24bits, so we move right 24-11=13.
|
||||||
fh_aac_frame_length |= (fh2 >> 13) & 0x07ff;
|
frame_length |= (abfv >> 13) & 0x07ff;
|
||||||
// adts_buffer_fullness 11 bslbf
|
// adts_buffer_fullness 11 bslbf
|
||||||
/*int16_t fh_adts_buffer_fullness = (fh2 >> 2) & 0x7ff;*/
|
/*int16_t fh_adts_buffer_fullness = (abfv >> 2) & 0x7ff;*/
|
||||||
// no_raw_data_blocks_in_frame 2 uimsbf
|
// number_of_raw_data_blocks_in_frame 2 uimsbf
|
||||||
/*int16_t fh_no_raw_data_blocks_in_frame = fh2 & 0x03;*/
|
/*int16_t number_of_raw_data_blocks_in_frame = abfv & 0x03;*/
|
||||||
// adts_error_check(), 1.A.2.2.3 Error detection
|
// adts_error_check(), 1.A.2.2.3 Error detection
|
||||||
if (!fh_protection_absent) {
|
if (!protection_absent) {
|
||||||
if (!stream->require(2)) {
|
if (!stream->require(2)) {
|
||||||
return ERROR_AAC_ADTS_HEADER;
|
return ERROR_AAC_ADTS_HEADER;
|
||||||
}
|
}
|
||||||
|
@ -412,47 +420,38 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame
|
||||||
/*int16_t crc_check = */stream->read_2bytes();
|
/*int16_t crc_check = */stream->read_2bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check the samplingFrequencyIndex
|
// TODO: check the sampling_frequency_index
|
||||||
// TODO: check the channelConfiguration
|
// TODO: check the channel_configuration
|
||||||
|
|
||||||
// raw_data_blocks
|
// raw_data_blocks
|
||||||
int adts_header_size = stream->pos() - adts_header_start;
|
int adts_header_size = stream->pos() - adts_header_start;
|
||||||
int raw_data_size = fh_aac_frame_length - adts_header_size;
|
int raw_data_size = frame_length - adts_header_size;
|
||||||
if (!stream->require(raw_data_size)) {
|
if (!stream->require(raw_data_size)) {
|
||||||
return ERROR_AAC_ADTS_HEADER;
|
return ERROR_AAC_ADTS_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the profile = object_id + 1
|
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
|
||||||
// Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
|
||||||
char aac_profile = audioObjectType + 1;
|
|
||||||
|
|
||||||
// the codec info.
|
// the codec info.
|
||||||
codec.protection_absent = fh_protection_absent;
|
codec.protection_absent = protection_absent;
|
||||||
codec.Profile_ObjectType = audioObjectType;
|
codec.profile = (SrsAacProfile)profile;
|
||||||
codec.sampling_frequency_index = samplingFrequencyIndex;
|
codec.sampling_frequency_index = sampling_frequency_index;
|
||||||
codec.channel_configuration = channelConfiguration;
|
codec.channel_configuration = channel_configuration;
|
||||||
codec.aac_frame_length = fh_aac_frame_length;
|
codec.frame_length = frame_length;
|
||||||
|
|
||||||
codec.aac_profile = aac_profile;
|
|
||||||
codec.aac_samplerate = samplingFrequencyIndex;
|
|
||||||
codec.aac_channel = channelConfiguration;
|
|
||||||
|
|
||||||
// @see srs_audio_write_raw_frame().
|
// @see srs_audio_write_raw_frame().
|
||||||
codec.sound_format = 10; // AAC
|
codec.sound_format = 10; // AAC
|
||||||
if (samplingFrequencyIndex <= 0x0c && samplingFrequencyIndex > 0x0a) {
|
if (sampling_frequency_index <= 0x0c && sampling_frequency_index > 0x0a) {
|
||||||
codec.sound_rate = SrsCodecAudioSampleRate5512;
|
codec.sound_rate = SrsCodecAudioSampleRate5512;
|
||||||
} else if (samplingFrequencyIndex <= 0x0a && samplingFrequencyIndex > 0x07) {
|
} else if (sampling_frequency_index <= 0x0a && sampling_frequency_index > 0x07) {
|
||||||
codec.sound_rate = SrsCodecAudioSampleRate11025;
|
codec.sound_rate = SrsCodecAudioSampleRate11025;
|
||||||
} else if (samplingFrequencyIndex <= 0x07 && samplingFrequencyIndex > 0x04) {
|
} else if (sampling_frequency_index <= 0x07 && sampling_frequency_index > 0x04) {
|
||||||
codec.sound_rate = SrsCodecAudioSampleRate22050;
|
codec.sound_rate = SrsCodecAudioSampleRate22050;
|
||||||
} else if (samplingFrequencyIndex <= 0x04) {
|
} else if (sampling_frequency_index <= 0x04) {
|
||||||
codec.sound_rate = SrsCodecAudioSampleRate44100;
|
codec.sound_rate = SrsCodecAudioSampleRate44100;
|
||||||
} else {
|
} else {
|
||||||
codec.sound_rate = SrsCodecAudioSampleRate44100;
|
codec.sound_rate = SrsCodecAudioSampleRate44100;
|
||||||
srs_warn("adts invalid sample rate for flv, rate=%#x", samplingFrequencyIndex);
|
srs_warn("adts invalid sample rate for flv, rate=%#x", sampling_frequency_index);
|
||||||
}
|
}
|
||||||
codec.sound_size = srs_max(0, srs_min(1, channelConfiguration - 1));
|
codec.sound_size = srs_max(0, srs_min(1, channel_configuration - 1));
|
||||||
// TODO: FIXME: finger it out the sound size by adts.
|
// TODO: FIXME: finger it out the sound size by adts.
|
||||||
codec.sound_size = 1; // 0(8bits) or 1(16bits).
|
codec.sound_size = 1; // 0(8bits) or 1(16bits).
|
||||||
|
|
||||||
|
@ -472,16 +471,13 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// only support aac profile 1-4.
|
// only support aac profile 1-4.
|
||||||
if (codec->aac_profile < 1 || codec->aac_profile > 4) {
|
if (codec->profile == SrsAacProfileReserved) {
|
||||||
return ERROR_AAC_DATA_INVALID;
|
return ERROR_AAC_DATA_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the profile = object_id + 1
|
SrsAacObjectType audioObjectType = srs_codec_aac_ts2rtmp(codec->profile);
|
||||||
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78,
|
char channelConfiguration = codec->channel_configuration;
|
||||||
// Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
|
char samplingFrequencyIndex = codec->sampling_frequency_index;
|
||||||
char profile_ObjectType = codec->aac_profile - 1;
|
|
||||||
char channelConfiguration = codec->aac_channel;
|
|
||||||
char samplingFrequencyIndex = codec->aac_samplerate;
|
|
||||||
|
|
||||||
// override the aac samplerate by user specified.
|
// override the aac samplerate by user specified.
|
||||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64146899
|
// @see https://github.com/winlinvip/simple-rtmp-server/issues/212#issuecomment-64146899
|
||||||
|
@ -503,7 +499,7 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
|
||||||
// AudioSpecificConfig (), page 33
|
// AudioSpecificConfig (), page 33
|
||||||
// 1.6.2.1 AudioSpecificConfig
|
// 1.6.2.1 AudioSpecificConfig
|
||||||
// audioObjectType; 5 bslbf
|
// audioObjectType; 5 bslbf
|
||||||
ch = (profile_ObjectType << 3) & 0xf8;
|
ch = (audioObjectType << 3) & 0xf8;
|
||||||
// 3bits left.
|
// 3bits left.
|
||||||
|
|
||||||
// samplingFrequencyIndex; 4 bslbf
|
// samplingFrequencyIndex; 4 bslbf
|
||||||
|
|
|
@ -32,6 +32,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <srs_kernel_codec.hpp>
|
||||||
|
|
||||||
class SrsStream;
|
class SrsStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,15 +94,10 @@ public:
|
||||||
struct SrsRawAacStreamCodec
|
struct SrsRawAacStreamCodec
|
||||||
{
|
{
|
||||||
int8_t protection_absent;
|
int8_t protection_absent;
|
||||||
int8_t Profile_ObjectType;
|
SrsAacProfile profile;
|
||||||
int8_t sampling_frequency_index;
|
int8_t sampling_frequency_index;
|
||||||
int8_t channel_configuration;
|
int8_t channel_configuration;
|
||||||
int16_t aac_frame_length;
|
int16_t frame_length;
|
||||||
|
|
||||||
// calc by Profile_ObjectType+1
|
|
||||||
char aac_profile;
|
|
||||||
char aac_samplerate;
|
|
||||||
char aac_channel;
|
|
||||||
|
|
||||||
char sound_format;
|
char sound_format;
|
||||||
char sound_rate;
|
char sound_rate;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue