1

I am trying to decode AAC encoded files in my application and to initialise the MediaFormatobject used to initialise my MediaCodec object, This is the code for setting up the variables for the MediaFormat object

MediaExtractor mediaExtractor = new MediaExtractor();
        try {
            mediaExtractor.setDataSource(audioFilePath);
        } catch (IOException e) {
            return false;
        }
        Log.d(TAG, "Number of tracks in the file are:" + mediaExtractor.getTrackCount());

        MediaFormat mediaFormat = mediaExtractor.getTrackFormat(0);

        Log.d(TAG, "mediaFormat:" + mediaFormat.toString());

        mSampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
        Log.d(TAG, "mSampleRate: " + mSampleRate);


        mChannels = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);

        Log.d(TAG, "mChannels number of channels: " + mChannels);

        // Reading the duration from the file and converting from micro seconds to milliseconds.
        mDuration = (int) (mediaFormat.getLong(MediaFormat.KEY_DURATION) / 1000);

        Log.d(TAG, "duration: " + mDuration);

        // Getting the csd-0 info from the file ..
        mCSDBuffer = mediaFormat.getByteBuffer("csd-0");

The problem I am facing is that the statement mCSDBuffer = mediaFormat.getByteBuffer("csd-0") fetches me null for the same file on some devices. The application is in production and I see this error on armabi-v7a/armabiprocessors devices with android API level of 17, 18 and 19 and most of these errors are on Samsung devices. Any direction on this?

Swapnil
  • 1,870
  • 2
  • 23
  • 48

1 Answers1

2

If the csd-0 buffer is null, then I would expect it still to decode correctly when passed into MediaCodec. Does it, if you just choose not to set the csd-0 data as input to MediaCodec, if it is null? In general, you should be able to decode the MediaExtractor output if you just pipe it straight to MediaCodec.

The actual format of the data output from MediaExtractor is not very strictly specified though, so in practice it is known that some manufacturers (mainly Samsung) change this in a way that only their own decoder handles. See e.g. https://code.google.com/p/android/issues/detail?id=74356 for another case of the same.

Ideally, the Android CTS tests would be made stricter to make sure that MediaExtractor behaves consistently, allowing its use in a more generic context, or use another decoder than MediaCodec. (E.g. with the current Samsung issues, you can't use MediaExtractor on one device, send the extracted data over a network to another device and decode it there.)

mstorsjo
  • 12,983
  • 2
  • 39
  • 62
  • I also have a custom function with the help of which I generate the "csd-0" buffer as mentioned in http://stackoverflow.com/a/32154154/2606411. Can I use this to manually set the info? – Swapnil Dec 08 '16 at 10:37
  • You might be able to use that. But if you do, you should probably also strip ADTS headers from the actual audio packets. IMO, if MediaExtractor chooses to return data in ADTS format (i.e. no `csd-0` and ADTS headers in the packets), then MediaCodec should be able to handle it, so I don't think you should need to do any editing at all. – mstorsjo Dec 08 '16 at 11:06
  • We have ourselves encoded the files that we use and we have set ADTS headers to all of them, so I guess it makes sense to set that header manually. – Swapnil Dec 14 '16 at 07:31
  • But even normally (when MediaExtractor returned the csd-0 info), we are reading the ADTS header by ourselves and getting all the info from that. Is there a way, we can avoid that with `MediaCodec` api? – Swapnil Dec 14 '16 at 07:33
  • So you're manually reading the ADTS headers in order to have samplerate and channel numbers to give to MediaCodec to initialize the decoder? Wouldn't MediaExtractor give you these values in the MediaFormat that it returns? – mstorsjo Dec 14 '16 at 07:43
  • So, for each packet, we have an ADTS header (that we wrote to each packet while encoding it). While decoding the file, we do the same. We first red the bytes equal to the header size and get the information about the number of bytes that follow that have been encoded and then read those number of bytes and decode them. For setting the samplerate and channels we are using the `MediaExtractor` object and that is where we are unable to get the csd-0 buffer in some Samsung devices. So the solution for this is to get this from the header of the first packet. Hope this works for all devices ! – Swapnil Dec 14 '16 at 08:49