Search code examples
androidhttp-live-streamingaacmpeg2-ts

Android PCM -> AAC = M4A vs. MPEG2-TS


How can I package raw AAC-data into a MPEG2-TS stream?

I'm continuous recoding (microphone) & compressing PCM-audio inside Android to AAC:

    encoder = MediaCodec.createEncoderByType("audio/mp4a-latm");
    MediaFormat format = new MediaFormat();
    format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
    format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
    format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
    format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);
    format.setInteger(MediaFormat.KEY_AAC_PROFILE,
            MediaCodecInfo.CodecProfileLevel.AACObjectLC);
    encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);

As this produces a raw, headless AAC, I'm also adding the required MPEG-headers for each frame:

    private void addADTStoPacket(byte[] packet, int packetLen) {
    int profile = 2; // M4A LC
                        // 39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
    int freqIdx = 4; // 44.1KHz
    int chanCfg = 2; // CPE

    // fill in ADTS data
    packet[0] = (byte) 0xFF;
    packet[1] = (byte) 0xF9;
    packet[2] = (byte) (((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
    packet[3] = (byte) (((chanCfg & 3) << 6) + (packetLen >> 11));
    packet[4] = (byte) ((packetLen & 0x7FF) >> 3);
    packet[5] = (byte) (((packetLen & 7) << 5) + 0x1F);
    // packet[6] = (byte) 0xFC;
    packet[6] = (byte) 0x00;// number of frames = 1;
}

This is working fine and I can play the created AAC-files eg. with VLC or the Google Music Player.

Now my question:

I would like to send the encoded data as a HTTP LIVE STREAM (HLS) to some renderers like I'm already doing it with WAV and MP3-streams.

But if I'm sending it to an Android-app, the stream does not start to play, until I interrupt the recording and therefor flushing/finishing the stream. No problems with MP3, here the playback is starting after seconds.

Regarding the "Supported Media Types"-page of Android, HLS is only supported on

HTTP/HTTPS live streaming draft protocol: MPEG-2 TS media files only

Who can tell me, how to package the raw AAC-stream into an MPEG-2 TS-stream rather than into a MPEG4-stream like now?

I'm new at this area, please excuse mistakes.


Solution

  • You sort of answer your own question. You need to set the ADTS version to MPEG2 instead of MPEG4. packet[1] = (byte) 0xF1;

    Also packet[6] = (byte) 0xFC; is correct unless you know the buffer fullness value.

    see more here: http://wiki.multimedia.cx/index.php?title=ADTS