summaryrefslogtreecommitdiffstats
path: root/contrib/faac
diff options
context:
space:
mode:
authorRodeo <[email protected]>2012-09-03 12:37:16 +0000
committerRodeo <[email protected]>2012-09-03 12:37:16 +0000
commit8d9969febdcec59fee453888ed0bb6a64adf7679 (patch)
treedbe81e961c2ed4c0f3e38d44c5afa86cc475693a /contrib/faac
parent56bf9b80b9b55ecaec9855addda41898261d26b1 (diff)
Audio improvements.
New supported samplerates: 8, 11.025, 12, 16 kHz. Now 8, 11.025, 12, 16, 22.05, 24, 42, 44.1, 48 Khz are supported. Unsupported samplerates are sanitized to the closest samplerate for all encoders. Samplerates < 32 kHz are now forbidden for AC3 encoding (sanitized to 32 kHz). Most AC3 decoders don't support such samplerates. New upmixing: 3.0 (Front Left, Right & Center) can now be upmixed to 5.1 to preserve the center channel. New mixdowns: 6.1 (Front Left, Right & Center, Surround Left, Right & Center, LFE) 7.1 (Front Left, Right & Center, Surround Left & Right, Rear Left & Right, LFE) -> available to Vorbis & FLAC encoders for compatible input channel layouts 7.1 (Front Left, Right & Center, Front Left & Right of Center, Surround Left & Right, LFE) -> available to AAC encoders (ca_aac, ca_haac, faac) for compatible input channel layouts Mono (Left Only): Stereo to Mono by discarding the Right channel Mono (Right Only): Stereo to Mono by discarding the Left channel -> available to all encoders for non-Dolby Stereo input The "6-channel discrete" mixdown becomes "5.1 Channels". New bitrates: 960 - 1536 Kbps. This lets users work around poor audio quality in crappy encoders by throwing more bits at them. Bitrate limits have been re-worked and re-tested for all encoders. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4930 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'contrib/faac')
-rw-r--r--contrib/faac/A00-bitrates.patch6
-rw-r--r--contrib/faac/A01-multichannel-improvements.patch752
-rw-r--r--contrib/faac/P00-cygwin.patch6
3 files changed, 758 insertions, 6 deletions
diff --git a/contrib/faac/A00-bitrates.patch b/contrib/faac/A00-bitrates.patch
index 50b11ec78..49460768e 100644
--- a/contrib/faac/A00-bitrates.patch
+++ b/contrib/faac/A00-bitrates.patch
@@ -1,6 +1,6 @@
-diff -Naur faac-1.28/libfaac/frame.c ../build.debug/contrib/faac/faac-1.28/libfaac/frame.c
---- faac-1.28.orig/libfaac/frame.c 2004-11-17 06:26:06.000000000 -0800
-+++ faac-1.28/libfaac/frame.c 2010-04-10 12:26:28.200614437 -0700
+diff -Naur faac-1.28.old/libfaac/frame.c faac-1.28.new/libfaac/frame.c
+--- faac-1.28.old/libfaac/frame.c 2004-11-17 06:26:06.000000000 -0800
++++ faac-1.28.new/libfaac/frame.c 2010-04-10 12:26:28.200614437 -0700
@@ -196,6 +196,8 @@
{47000, 10000},
{64000, 16000},
diff --git a/contrib/faac/A01-multichannel-improvements.patch b/contrib/faac/A01-multichannel-improvements.patch
new file mode 100644
index 000000000..d0ec5ce3c
--- /dev/null
+++ b/contrib/faac/A01-multichannel-improvements.patch
@@ -0,0 +1,752 @@
+diff -Naur faac-1.28.old/frontend/main.c faac-1.28.new/frontend/main.c
+--- faac-1.28.old/frontend/main.c 2009-01-24 02:10:20.000000000 +0100
++++ faac-1.28.new/frontend/main.c 2012-08-06 21:15:34.000000000 +0200
+@@ -858,7 +858,7 @@
+ break;
+ }
+ if (infile->channels >= 6)
+- myFormat->useLfe = 1;
++ myFormat->numLFEChannels = 1;
+ myFormat->allowMidside = useMidSide;
+ if (bitRate)
+ myFormat->bitRate = bitRate / infile->channels;
+diff -Naur faac-1.28.old/include/faaccfg.h faac-1.28.new/include/faaccfg.h
+--- faac-1.28.old/include/faaccfg.h 2004-07-04 14:12:05.000000000 +0200
++++ faac-1.28.new/include/faaccfg.h 2012-08-06 21:15:34.000000000 +0200
+@@ -66,8 +66,14 @@
+ /* Allow mid/side coding */
+ unsigned int allowMidside;
+
+- /* Use one of the channels as LFE channel */
+- unsigned int useLfe;
++ /* Channel configuration */
++ unsigned int channelConfiguration;
++
++ /* Number of front, side, back & LFE channels */
++ unsigned int numFrontChannels;
++ unsigned int numSideChannels;
++ unsigned int numBackChannels;
++ unsigned int numLFEChannels;
+
+ /* Use Temporal Noise Shaping */
+ unsigned int useTns;
+diff -Naur faac-1.28.old/libfaac/bitstream.c faac-1.28.new/libfaac/bitstream.c
+--- faac-1.28.old/libfaac/bitstream.c 2007-06-05 20:59:47.000000000 +0200
++++ faac-1.28.new/libfaac/bitstream.c 2012-08-06 21:15:34.000000000 +0200
+@@ -1032,6 +1032,219 @@
+ return j;
+ }
+
++/* write a program_config_element() */
++int WritePCE(faacEncHandle hEncoder,
++ BitStream *bitStream,
++ int byte_alignment,
++ int instance_tag,
++ int writeFlag)
++{
++ int i;
++ int bits = 0;
++
++ /* we can have up to 29 full-bandwidth channels of each type:
++ * 4 bits -> 0 - 15 elements, 14 CPEs (28 channels) and 1 SCE (1 channel)
++ * we can have up to 3 LFE channels:
++ * 2 bits -> 0 - 3 elements, 3 LFEs (1 channel) */
++ if (hEncoder->config.numFrontChannels > 29) {
++ fprintf(stderr, "WritePCE: too many front channels (%u)\n",
++ hEncoder->config.numFrontChannels);
++ return 0;
++ }
++ if (hEncoder->config.numSideChannels > 29) {
++ fprintf(stderr, "WritePCE: too many side channels (%u)\n",
++ hEncoder->config.numSideChannels);
++ return 0;
++ }
++ if (hEncoder->config.numBackChannels > 29) {
++ fprintf(stderr, "WritePCE: too many back channels (%u)\n",
++ hEncoder->config.numBackChannels);
++ return 0;
++ }
++ if (hEncoder->config.numLFEChannels > 3) {
++ fprintf(stderr, "WritePCE: too many LFE channels (%u)\n",
++ hEncoder->config.numLFEChannels);
++ return 0;
++ }
++ /* program_config_element() shall be used only for the audio object types:
++ * AAC main, AAC SSR, AAC LC and AAC LTP */
++ if (hEncoder->config.aacObjectType > 4) {
++ fprintf(stderr, "WritePCE: unsupported AudioObjectType %u",
++ hEncoder->config.aacObjectType);
++ return 0;
++ }
++
++ /* Determine the channel configuration (see GetChannelInfo) */
++ int sceTag = 0;
++ int cpeTag = 0;
++ int lfeTag = 0;
++ int num_front_channel_elements = 0;
++ int front_element_is_cpe[15] = { 0 };
++ int front_element_tag_select[15] = { 0 };
++ int num_side_channel_elements = 0;
++ int side_element_is_cpe[15] = { 0 };
++ int side_element_tag_select[15] = { 0 };
++ int num_back_channel_elements = 0;
++ int back_element_is_cpe[15] = { 0 };
++ int back_element_tag_select[15] = { 0 };
++ int num_lfe_channel_elements = 0;
++ int lfe_element_tag_select[3] = { 0 };
++ // Front channels
++ i = hEncoder->config.numFrontChannels;
++ if (i % 2) {
++ front_element_is_cpe[num_front_channel_elements] = 0;
++ front_element_tag_select[num_front_channel_elements] = sceTag;
++ num_front_channel_elements++;
++ sceTag++;
++ i--;
++ }
++ while (i) {
++ front_element_is_cpe[num_front_channel_elements] = 1;
++ front_element_tag_select[num_front_channel_elements] = cpeTag;
++ num_front_channel_elements++;
++ cpeTag++;
++ i -= 2;
++ }
++ // Side channels
++ i = hEncoder->config.numSideChannels;
++ while (i > 1) {
++ side_element_is_cpe[num_side_channel_elements] = 1;
++ side_element_tag_select[num_side_channel_elements] = cpeTag;
++ num_side_channel_elements++;
++ cpeTag++;
++ i -= 2;
++ }
++ if (i) {
++ side_element_is_cpe[num_side_channel_elements] = 0;
++ side_element_tag_select[num_side_channel_elements] = sceTag;
++ num_side_channel_elements++;
++ sceTag++;
++ i--;
++ }
++ // Back channels
++ i = hEncoder->config.numBackChannels;
++ while (i > 1) {
++ back_element_is_cpe[num_back_channel_elements] = 1;
++ back_element_tag_select[num_back_channel_elements] = cpeTag;
++ num_back_channel_elements++;
++ cpeTag++;
++ i -= 2;
++ }
++ if (i) {
++ back_element_is_cpe[num_back_channel_elements] = 0;
++ back_element_tag_select[num_back_channel_elements] = sceTag;
++ num_back_channel_elements++;
++ sceTag++;
++ i--;
++ }
++ // LFE channels
++ i = hEncoder->config.numLFEChannels;
++ while (i) {
++ lfe_element_tag_select[num_lfe_channel_elements] = lfeTag;
++ num_lfe_channel_elements++;
++ lfeTag++;
++ i--;
++ }
++
++ /* element_instance_tag */
++ if (writeFlag)
++ PutBit(bitStream, instance_tag, 4);
++ bits =+ 4;
++
++ /* object_type */
++ if (writeFlag)
++ PutBit(bitStream, hEncoder->config.aacObjectType - 1, 2);
++ bits += 2;
++
++ /* sampling_frequency_index */
++ if (writeFlag)
++ PutBit(bitStream, hEncoder->sampleRateIdx, 4);
++ bits += 4;
++
++ /* num_front_channel_elements */
++ if (writeFlag)
++ PutBit(bitStream, num_front_channel_elements, 4);
++ bits += 4;
++
++ /* num_side_channel_elements */
++ if (writeFlag)
++ PutBit(bitStream, num_side_channel_elements, 4);
++ bits += 4;
++
++ /* num_back_channel_elements */
++ if (writeFlag)
++ PutBit(bitStream, num_back_channel_elements, 4);
++ bits += 4;
++
++ /* num_lfe_channel_elements */
++ if (writeFlag)
++ PutBit(bitStream, num_lfe_channel_elements, 2);
++ bits += 2;
++
++ /* num_assoc_data_elements */
++ if (writeFlag)
++ PutBit(bitStream, 0, 3);
++ bits += 3;
++
++ /* num_valid_cc_elements */
++ if (writeFlag)
++ PutBit(bitStream, 0, 4);
++ bits += 4;
++
++ /* mono_mixdown_present */
++ if (writeFlag)
++ PutBit(bitStream, 0, 1);
++ bits++;
++
++ /* stereo_mixdown_present */
++ if (writeFlag)
++ PutBit(bitStream, 0, 1);
++ bits++;
++
++ /* matrix_mixdown_idx_present */
++ if (writeFlag)
++ PutBit(bitStream, 0, 1);
++ bits++;
++
++ /* describe the channel configuration */
++ for (i = 0; i < num_front_channel_elements; i++) {
++ if (writeFlag) {
++ PutBit(bitStream, front_element_is_cpe[i], 1);
++ PutBit(bitStream, front_element_tag_select[i], 4);
++ }
++ bits += 5;
++ }
++ for (i = 0; i < num_side_channel_elements; i++) {
++ if (writeFlag) {
++ PutBit(bitStream, side_element_is_cpe[i], 1);
++ PutBit(bitStream, side_element_tag_select[i], 4);
++ }
++ bits += 5;
++ }
++ for (i = 0; i < num_back_channel_elements; i++) {
++ if (writeFlag) {
++ PutBit(bitStream, back_element_is_cpe[i], 1);
++ PutBit(bitStream, back_element_tag_select[i], 4);
++ }
++ bits += 5;
++ }
++ for (i = 0; i < num_lfe_channel_elements; i++) {
++ if (writeFlag)
++ PutBit(bitStream, lfe_element_tag_select[i], 4);
++ bits += 4;
++ }
++
++ /* byte_alignment() */
++ bits += ByteAlign(bitStream, writeFlag, bits + byte_alignment);
++
++ /* comment_field_bytes */
++ if (writeFlag)
++ PutBit(bitStream, 0, 8);
++ bits += 8;
++
++ return bits;
++}
++
+ #ifdef DRM
+ /*
+ ****************************************************************************
+diff -Naur faac-1.28.old/libfaac/bitstream.h faac-1.28.new/libfaac/bitstream.h
+--- faac-1.28.old/libfaac/bitstream.h 2004-07-04 14:10:52.000000000 +0200
++++ faac-1.28.new/libfaac/bitstream.h 2012-08-06 21:15:34.000000000 +0200
+@@ -164,6 +164,13 @@
+ unsigned long data,
+ int numBit);
+
++/* write a program_config_element() */
++int WritePCE(faacEncHandle hEncoder,
++ BitStream *bitStream,
++ int byte_alignment,
++ int instance_tag,
++ int writeFlag);
++
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+diff -Naur faac-1.28.old/libfaac/channels.c faac-1.28.new/libfaac/channels.c
+--- faac-1.28.old/libfaac/channels.c 2001-09-04 20:39:35.000000000 +0200
++++ faac-1.28.new/libfaac/channels.c 2012-08-06 21:15:34.000000000 +0200
+@@ -28,83 +28,112 @@
+ #include "coder.h"
+ #include "util.h"
+
+-/* If LFE present */
+-/* Num channels # of SCE's # of CPE's #of LFE's */
+-/* ============ ========== ========== ========= */
+-/* 1 1 0 0 */
+-/* 2 0 1 0 */
+-/* 3 1 1 0 */
+-/* 4 1 1 1 */
+-/* 5 1 2 0 */
+-/* For more than 5 channels, use the following elements: */
+-/* 2*N 1 2*(N-1) 1 */
+-/* 2*N+1 1 2*N 0 */
+-/* */
+-/* Else: */
+-/* */
+-/* Num channels # of SCE's # of CPE's #of LFE's */
+-/* ============ ========== ========== ========= */
+-/* 1 1 0 0 */
+-/* 2 0 1 0 */
+-/* 3 1 1 0 */
+-/* 4 2 1 0 */
+-/* 5 1 2 0 */
+-/* For more than 5 channels, use the following elements: */
+-/* 2*N 2 2*(N-1) 0 */
+-/* 2*N+1 1 2*N 0 */
+-
+-void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe)
+-{
+- int sceTag = 0;
+- int lfeTag = 0;
+- int cpeTag = 0;
+- int numChannelsLeft = numChannels;
++static void addSCE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag);
++static void addCPE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag);
++static void addLFE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag);
+
+
+- /* First element is sce, except for 2 channel case */
+- if (numChannelsLeft != 2) {
+- channelInfo[numChannels-numChannelsLeft].present = 1;
+- channelInfo[numChannels-numChannelsLeft].tag = sceTag++;
+- channelInfo[numChannels-numChannelsLeft].cpe = 0;
+- channelInfo[numChannels-numChannelsLeft].lfe = 0;
++void GetChannelInfo(ChannelInfo *channelInfo, int numFrontChannels, int numSideChannels, int numBackChannels, int numLFEChannels)
++{
++ int i;
++ int sceTag = 0;
++ int cpeTag = 0;
++ int lfeTag = 0;
++ int numChannels = (numFrontChannels +
++ numSideChannels +
++ numBackChannels +
++ numLFEChannels);
++ int numChannelsLeft = numChannels;
++
++ /* Front channels */
++ i = numFrontChannels;
++ if (i % 2) {
++ // Front Center
++ addSCE(channelInfo, numChannels, numChannelsLeft, sceTag);
+ numChannelsLeft--;
++ sceTag++;
++ i--;
++ }
++ while (i) {
++ // Front Left/Right, Front Left/Right of Center, ???
++ addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag);
++ numChannelsLeft -= 2;
++ cpeTag++;
++ i -= 2;
+ }
+
+- /* Next elements are cpe's */
+- while (numChannelsLeft > 1) {
+- /* Left channel info */
+- channelInfo[numChannels-numChannelsLeft].present = 1;
+- channelInfo[numChannels-numChannelsLeft].tag = cpeTag++;
+- channelInfo[numChannels-numChannelsLeft].cpe = 1;
+- channelInfo[numChannels-numChannelsLeft].common_window = 0;
+- channelInfo[numChannels-numChannelsLeft].ch_is_left = 1;
+- channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft+1;
+- channelInfo[numChannels-numChannelsLeft].lfe = 0;
++ /* Side channels */
++ i = numSideChannels;
++ while (i > 1) {
++ // Surround Left/Right (if rear surrounds present), ???
++ addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag);
++ numChannelsLeft -= 2;
++ cpeTag++;
++ i -= 2;
++ }
++ if (i) {
++ // ???
++ addSCE(channelInfo, numChannels, numChannelsLeft, sceTag);
+ numChannelsLeft--;
++ sceTag++;
++ i--;
++ }
+
+- /* Right channel info */
+- channelInfo[numChannels-numChannelsLeft].present = 1;
+- channelInfo[numChannels-numChannelsLeft].cpe = 1;
+- channelInfo[numChannels-numChannelsLeft].common_window = 0;
+- channelInfo[numChannels-numChannelsLeft].ch_is_left = 0;
+- channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft-1;
+- channelInfo[numChannels-numChannelsLeft].lfe = 0;
++ /* Back channels */
++ i = numBackChannels;
++ while (i > 1) {
++ // Surround Left/Right (if rear surrounds absent), Rear Surround Left/Right, ???
++ addCPE(channelInfo, numChannels, numChannelsLeft, cpeTag);
++ numChannelsLeft -= 2;
++ cpeTag++;
++ i -= 2;
++ }
++ if (i) {
++ // Surround Center
++ addSCE(channelInfo, numChannels, numChannelsLeft, sceTag);
+ numChannelsLeft--;
++ sceTag++;
++ i--;
+ }
+
+- /* Is there another channel left ? */
+- if (numChannelsLeft) {
+- if (useLfe) {
+- channelInfo[numChannels-numChannelsLeft].present = 1;
+- channelInfo[numChannels-numChannelsLeft].tag = lfeTag++;
+- channelInfo[numChannels-numChannelsLeft].cpe = 0;
+- channelInfo[numChannels-numChannelsLeft].lfe = 1;
+- } else {
+- channelInfo[numChannels-numChannelsLeft].present = 1;
+- channelInfo[numChannels-numChannelsLeft].tag = sceTag++;
+- channelInfo[numChannels-numChannelsLeft].cpe = 0;
+- channelInfo[numChannels-numChannelsLeft].lfe = 0;
+- }
++ /* LFE channel */
++ i = numLFEChannels;
++ while (i) {
++ addLFE(channelInfo, numChannels, numChannelsLeft, lfeTag);
+ numChannelsLeft--;
++ lfeTag++;
++ i--;
+ }
+ }
++
++static void addSCE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) {
++ channelInfo[numChannels-numChannelsLeft].present = 1;
++ channelInfo[numChannels-numChannelsLeft].cpe = 0;
++ channelInfo[numChannels-numChannelsLeft].lfe = 0;
++ channelInfo[numChannels-numChannelsLeft].tag = tag;
++}
++
++static void addCPE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) {
++ /* Left channel info */
++ channelInfo[numChannels-numChannelsLeft].present = 1;
++ channelInfo[numChannels-numChannelsLeft].cpe = 1;
++ channelInfo[numChannels-numChannelsLeft].lfe = 0;
++ channelInfo[numChannels-numChannelsLeft].tag = tag;
++ channelInfo[numChannels-numChannelsLeft].ch_is_left = 1;
++ channelInfo[numChannels-numChannelsLeft].common_window = 0;
++ channelInfo[numChannels-numChannelsLeft].paired_ch = numChannels-numChannelsLeft+1;
++ /* Right channel info */
++ channelInfo[numChannels-numChannelsLeft+1].present = 1;
++ channelInfo[numChannels-numChannelsLeft+1].cpe = 1;
++ channelInfo[numChannels-numChannelsLeft+1].lfe = 0;
++ channelInfo[numChannels-numChannelsLeft+1].ch_is_left = 0;
++ channelInfo[numChannels-numChannelsLeft+1].common_window = 0;
++ channelInfo[numChannels-numChannelsLeft+1].paired_ch = numChannels-numChannelsLeft;
++}
++
++static void addLFE(ChannelInfo *channelInfo, int numChannels, int numChannelsLeft, int tag) {
++ channelInfo[numChannels-numChannelsLeft].present = 1;
++ channelInfo[numChannels-numChannelsLeft].cpe = 0;
++ channelInfo[numChannels-numChannelsLeft].lfe = 1;
++ channelInfo[numChannels-numChannelsLeft].tag = tag;
++}
+diff -Naur faac-1.28.old/libfaac/channels.h faac-1.28.new/libfaac/channels.h
+--- faac-1.28.old/libfaac/channels.h 2003-06-26 21:19:41.000000000 +0200
++++ faac-1.28.new/libfaac/channels.h 2012-08-06 21:15:34.000000000 +0200
+@@ -45,7 +45,7 @@
+ MSInfo msInfo;
+ } ChannelInfo;
+
+-void GetChannelInfo(ChannelInfo *channelInfo, int numChannels, int useLfe);
++void GetChannelInfo(ChannelInfo *channelInfo, int numFrontChannels, int numSideChannels, int numBackChannels, int numLFEChannels);
+
+ #ifdef __cplusplus
+ }
+diff -Naur faac-1.28.old/libfaac/frame.c faac-1.28.new/libfaac/frame.c
+--- faac-1.28.old/libfaac/frame.c 2004-11-17 15:26:06.000000000 +0100
++++ faac-1.28.new/libfaac/frame.c 2012-08-06 21:15:34.000000000 +0200
+@@ -99,21 +99,47 @@
+ return -2; /* not supported */
+ }
+
+- *pSizeOfDecoderSpecificInfo = 2;
+- *ppBuffer = malloc(2);
++ if (hEncoder->config.channelConfiguration > 7) {
++ fprintf(stderr, "faacEncGetDecoderSpecificInfo: "
++ "invalid channel configuration %u\n",
++ hEncoder->config.channelConfiguration);
++ return -2;
++ } else if (hEncoder->config.channelConfiguration) {
++ // 16 bits
++ *pSizeOfDecoderSpecificInfo = 2;
++ } else {
++ // 16 bits + size of the program_config_element()
++ *pSizeOfDecoderSpecificInfo = 2 + (WritePCE(hEncoder, NULL, 0, 0, 0) / 8);
++ }
+
+- if(*ppBuffer != NULL){
++ *ppBuffer = malloc(*pSizeOfDecoderSpecificInfo);
+
++ if (*ppBuffer != NULL) {
+ memset(*ppBuffer,0,*pSizeOfDecoderSpecificInfo);
+ pBitStream = OpenBitStream(*pSizeOfDecoderSpecificInfo, *ppBuffer);
+ PutBit(pBitStream, hEncoder->config.aacObjectType, 5);
+ PutBit(pBitStream, hEncoder->sampleRateIdx, 4);
+- PutBit(pBitStream, hEncoder->numChannels, 4);
++ PutBit(pBitStream, hEncoder->config.channelConfiguration, 4);
++ PutBit(pBitStream, 0, 1); // frameLengthFlag
++ PutBit(pBitStream, 0, 1); // dependsOnCoreCoder
++ PutBit(pBitStream, 0, 1); // extensionFlag
++ if (!hEncoder->config.channelConfiguration) {
++ /* a program_config_element() must be written */
++ if (WritePCE(hEncoder, pBitStream, 0, 0, 1) <= 0) {
++ fprintf(stderr,
++ "faacEncGetDecoderSpecificInfo: WritePCE() failed!\n");
++ *pSizeOfDecoderSpecificInfo = 0;
++ CloseBitStream(pBitStream);
++ free(*ppBuffer);
++ *ppBuffer = NULL;
++ return -3;
++ }
++ }
+ CloseBitStream(pBitStream);
+-
+ return 0;
+ } else {
+- return -3;
++ *pSizeOfDecoderSpecificInfo = 0;
++ return -4;
+ }
+ }
+
+@@ -131,7 +157,6 @@
+ int i;
+
+ hEncoder->config.allowMidside = config->allowMidside;
+- hEncoder->config.useLfe = config->useLfe;
+ hEncoder->config.useTns = config->useTns;
+ hEncoder->config.aacObjectType = config->aacObjectType;
+ hEncoder->config.mpegVersion = config->mpegVersion;
+@@ -139,6 +164,77 @@
+ hEncoder->config.inputFormat = config->inputFormat;
+ hEncoder->config.shortctl = config->shortctl;
+
++ if (!config->channelConfiguration) {
++ if (hEncoder->numChannels != (config->numFrontChannels +
++ config->numSideChannels +
++ config->numBackChannels +
++ config->numLFEChannels)) {
++ fprintf(stderr, "faacEncSetConfiguration: "
++ "numChannels doesn't match the custom channel configuration\n");
++ return 0;
++ }
++ hEncoder->config.numFrontChannels = config->numFrontChannels;
++ hEncoder->config.numSideChannels = config->numSideChannels;
++ hEncoder->config.numBackChannels = config->numBackChannels;
++ hEncoder->config.numLFEChannels = config->numLFEChannels;
++ } else if (config->channelConfiguration > 7) {
++ fprintf(stderr, "faacEncSetConfiguration: "
++ "invalid channel configuration %u\n",
++ config->channelConfiguration);
++ return 0;
++ } else {
++ if ((config->channelConfiguration == 7 && hEncoder->numChannels != 8) ||
++ (config->channelConfiguration != 7 && hEncoder->numChannels != config->channelConfiguration)) {
++ fprintf(stderr, "faacEncSetConfiguration: "
++ "numChannels doesn't match the channel configuration\n");
++ return 0;
++ }
++ switch (config->channelConfiguration) {
++ case 7:
++ hEncoder->config.numFrontChannels = 5;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 1;
++ break;
++ case 6:
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 1;
++ break;
++ case 5:
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 4:
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 1;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 3:
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 2:
++ hEncoder->config.numFrontChannels = 2;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 1:
++ hEncoder->config.numFrontChannels = 1;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ }
++ }
++
+ assert((hEncoder->config.outputFormat == 0) || (hEncoder->config.outputFormat == 1));
+
+ switch( hEncoder->config.inputFormat )
+@@ -306,6 +402,12 @@
+ *maxOutputBytes += 1; /* for CRC */
+ #endif
+
++ if (!numChannels || numChannels > 64) {
++ fprintf(stderr, "faacEncOpen: invalid number of channels %u\n",
++ numChannels);
++ return NULL;
++ }
++
+ hEncoder = (faacEncStruct*)AllocMemory(sizeof(faacEncStruct));
+ SetMemory(hEncoder, 0, sizeof(faacEncStruct));
+
+@@ -324,7 +426,6 @@
+ hEncoder->config.mpegVersion = MPEG4;
+ hEncoder->config.aacObjectType = LTP;
+ hEncoder->config.allowMidside = 1;
+- hEncoder->config.useLfe = 1;
+ hEncoder->config.useTns = 0;
+ hEncoder->config.bitRate = 0; /* default bitrate / channel */
+ hEncoder->config.bandWidth = bwfac * hEncoder->sampleRate;
+@@ -340,6 +441,91 @@
+ /* default channel map is straight-through */
+ for( channel = 0; channel < 64; channel++ )
+ hEncoder->config.channel_map[channel] = channel;
++
++ /* Define a sensible default channel configuration */
++ if (numChannels <= 6 || numChannels == 8) {
++ switch (numChannels) {
++ case 8:
++ hEncoder->config.channelConfiguration = 7;
++ hEncoder->config.numFrontChannels = 5;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 1;
++ break;
++ case 6:
++ hEncoder->config.channelConfiguration = 6;
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 1;
++ break;
++ case 5:
++ hEncoder->config.channelConfiguration = 5;
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 2;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 4:
++ hEncoder->config.channelConfiguration = 4;
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 1;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 3:
++ hEncoder->config.channelConfiguration = 3;
++ hEncoder->config.numFrontChannels = 3;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 2:
++ hEncoder->config.channelConfiguration = 2;
++ hEncoder->config.numFrontChannels = 2;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ case 1:
++ hEncoder->config.channelConfiguration = 1;
++ hEncoder->config.numFrontChannels = 1;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ break;
++ }
++ } else {
++ hEncoder->config.channelConfiguration = 0;
++ hEncoder->config.numFrontChannels = 0;
++ hEncoder->config.numSideChannels = 0;
++ hEncoder->config.numBackChannels = 0;
++ hEncoder->config.numLFEChannels = 0;
++ for (channel = numChannels; channel > 0; channel--) {
++ // 7 channels: 7.0 (C L R Ls Rs Rls Rrs)
++ // 9 channels: 9.0 (Lc Rc L R Ls Rs Rls Rrs Cs)
++ // 10 channels: 10.0 (C Lc Rc L R Ls Rs Rls Rrs Cs)
++ // for more than 10 channels, use faacEncSetConfiguration()
++ if (hEncoder->config.numFrontChannels < 3) {
++ // C, L, R
++ hEncoder->config.numFrontChannels++;
++ } else if (hEncoder->config.numBackChannels < 2) {
++ // Ls or Rls, Rs or Rrs
++ hEncoder->config.numBackChannels++;
++ } else if (hEncoder->config.numSideChannels < 2) {
++ // Ls, Rs
++ hEncoder->config.numSideChannels++;
++ } else if (hEncoder->config.numBackChannels < 3) {
++ // Cs
++ hEncoder->config.numBackChannels++;
++ } else if (hEncoder->config.numFrontChannels < 5) {
++ // Lc, Rc
++ hEncoder->config.numFrontChannels++;
++ } else {
++ break;
++ }
++ }
++ }
+
+ /*
+ by default we have to be compatible with all previous software
+@@ -459,14 +645,13 @@
+ double fix;
+ #endif
+
+- /* local copy's of parameters */
++ /* local copies of parameters */
+ ChannelInfo *channelInfo = hEncoder->channelInfo;
+ CoderInfo *coderInfo = hEncoder->coderInfo;
+ unsigned int numChannels = hEncoder->numChannels;
+ unsigned int sampleRate = hEncoder->sampleRate;
+ unsigned int aacObjectType = hEncoder->config.aacObjectType;
+ unsigned int mpegVersion = hEncoder->config.mpegVersion;
+- unsigned int useLfe = hEncoder->config.useLfe;
+ unsigned int useTns = hEncoder->config.useTns;
+ unsigned int allowMidside = hEncoder->config.allowMidside;
+ unsigned int bandWidth = hEncoder->config.bandWidth;
+@@ -484,7 +669,11 @@
+ return 0;
+
+ /* Determine the channel configuration */
+- GetChannelInfo(channelInfo, numChannels, useLfe);
++ GetChannelInfo(channelInfo,
++ hEncoder->config.numFrontChannels,
++ hEncoder->config.numSideChannels,
++ hEncoder->config.numBackChannels,
++ hEncoder->config.numLFEChannels);
+
+ /* Update current sample buffers */
+ for (channel = 0; channel < numChannels; channel++)
diff --git a/contrib/faac/P00-cygwin.patch b/contrib/faac/P00-cygwin.patch
index a5da42d87..bef152139 100644
--- a/contrib/faac/P00-cygwin.patch
+++ b/contrib/faac/P00-cygwin.patch
@@ -1,6 +1,6 @@
-diff -Naur faac-1.28.orig/include/faac.h faac-1.28/include/faac.h
---- faac-1.28.orig/include/faac.h 2009-01-25 13:50:32.000000000 -0500
-+++ faac-1.28/include/faac.h 2009-03-20 03:31:46.000000000 -0400
+diff -Naur faac-1.28.old/include/faac.h faac-1.28.new/include/faac.h
+--- faac-1.28.old/include/faac.h 2009-01-25 13:50:32.000000000 -0500
++++ faac-1.28.new/include/faac.h 2009-03-20 03:31:46.000000000 -0400
@@ -50,7 +50,7 @@
typedef void *faacEncHandle;