for #310, workaround to force to LC/MAIN, donot support SSR above. 2.0.113

pull/133/head
winlin 10 years ago
parent f8bdd28de6
commit 4820d455d5

@ -309,6 +309,12 @@ int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsSimpleBuffer* ab)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// if flushed yet, ignore.
if (ab->length() == 0) {
srs_info("ignore hls segment audio flushed yet.");
return ret;
}
// if current is NULL, segment is not open, ignore the flush event. // if current is NULL, segment is not open, ignore the flush event.
if (!current) { if (!current) {
srs_warn("flush audio ignored, for segment is not open."); srs_warn("flush audio ignored, for segment is not open.");
@ -336,6 +342,12 @@ int SrsHlsMuxer::flush_video(SrsMpegtsFrame* /*af*/, SrsSimpleBuffer* /*ab*/, Sr
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// if flushed yet, ignore.
if (vb->length() == 0) {
srs_info("ignore hls segment video flushed yet.");
return ret;
}
// if current is NULL, segment is not open, ignore the flush event. // if current is NULL, segment is not open, ignore the flush event.
if (!current) { if (!current) {
srs_warn("flush video ignored, for segment is not open."); srs_warn("flush video ignored, for segment is not open.");
@ -776,6 +788,13 @@ int SrsHlsCache::reap_segment(string log_desc, SrsHlsMuxer* muxer, int64_t segme
} }
// TODO: flush audio before or after segment? // TODO: flush audio before or after segment?
// segment open, flush video first.
if ((ret = muxer->flush_video(cache->af, cache->ab, cache->vf, cache->vb)) != ERROR_SUCCESS) {
srs_error("m3u8 muxer flush video failed. ret=%d", ret);
return ret;
}
// segment open, flush the audio. // segment open, flush the audio.
// @see: ngx_rtmp_hls_open_fragment // @see: ngx_rtmp_hls_open_fragment
/* start fragment with audio to make iPhone happy */ /* start fragment with audio to make iPhone happy */

@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version // current release version
#define VERSION_MAJOR 2 #define VERSION_MAJOR 2
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 112 #define VERSION_REVISION 113
// server info. // server info.
#define RTMP_SIG_SRS_KEY "SRS" #define RTMP_SIG_SRS_KEY "SRS"

@ -281,25 +281,41 @@ int SrsAvcAacCodec::audio_aac_demux(char* data, int size, SrsCodecSample* sample
} }
// only need to decode the first 2bytes: // only need to decode the first 2bytes:
// audioObjectType, aac_profile, 5bits. // audioObjectType, aac_profile, 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)) {
ret = ERROR_HLS_DECODE_ERROR; ret = ERROR_HLS_DECODE_ERROR;
srs_error("audio codec decode aac sequence header failed. ret=%d", ret); srs_error("audio codec decode aac sequence header failed. ret=%d", ret);
return ret; return ret;
} }
aac_profile = stream->read_1bytes(); u_int8_t profile_ObjectType = stream->read_1bytes();
aac_sample_rate = stream->read_1bytes(); u_int8_t samplingFrequencyIndex = stream->read_1bytes();
aac_channels = (aac_sample_rate >> 3) & 0x0f; aac_channels = (samplingFrequencyIndex >> 3) & 0x0f;
aac_sample_rate = ((aac_profile << 1) & 0x0e) | ((aac_sample_rate >> 7) & 0x01); samplingFrequencyIndex = ((profile_ObjectType << 1) & 0x0e) | ((samplingFrequencyIndex >> 7) & 0x01);
aac_profile = (aac_profile >> 3) & 0x1f; profile_ObjectType = (profile_ObjectType >> 3) & 0x1f;
if (aac_profile == 0 || aac_profile == 0x1f) { // set the aac sample rate.
aac_sample_rate = samplingFrequencyIndex;
// 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
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", aac_profile, ret); "adts object=%d invalid. ret=%d", profile_ObjectType, ret);
return ret; return ret;
} }

@ -1990,6 +1990,20 @@ int SrsTsCache::do_cache_audio(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;
@ -2022,7 +2036,7 @@ int SrsTsCache::do_cache_audio(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] = (codec->aac_profile << 6) & 0xc0; adts_header[2] = (profile_ObjectType << 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

@ -375,10 +375,10 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame
// 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 = (fh1 >> 14) & 0x03; int8_t audioObjectType = (fh1 >> 14) & 0x03;
int8_t fh_sampling_frequency_index = (fh1 >> 10) & 0x0f; int8_t samplingFrequencyIndex = (fh1 >> 10) & 0x0f;
/*int8_t fh_private_bit = (fh1 >> 9) & 0x01;*/ /*int8_t fh_private_bit = (fh1 >> 9) & 0x01;*/
int8_t fh_channel_configuration = (fh1 >> 6) & 0x07; int8_t channelConfiguration = (fh1 >> 6) & 0x07;
/*int8_t fh_original = (fh1 >> 5) & 0x01;*/ /*int8_t fh_original = (fh1 >> 5) & 0x01;*/
/*int8_t fh_home = (fh1 >> 4) & 0x01;*/ /*int8_t fh_home = (fh1 >> 4) & 0x01;*/
// @remark, Emphasis is removed, // @remark, Emphasis is removed,
@ -412,8 +412,8 @@ 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 fh_sampling_frequency_index // TODO: check the samplingFrequencyIndex
// TODO: check the fh_channel_configuration // TODO: check the channelConfiguration
// raw_data_blocks // raw_data_blocks
int adts_header_size = stream->pos() - adts_header_start; int adts_header_size = stream->pos() - adts_header_start;
@ -425,34 +425,34 @@ int SrsRawAacStream::adts_demux(SrsStream* stream, char** pframe, int* pnb_frame
// the profile = object_id + 1 // the profile = object_id + 1
// @see aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 78, // @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 // Table 1. A.9 ¨C MPEG-2 Audio profiles and MPEG-4 Audio object types
char aac_profile = fh_Profile_ObjectType + 1; char aac_profile = audioObjectType + 1;
// the codec info. // the codec info.
codec.protection_absent = fh_protection_absent; codec.protection_absent = fh_protection_absent;
codec.Profile_ObjectType = fh_Profile_ObjectType; codec.Profile_ObjectType = audioObjectType;
codec.sampling_frequency_index = fh_sampling_frequency_index; codec.sampling_frequency_index = samplingFrequencyIndex;
codec.channel_configuration = fh_channel_configuration; codec.channel_configuration = channelConfiguration;
codec.aac_frame_length = fh_aac_frame_length; codec.aac_frame_length = fh_aac_frame_length;
codec.aac_profile = aac_profile; codec.aac_profile = aac_profile;
codec.aac_samplerate = fh_sampling_frequency_index; codec.aac_samplerate = samplingFrequencyIndex;
codec.aac_channel = fh_channel_configuration; 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 (fh_sampling_frequency_index <= 0x0c && fh_sampling_frequency_index > 0x0a) { if (samplingFrequencyIndex <= 0x0c && samplingFrequencyIndex > 0x0a) {
codec.sound_rate = SrsCodecAudioSampleRate5512; codec.sound_rate = SrsCodecAudioSampleRate5512;
} else if (fh_sampling_frequency_index <= 0x0a && fh_sampling_frequency_index > 0x07) { } else if (samplingFrequencyIndex <= 0x0a && samplingFrequencyIndex > 0x07) {
codec.sound_rate = SrsCodecAudioSampleRate11025; codec.sound_rate = SrsCodecAudioSampleRate11025;
} else if (fh_sampling_frequency_index <= 0x07 && fh_sampling_frequency_index > 0x04) { } else if (samplingFrequencyIndex <= 0x07 && samplingFrequencyIndex > 0x04) {
codec.sound_rate = SrsCodecAudioSampleRate22050; codec.sound_rate = SrsCodecAudioSampleRate22050;
} else if (fh_sampling_frequency_index <= 0x04) { } else if (samplingFrequencyIndex <= 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", fh_sampling_frequency_index); srs_warn("adts invalid sample rate for flv, rate=%#x", samplingFrequencyIndex);
} }
codec.sound_size = srs_max(0, srs_min(1, fh_channel_configuration - 1)); codec.sound_size = srs_max(0, srs_min(1, channelConfiguration - 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).
@ -471,19 +471,27 @@ int SrsRawAacStream::mux_sequence_header(SrsRawAacStreamCodec* codec, string& sh
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
char aac_channel = codec->aac_channel; // only support aac profile 1-4.
char aac_profile = codec->aac_profile; if (codec->aac_profile < 1 || codec->aac_profile > 4) {
char aac_samplerate = codec->aac_samplerate; return ERROR_AAC_DATA_INVALID;
}
// 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 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
switch (codec->sound_rate) { switch (codec->sound_rate) {
case SrsCodecAudioSampleRate11025: case SrsCodecAudioSampleRate11025:
aac_samplerate = 0x0a; break; samplingFrequencyIndex = 0x0a; break;
case SrsCodecAudioSampleRate22050: case SrsCodecAudioSampleRate22050:
aac_samplerate = 0x07; break; samplingFrequencyIndex = 0x07; break;
case SrsCodecAudioSampleRate44100: case SrsCodecAudioSampleRate44100:
aac_samplerate = 0x04; break; samplingFrequencyIndex = 0x04; break;
default: default:
break; break;
} }
@ -495,26 +503,22 @@ 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 = (aac_profile << 3) & 0xf8; ch = (profile_ObjectType << 3) & 0xf8;
// 3bits left. // 3bits left.
// samplingFrequencyIndex; 4 bslbf // samplingFrequencyIndex; 4 bslbf
ch |= (aac_samplerate >> 1) & 0x07; ch |= (samplingFrequencyIndex >> 1) & 0x07;
sh += ch; sh += ch;
ch = (aac_samplerate << 7) & 0x80; ch = (samplingFrequencyIndex << 7) & 0x80;
if (aac_samplerate == 0x0f) { if (samplingFrequencyIndex == 0x0f) {
return ERROR_AAC_DATA_INVALID; return ERROR_AAC_DATA_INVALID;
} }
// 7bits left. // 7bits left.
// channelConfiguration; 4 bslbf // channelConfiguration; 4 bslbf
ch |= (aac_channel << 3) & 0x78; ch |= (channelConfiguration << 3) & 0x78;
// 3bits left. // 3bits left.
// only support aac profile 1-4.
if (aac_profile < 1 || aac_profile > 4) {
return ERROR_AAC_DATA_INVALID;
}
// GASpecificConfig(), page 451 // GASpecificConfig(), page 451
// 4.4.1 Decoder configuration (GASpecificConfig) // 4.4.1 Decoder configuration (GASpecificConfig)
// frameLengthFlag; 1 bslbf // frameLengthFlag; 1 bslbf

Loading…
Cancel
Save