LoginSignup
0
2

More than 5 years have passed since last update.

Live AAC audio streaming with ffmpeg.exe and live docode with MediaCodec class of Android (Xamarin)

Last updated at Posted at 2019-02-02

ffmpeg.exe (encode PCM to AAC-LC and pack the data to adts format)

  • exec ffmpeg.exe from my program
  • ffmpeg.exe -f f32le -ar 48000 -ac 2 -i - -f u16le -ar 24000 -ac 1 -map 0 -codec:a aac -profile aac_low -ab 8k -f adts -
  • my program passes captured PC internal sound data through stdin of ffmpeg.exe process
  • IMPORTANT: passing samples is needed 1024 samples at the same time (= pass 1024 samples with one write call and then call flush)
  • stdout of ffmpeg.exe is read by my program and send it to Android app.
    • IMPORTANT: you should read ffmpeg write data with one read call (it should be a adts frame)

Decoder with MediaCodec class

decode.cs
            HandlerThread callbackThread = new HandlerThread("AACDecodingHandler");
            callbackThread.Start();
            Handler handler = new Handler(callbackThread.Looper);

            decoder = MediaCodec.CreateDecoderByType("audio/mp4a-latm");
            // samplingRate and ch is your required value
            var format = MediaFormat.CreateAudioFormat("audio/mp4a-latm", samplingRate, ch);

            // IMPORTANT: csd_data is byte array (7 elements). this data is exist head of stream (= stdout of ffmpeg.exe)
            //            this 7 bytes is adts fixed header of first frame but you should not removed it from frame.
            //            you should pass first adts frame to InputBuffer with header (first 7 bytes).
            int profile = (csd_data[2] & 0xC0) >> 6;
            int srate = (csd_data[2] & 0x3C) >> 2;
            int channel = ((csd_data[2] & 0x01) << 2) | ((csd_data[3] & 0xC0) >> 6);
            byte csd0_0 = (byte)(((profile + 1) << 3) | srate >> 1);
            byte csd0_1 = (byte)(((srate << 7) & 0x80) | channel << 3 );
            byte[] bytes = new byte[] { csd0_0, csd0_1 };
            ByteBuffer csd = ByteBuffer.Wrap(bytes);
            format.SetInteger(MediaFormat.KeyIsAdts, 1);

            format.SetByteBuffer("csd-0", csd);

            // cbk is your callback class
            decoder.SetCallback(cbk, handler);
            decoder.Configure(format, null, null, 0);

            decoder.Start();

Useful tool for validating your AAC adts data

Whole code

Enjoy!

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2