@ -146,6 +146,86 @@ static int get_ilbc_mode(AVCodecContext *avctx)
return 30 ;
}
static av_cold int get_channel_label ( int channel )
{
uint64_t map = 1 < < channel ;
if ( map < = AV_CH_LOW_FREQUENCY )
return channel + 1 ;
else if ( map < = AV_CH_BACK_RIGHT )
return channel + 29 ;
else if ( map < = AV_CH_BACK_CENTER )
return channel - 1 ;
else if ( map < = AV_CH_SIDE_RIGHT )
return channel - 4 ;
else if ( map < = AV_CH_TOP_BACK_RIGHT )
return channel + 1 ;
else if ( map < = AV_CH_STEREO_RIGHT )
return - 1 ;
else if ( map < = AV_CH_WIDE_RIGHT )
return channel + 4 ;
else if ( map < = AV_CH_SURROUND_DIRECT_RIGHT )
return channel - 23 ;
else if ( map = = AV_CH_LOW_FREQUENCY_2 )
return kAudioChannelLabel_LFE2 ;
else
return - 1 ;
}
static int remap_layout ( AudioChannelLayout * layout , uint64_t in_layout , int count )
{
int i ;
int c = 0 ;
layout - > mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions ;
layout - > mNumberChannelDescriptions = count ;
for ( i = 0 ; i < count ; i + + ) {
int label ;
while ( ! ( in_layout & ( 1 < < c ) ) & & c < 64 )
c + + ;
if ( c = = 64 )
return AVERROR ( EINVAL ) ; // This should never happen
label = get_channel_label ( c ) ;
layout - > mChannelDescriptions [ i ] . mChannelLabel = label ;
if ( label < 0 )
return AVERROR ( EINVAL ) ;
c + + ;
}
return 0 ;
}
static int get_aac_tag ( uint64_t in_layout )
{
switch ( in_layout ) {
case AV_CH_LAYOUT_MONO :
return kAudioChannelLayoutTag_Mono ;
case AV_CH_LAYOUT_STEREO :
return kAudioChannelLayoutTag_Stereo ;
case AV_CH_LAYOUT_QUAD :
return kAudioChannelLayoutTag_AAC_Quadraphonic ;
case AV_CH_LAYOUT_OCTAGONAL :
return kAudioChannelLayoutTag_AAC_Octagonal ;
case AV_CH_LAYOUT_SURROUND :
return kAudioChannelLayoutTag_AAC_3_0 ;
case AV_CH_LAYOUT_4POINT0 :
return kAudioChannelLayoutTag_AAC_4_0 ;
case AV_CH_LAYOUT_5POINT0 :
return kAudioChannelLayoutTag_AAC_5_0 ;
case AV_CH_LAYOUT_5POINT1 :
return kAudioChannelLayoutTag_AAC_5_1 ;
case AV_CH_LAYOUT_6POINT0 :
return kAudioChannelLayoutTag_AAC_6_0 ;
case AV_CH_LAYOUT_6POINT1 :
return kAudioChannelLayoutTag_AAC_6_1 ;
case AV_CH_LAYOUT_7POINT0 :
return kAudioChannelLayoutTag_AAC_7_0 ;
case AV_CH_LAYOUT_7POINT1_WIDE_BACK :
return kAudioChannelLayoutTag_AAC_7_1 ;
case AV_CH_LAYOUT_7POINT1 :
return kAudioChannelLayoutTag_MPEG_7_1_C ;
default :
return 0 ;
}
}
static av_cold int ffat_init_encoder ( AVCodecContext * avctx )
{
ATDecodeContext * at = avctx - > priv_data ;
@ -170,11 +250,12 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
. mFormatID = ffat_get_format_id ( avctx - > codec_id , avctx - > profile ) ,
. mChannelsPerFrame = in_format . mChannelsPerFrame ,
} ;
AudioChannelLayout channel_layout = {
. mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap ,
. mChannelBitmap = avctx - > channel_layout ,
} ;
UInt32 size = sizeof ( channel_layout ) ;
UInt32 layout_size = sizeof ( AudioChannelLayout ) +
sizeof ( AudioChannelDescription ) * avctx - > channels ;
AudioChannelLayout * channel_layout = av_malloc ( layout_size ) ;
if ( ! channel_layout )
return AVERROR ( ENOMEM ) ;
if ( avctx - > codec_id = = AV_CODEC_ID_ILBC ) {
int mode = get_ilbc_mode ( avctx ) ;
@ -186,22 +267,45 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
if ( status ! = 0 ) {
av_log ( avctx , AV_LOG_ERROR , " AudioToolbox init error: %i \n " , ( int ) status ) ;
av_free ( channel_layout ) ;
return AVERROR_UNKNOWN ;
}
size = sizeof ( UInt32 ) ;
if ( ! avctx - > channel_layout )
avctx - > channel_layout = av_get_default_channel_layout ( avctx - > channels ) ;
if ( ( status = remap_layout ( channel_layout , avctx - > channel_layout , avctx - > channels ) ) < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " Invalid channel layout \n " ) ;
av_free ( channel_layout ) ;
return status ;
}
AudioConverterSetProperty ( at - > converter , kAudioConverterInputChannelLayout ,
size , & channel_layout ) ;
AudioConverterSetProperty ( at - > converter , kAudioConverterOutputChannelLayout ,
size , & channel_layout ) ;
if ( AudioConverterSetProperty ( at - > converter , kAudioConverterInputChannelLayout ,
layout_size , channel_layout ) ) {
av_log ( avctx , AV_LOG_ERROR , " Unsupported input channel layout \n " ) ;
av_free ( channel_layout ) ;
return AVERROR ( EINVAL ) ;
}
if ( avctx - > codec_id = = AV_CODEC_ID_AAC ) {
int tag = get_aac_tag ( avctx - > channel_layout ) ;
if ( tag ) {
channel_layout - > mChannelLayoutTag = tag ;
channel_layout - > mNumberChannelDescriptions = 0 ;
}
}
if ( AudioConverterSetProperty ( at - > converter , kAudioConverterOutputChannelLayout ,
layout_size , channel_layout ) ) {
av_log ( avctx , AV_LOG_ERROR , " Unsupported output channel layout \n " ) ;
av_free ( channel_layout ) ;
return AVERROR ( EINVAL ) ;
}
av_free ( channel_layout ) ;
if ( avctx - > bits_per_raw_sample ) {
size = sizeof ( avctx - > bits_per_raw_sample ) ;
if ( avctx - > bits_per_raw_sample )
AudioConverterSetProperty ( at - > converter ,
kAudioConverterPropertyBitDepthHint ,
size , & avctx - > bits_per_raw_sample ) ;
}
sizeof ( avctx - > bits_per_raw_sample ) ,
& avctx - > bits_per_raw_sample ) ;
if ( at - > mode = = - 1 )
at - > mode = ( avctx - > flags & AV_CODEC_FLAG_QSCALE ) ?
@ -209,7 +313,7 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
kAudioCodecBitRateControlMode_Constant ;
AudioConverterSetProperty ( at - > converter , kAudioCodecPropertyBitRateControlMode ,
size , & at - > mode ) ;
sizeof ( at - > mode ) , & at - > mode ) ;
if ( at - > mode = = kAudioCodecBitRateControlMode_Variable ) {
int q = avctx - > global_quality / FF_QP2LAMBDA ;
@ -220,16 +324,50 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
}
q = 127 - q * 9 ;
AudioConverterSetProperty ( at - > converter , kAudioCodecPropertySoundQualityForVBR ,
size , & q ) ;
sizeof ( q ) , & q ) ;
} else if ( avctx - > bit_rate > 0 ) {
UInt32 rate = avctx - > bit_rate ;
UInt32 size ;
status = AudioConverterGetPropertyInfo ( at - > converter ,
kAudioConverterApplicableEncodeBitRates ,
& size , NULL ) ;
if ( ! status & & size ) {
UInt32 new_rate = rate ;
int count ;
int i ;
AudioValueRange * ranges = av_malloc ( size ) ;
if ( ! ranges )
return AVERROR ( ENOMEM ) ;
AudioConverterGetProperty ( at - > converter ,
kAudioConverterApplicableEncodeBitRates ,
& size , ranges ) ;
count = size / sizeof ( AudioValueRange ) ;
for ( i = 0 ; i < count ; i + + ) {
AudioValueRange * range = & ranges [ i ] ;
if ( rate > = range - > mMinimum & & rate < = range - > mMaximum ) {
new_rate = rate ;
break ;
} else if ( rate > range - > mMaximum ) {
new_rate = range - > mMaximum ;
} else {
new_rate = range - > mMinimum ;
break ;
}
}
if ( new_rate ! = rate ) {
av_log ( avctx , AV_LOG_WARNING ,
" Bitrate %u not allowed; changing to %u \n " , rate , new_rate ) ;
rate = new_rate ;
}
av_free ( ranges ) ;
}
AudioConverterSetProperty ( at - > converter , kAudioConverterEncodeBitRate ,
size , & rate ) ;
sizeof ( rate ) , & rate ) ;
}
at - > quality = 96 - at - > quality * 32 ;
AudioConverterSetProperty ( at - > converter , kAudioConverterCodecQuality ,
size , & at - > quality ) ;
sizeof ( at - > quality ) , & at - > quality ) ;
if ( ! AudioConverterGetPropertyInfo ( at - > converter , kAudioConverterCompressionMagicCookie ,
& avctx - > extradata_size , NULL ) & &
@ -289,10 +427,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
# if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
if ( at - > mode = = kAudioCodecBitRateControlMode_Variable & & avctx - > rc_max_rate ) {
int max_size = avctx - > rc_max_rate * avctx - > frame_size / avctx - > sample_rate ;
UInt32 max_size = avctx - > rc_max_rate * avctx - > frame_size / avctx - > sample_rate ;
if ( max_size )
AudioConverterSetProperty ( at - > converter , kAudioCodecPropertyPacketSizeLimitForVBR ,
size , & max_size ) ;
AudioConverterSetProperty ( at - > converter , kAudioCodecPropertyPacketSizeLimitForVBR ,
sizeof ( max_ size ) , & max_size ) ;
}
# endif
@ -455,7 +593,23 @@ static const AVOption options[] = {
. profiles = PROFILES , \
} ;
FFAT_ENC ( aac , AV_CODEC_ID_AAC , aac_profiles )
static const uint64_t aac_at_channel_layouts [ ] = {
AV_CH_LAYOUT_MONO ,
AV_CH_LAYOUT_STEREO ,
AV_CH_LAYOUT_SURROUND ,
AV_CH_LAYOUT_4POINT0 ,
AV_CH_LAYOUT_5POINT0 ,
AV_CH_LAYOUT_5POINT1 ,
AV_CH_LAYOUT_6POINT0 ,
AV_CH_LAYOUT_6POINT1 ,
AV_CH_LAYOUT_7POINT0 ,
AV_CH_LAYOUT_7POINT1_WIDE_BACK ,
AV_CH_LAYOUT_QUAD ,
AV_CH_LAYOUT_OCTAGONAL ,
0 ,
} ;
FFAT_ENC ( aac , AV_CODEC_ID_AAC , aac_profiles , , . channel_layouts = aac_at_channel_layouts )
//FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL)
FFAT_ENC ( alac , AV_CODEC_ID_ALAC , NULL , | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | AV_CODEC_CAP_LOSSLESS )
FFAT_ENC ( ilbc , AV_CODEC_ID_ILBC , NULL )