• 5
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

I wish to use MediaRecorder.AudioEncoder.HE_AAC whenever possible.

However, the following code fails to generate valid audio file in some devices, unless I use MediaRecorder.AudioEncoder.AAC.

private void startMediaRecorder() {
    mediaRecorder = new MediaRecorder();
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mediaRecorder.setAudioChannels(1);
    mediaRecorder.setAudioSamplingRate(8000);
    mediaRecorder.setAudioEncodingBitRate(32000);
    /*
    mediaRecorder.setAudioChannels(1);
    mediaRecorder.setAudioSamplingRate(44100);
    mediaRecorder.setAudioEncodingBitRate(96000);
     */
    mediaRecorder.setMaxDuration(RECORDING_MEDIA_RECORDER_MAX_DURATION);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
    } else {
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    }
    mediaRecorder.setOutputFile(getMicFilepath());

    mediaRecorder.setOnInfoListener((mediaRecorder, what, i1) -> {
        if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
            dismiss();
        }
    });

    try {
        mediaRecorder.prepare();
    } catch (IOException e) {
        Log.e(TAG, "", e);
    }

    mediaRecorder.start();
}

For device which doesn't support HE_AAC, No crash and no exception thrown. But, you can see the following error log

E/MediaProfiles: The given audio encoder 4 is not found


I try MediaCodecList.getCodecInfoAt, to see it can give me some useful information, on whether MediaRecorder.AudioEncoder.HE_AAC is supported on selected device.

    int numCodecs = 0;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        numCodecs = MediaCodecList.getCodecCount();

        for (int i = 0; i < numCodecs; i++) {
            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

            if (!codecInfo.isEncoder()) {
                continue;
            }

            for (String s : codecInfo.getSupportedTypes())
                android.util.Log.i("CHEOK", "getSupportedTypes = " + s);
            android.util.Log.i("CHEOK", "name = " + codecInfo.getName());
        }
    }

Output for device which doesn't support HE_AAC

getSupportedTypes = audio/mp4a-latm
name = OMX.google.aac.encoder
getSupportedTypes = audio/3gpp
name = OMX.google.amrnb.encoder
getSupportedTypes = audio/amr-wb
name = OMX.google.amrwb.encoder
getSupportedTypes = audio/flac
name = OMX.google.flac.encoder
getSupportedTypes = video/3gpp
name = OMX.google.h263.encoder
getSupportedTypes = video/avc
name = OMX.google.h264.encoder
getSupportedTypes = video/mp4v-es
name = OMX.google.mpeg4.encoder
getSupportedTypes = video/x-vnd.on2.vp8
name = OMX.google.vp8.encoder

Output for device which supports HE_AAC

getSupportedTypes = audio/mp4a-latm
name = OMX.google.aac.encoder
getSupportedTypes = audio/3gpp
name = OMX.google.amrnb.encoder
getSupportedTypes = audio/amr-wb
name = OMX.google.amrwb.encoder
getSupportedTypes = audio/flac
name = OMX.google.flac.encoder
getSupportedTypes = video/avc
name = OMX.qcom.video.encoder.avc
getSupportedTypes = video/avc
name = OMX.google.h264.encoder
getSupportedTypes = video/3gpp
name = OMX.qcom.video.encoder.h263
getSupportedTypes = video/3gpp
name = OMX.google.h263.encoder
getSupportedTypes = video/hevc
name = OMX.qcom.video.encoder.hevc
getSupportedTypes = video/mp4v-es
name = OMX.qcom.video.encoder.mpeg4
getSupportedTypes = video/mp4v-es
name = OMX.google.mpeg4.encoder
getSupportedTypes = video/x-vnd.on2.vp8
name = OMX.qcom.video.encoder.vp8
getSupportedTypes = video/x-vnd.on2.vp8
name = OMX.google.vp8.encoder
getSupportedTypes = video/x-vnd.on2.vp9
name = OMX.google.vp9.encoder

Based on the above output, I can hardly correlate information returned by MediaCodecList.getCodecInfoAt, with whether MediaRecorder.AudioEncoder.HE_AAC is supported.

Any suggestion on what is a reliable way to do so?


Updated solution

This is the solution, with assumption HE_AAC can be detected using profile MediaCodecInfo.CodecProfileLevel.AACObjectHE and MediaCodecInfo.CodecProfileLevel.AACObjectHE_PS

Do I miss out other profiles?

private static final String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";

private boolean isHeAacEncoderSupported() {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
        int numCodecs = MediaCodecList.getCodecCount();

        for (int i = 0; i < numCodecs; i++) {
            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

            if (!codecInfo.isEncoder()) {
                continue;
            }

            for (String supportedType : codecInfo.getSupportedTypes()) {
                if (supportedType.equalsIgnoreCase(MIMETYPE_AUDIO_AAC)) {
                    MediaCodecInfo.CodecCapabilities cap = codecInfo.getCapabilitiesForType(MIMETYPE_AUDIO_AAC);
                    MediaCodecInfo.CodecProfileLevel[] profileLevels = cap.profileLevels;
                    for (MediaCodecInfo.CodecProfileLevel profileLevel : profileLevels) {
                        int profile = profileLevel.profile;
                        if (profile == MediaCodecInfo.CodecProfileLevel.AACObjectHE || profile == MediaCodecInfo.CodecProfileLevel.AACObjectHE_PS) {
                            return true;
                        }
                    }
                }
            }
        }
    }

    return false;
}

All AAC codecs share the same MIME type, but you should be able to distinguish them by profile level and compare with MediaCodecInfo.CodecProfileLevel.

  • 1
Reply Report
      • 1
    • Thanks. Will give it a try. Currently, to first determine whether a codec is from aac family, we are using codecinfo name, to compare with "OMX.google.aac.encoder". But, is that realiable enough? What if, aac codec is provided by another vendor?