Problem setting channels in AAC config packet

I’m using Xuggler to encode AAC audio and send the packets to a Publisher. The encode process seems to work fine, but it seems that I’m having a problem getting the channels property of the AACFrame to set properly

My code is as follows:

AACFrame frame = new AACFrame();

int sampleRate = 44100;

int channels = 2;

frame.setSampleRate(44100);

frame.setChannels(2);

frame.setRateIndex(AACUtils.sampleRateToIndex(sampleRate));

frame.setChannelIndex(AACUtils.channelCountToIndex(sampleRate));

frame.setProfileObjectType(1);

byte[] codecConfig = new byte[2];

AACUtils.encodeAACCodecConfig(frame, codecConfig, 0);

byte[] finalConfig = new byte[codecConfig.length+2];

byte header = (byte)0xaf;

finalConfig[0] = (byte)0xaf;

finalConfig[1] = (byte)0;

System.arraycopy(codecConfig, 0, finalConfig, 2, codecConfig.length);

I’ve tried sending this packet to the publisher once before starting audio packets, and also once before each audio packet. The results are the same…

When I read the stream in on another wowza server, it looks like the config packet is reporting 0 channels:

[mp4a.40.1]: AAC Audio info: {AACFrame: size: 0, rate: 44100, channels: 0, samples: 1024, errorBitsAbsent: true, profileObjectType: “Main”}

The sample rate, samples per packet, and profileObjectType are coming across as expected, but channels always reads 0. I can play the stream on VLC and on Android over RTSP, but VLC reports an error on the channels value, and the stream cannot be played by iOS or Flash.

I’ve also tried with the LC profile… same results.

ideas?

I don’t quite understand. For AAC you need to send a 2-byte codec config packet (with a 2-byte header) before you send your first audio packet. What does this packet look like? Also, the AAC packets should be sent without the ADTS (I think that is the correct acronym) header. Are you doing this. The ADTS header is 7 bytes long and the first 12 bits are 0xfff.

Charlie

That does not sound quite right. I am out of town. Will need to look at it more closely when I get back. If you can post of send us more of the code then I can take a look at it.

Charlie

Cool, glad to hear yoi have this sorted out.

Charlie

For the codec config packet, I’m taking the byte array from the above code (finalConfig) and providing that as the byte[] argument in a call to publisher.addAudioData . The decimal representations of the bytes in the config packet are:

0: -81

1: 0

2: 10

3: 0

For the AAC packets, I’m building up a byte array as follows:

ba[0] = 1;

ba[1] = 0xaf;

and then adding the AAC encoded samples from Xuggler to the array (the length of the byte array varies, but there are always 1024 samples). That byte array is then used as the byte[] argument passed to publisher.addAudioData()

Playback is fine on RTSP clients… it just seems that the missing value for the number of channels in the config seems to be breaking RTMP and Cupertino.

Fixed. Instead of using AACFrame to build up the config byte array, I gleaned some code from red5. http://red5.googlecode.com/svn-history/r3728/java/server/trunk/src/org/red5/server/stream/codec/AACAudio.java

The difference is that the config packet generated is as follows:

0: -81

1: 0

2: 18

3: 16

That said, holy cow… the output quality of FAAC (what Xuggler uses for aac encoding) is horrible at anything under 256kbps. Maybe I’ll revise my AAC encoding workflow to use Wowza’s transcoder to go from mp3 to aac once I have a sandybridge server set up. With that, which AAC encoder is the transcoder using?