Java Code Examples for android.media.MediaCodecInfo#isEncoder()

The following examples show how to use android.media.MediaCodecInfo#isEncoder() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: MediaController.java    From SiliCompressor with Apache License 2.0 6 votes vote down vote up
public static MediaCodecInfo selectCodec(String mimeType) {
    int numCodecs = MediaCodecList.getCodecCount();
    MediaCodecInfo lastCodecInfo = null;
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        if (!codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (String type : types) {
            if (type.equalsIgnoreCase(mimeType)) {
                lastCodecInfo = codecInfo;
                if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
                    return lastCodecInfo;
                } else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
                    return lastCodecInfo;
                }
            }
        }
    }
    return lastCodecInfo;
}
 
Example 2
Source File: Api16Builder.java    From jellyfin-androidtv with GNU General Public License v2.0 6 votes vote down vote up
public void buildProfiles(DeviceProfile profile){
    ArrayList<DirectPlayProfile> directPlayProfiles = new ArrayList<>();
    ArrayList<CodecProfile> codecProfiles = new ArrayList<>();

    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        if (codecInfo.isEncoder()) {
            continue;
        }

        ProcessMediaCodecInfo(codecInfo, directPlayProfiles, codecProfiles);
    }

    profile.setDirectPlayProfiles(directPlayProfiles.toArray(new DirectPlayProfile[directPlayProfiles.size()]));
    profile.setCodecProfiles(codecProfiles.toArray(new CodecProfile[codecProfiles.size()]));
}
 
Example 3
Source File: MediaVideoEncoder.java    From Tok-Android with GNU General Public License v3.0 6 votes vote down vote up
/**
 * select the first codec that match a specific MIME type
 *
 * @return null if no codec matched
 */
protected static final MediaCodecInfo selectVideoCodec(final String mimeType) {
    LogUtil.i(TAG, "selectVideoCodec:");

    // get the list of available codecs
    final int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);

        if (!codecInfo.isEncoder()) {    // skipp decoder
            continue;
        }
        // select first codec that match a specific MIME type and color format
        final String[] types = codecInfo.getSupportedTypes();
        for (int j = 0; j < types.length; j++) {
            if (types[j].equalsIgnoreCase(mimeType)) {
                LogUtil.i(TAG, "codec:" + codecInfo.getName() + ",MIME=" + types[j]);
                final int format = selectColorFormat(codecInfo, mimeType);
                if (format > 0) {
                    return codecInfo;
                }
            }
        }
    }
    return null;
}
 
Example 4
Source File: VideoController.java    From VideoCompressor with Apache License 2.0 6 votes vote down vote up
public static MediaCodecInfo selectCodec(String mimeType) {
    int numCodecs = MediaCodecList.getCodecCount();
    MediaCodecInfo lastCodecInfo = null;
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        if (!codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (String type : types) {
            if (type.equalsIgnoreCase(mimeType)) {
                lastCodecInfo = codecInfo;
                if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
                    return lastCodecInfo;
                } else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
                    return lastCodecInfo;
                }
            }
        }
    }
    return lastCodecInfo;
}
 
Example 5
Source File: VideoRecoder.java    From deltachat-android with GNU General Public License v3.0 6 votes vote down vote up
@SuppressLint("NewApi")
private static MediaCodecInfo selectCodec(String mimeType) {
  int numCodecs = MediaCodecList.getCodecCount();
  MediaCodecInfo lastCodecInfo = null;
  for (int i = 0; i < numCodecs; i++) {
    MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
    if (!codecInfo.isEncoder()) {
      continue;
    }
    String[] types = codecInfo.getSupportedTypes();
    for (String type : types) {
      if (type.equalsIgnoreCase(mimeType)) {
        lastCodecInfo = codecInfo;
        if (!lastCodecInfo.getName().equals("OMX.SEC.avc.enc")) {
          return lastCodecInfo;
        } else if (lastCodecInfo.getName().equals("OMX.SEC.AVC.Encoder")) {
          return lastCodecInfo;
        }
      }
    }
  }
  return lastCodecInfo;
}
 
Example 6
Source File: HardwareVideoEncoderFactory.java    From webrtc_android with MIT License 6 votes vote down vote up
private MediaCodecInfo findCodecForType(VideoCodecType type) {
    for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) {
        MediaCodecInfo info = null;
        try {
            info = MediaCodecList.getCodecInfoAt(i);
        } catch (IllegalArgumentException e) {
            Logging.e(TAG, "Cannot retrieve encoder codec info", e);
        }

        if (info == null || !info.isEncoder()) {
            continue;
        }

        if (isSupportedCodec(info, type)) {
            return info;
        }
    }
    return null; // No support for this type.
}
 
Example 7
Source File: AudioUtils.java    From AlexaAndroid with GNU General Public License v2.0 6 votes vote down vote up
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static List<String> getAvailableEncoders(int sampleRate) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        MediaFormat format = MediaFormatFactory.createMediaFormat(MediaFormatFactory.Type.FLAC, sampleRate);
        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        String encoderAsStr = mcl.findEncoderForFormat(format);
        List<String> encoders = new ArrayList<>();
        for (MediaCodecInfo info : mcl.getCodecInfos()) {
            if (info.isEncoder()) {
                if (info.getName().equals(encoderAsStr)) {
                    encoders.add("*** " + info.getName() + ": " + TextUtils.join(", ", info.getSupportedTypes()));
                } else {
                    encoders.add(info.getName() + ": " + TextUtils.join(", ", info.getSupportedTypes()));
                }
            }
        }
        return encoders;
    }
    return Collections.emptyList();
}
 
Example 8
Source File: EncodeDecode.java    From videocreator with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the first codec capable of encoding the specified MIME type, or
 * null if no match was found.
 */
private static MediaCodecInfo selectCodec(String mimeType) {
    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        if (!codecInfo.isEncoder()) {
            continue;
        }
        String[] types = codecInfo.getSupportedTypes();
        for (int j = 0; j < types.length; j++) {
            if (types[j].equalsIgnoreCase(mimeType)) {
                return codecInfo;
            }
        }
    }
    return null;
}
 
Example 9
Source File: StreamingAudioEncoder.java    From live-transcribe-speech-engine with Apache License 2.0 6 votes vote down vote up
/**
 * Searches for a codec that implements the requested format conversion. Android framework encoder
 * only.
 */
private static MediaCodecInfo searchAmongAndroidSupportedCodecs(String mimeType) {
  int numCodecs = MediaCodecList.getCodecCount();
  for (int i = 0; i < numCodecs; i++) {
    MediaCodecInfo codecAndBitrate = MediaCodecList.getCodecInfoAt(i);
    if (!codecAndBitrate.isEncoder()) {
      continue;
    }
    String[] codecTypes = codecAndBitrate.getSupportedTypes();
    for (int j = 0; j < codecTypes.length; j++) {
      if (codecTypes[j].equalsIgnoreCase(mimeType)) {
        return codecAndBitrate;
      }
    }
  }
  return null;
}
 
Example 10
Source File: AudioUtils.java    From AlexaAndroid with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Maps the given mime type to a list of names of suitable codecs.
 * Only OMX-codecs are considered.
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static List<String> getEncoderNamesForType(String mime) {
    LinkedList<String> names = new LinkedList<>();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        int n = MediaCodecList.getCodecCount();
        for (int i = 0; i < n; ++i) {
            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
            if (!info.isEncoder()) {
                continue;
            }
            if (!info.getName().startsWith("OMX.")) {
                // Unfortunately for legacy reasons, "AACEncoder", a
                // non OMX component had to be in this list for the video
                // editor code to work... but it cannot actually be instantiated
                // using MediaCodec.
                Log.i("skipping '" + info.getName() + "'.");
                continue;
            }
            String[] supportedTypes = info.getSupportedTypes();
            for (int j = 0; j < supportedTypes.length; ++j) {
                if (supportedTypes[j].equalsIgnoreCase(mime)) {
                    names.push(info.getName());
                    break;
                }
            }
        }
    }
    // Return an empty list if API is too old
    // TODO: maybe return null or throw exception
    return names;
}
 
Example 11
Source File: MediaCodecListCompat.java    From phoenix with Apache License 2.0 5 votes vote down vote up
private String findCoderForFormat(MediaFormat format, boolean findEncoder) {
    String mimeType = format.getString(MediaFormat.KEY_MIME);
    Iterator<MediaCodecInfo> iterator = new MediaCodecInfoIterator();
    while (iterator.hasNext()) {
        MediaCodecInfo codecInfo = iterator.next();
        if (codecInfo.isEncoder() != findEncoder) continue;
        if (Arrays.asList(codecInfo.getSupportedTypes()).contains(mimeType)) {
            return codecInfo.getName();
        }
    }
    return null;
}
 
Example 12
Source File: CodecWrapper.java    From letv with Apache License 2.0 5 votes vote down vote up
public static int getAVCLevel() {
    int maxAVCLevel = 0;
    if (VERSION.SDK_INT >= 16) {
        int mediaCodecListCount = MediaCodecList.getCodecCount();
        for (int i = 0; i < mediaCodecListCount; i++) {
            MediaCodecInfo mediaCodecInfo = MediaCodecList.getCodecInfoAt(i);
            if (!(mediaCodecInfo.isEncoder() || mediaCodecInfo.getName().startsWith("OMX.google") || mediaCodecInfo.getName().startsWith("OMX.TI."))) {
                Log.d(LOG_TAG, "getAVCLevel()->name:" + mediaCodecInfo.getName());
                for (String type : mediaCodecInfo.getSupportedTypes()) {
                    if (type.contains("avc")) {
                        Log.d(LOG_TAG, "getAVCLevel()->type:" + type);
                        try {
                            CodecCapabilities codecCapabilities = mediaCodecInfo.getCapabilitiesForType(type);
                            for (int colorFormat : codecCapabilities.colorFormats) {
                                Log.d(LOG_TAG, "getAVCLevel()->Color Format: " + colorFormat + " " + colorFormatToString(colorFormat));
                            }
                            for (CodecProfileLevel codecProfileLevel : codecCapabilities.profileLevels) {
                                String level = "unknown type";
                                String sprofile = "unknown type";
                                Log.d(LOG_TAG, "getAVCLevel()->Codec Profile Level:" + avcLevelToString(codecProfileLevel.level) + " profile:" + avcProfileToString(codecProfileLevel.profile));
                                if (codecProfileLevel.level > maxAVCLevel) {
                                    maxAVCLevel = codecProfileLevel.level;
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        Log.d(LOG_TAG, "getAVCLevel()->Max AVCLevel:" + maxAVCLevel + " " + avcProfileToString(maxAVCLevel));
    }
    return maxAVCLevel;
}
 
Example 13
Source File: MediaUtils.java    From jellyfin-androidtv with GNU General Public License v2.0 5 votes vote down vote up
private static boolean hasCodecForMime(boolean encoder, String mime) {
    for (MediaCodecInfo info : sMCL.getCodecInfos()) {
        if (encoder != info.isEncoder()) {
            continue;
        }
        for (String type : info.getSupportedTypes()) {
            if (type.equalsIgnoreCase(mime)) {
                Timber.i("found codec %s for mime %s", info.getName(), mime);
                return true;
            }
        }
    }
    return false;
}
 
Example 14
Source File: TrackTranscoderException.java    From LiTr with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@NonNull
private String convertMediaCodecInfoToString(@NonNull MediaCodecInfo mediaCodecInfo) {
    return "MediaCodecInfo: "
        + mediaCodecInfo.getName() + ','
        + mediaCodecInfo.isEncoder() + ','
        + Arrays.asList(mediaCodecInfo.getSupportedTypes()).toString();
}
 
Example 15
Source File: MediaCodecHelper.java    From libcommon with Apache License 2.0 5 votes vote down vote up
/**
	 * 指定したMIMEに一致する最初の音声エンコード用コーデックを選択する
	 * 対応するものがなければnullを返す
	 * @param mimeType
	 * @return
	 */
	@Deprecated
	@Nullable
	public static final MediaCodecInfo selectAudioEncoder(final String mimeType) {
//    	if (DEBUG) Log.v(TAG, "selectAudioCodec:");

 		MediaCodecInfo result = null;
 		// コーデックの一覧を取得
		//noinspection deprecation
		final int numCodecs = getCodecCount();
LOOP:	for (int i = 0; i < numCodecs; i++) {
			//noinspection deprecation
	     	final MediaCodecInfo codecInfo = getCodecInfoAt(i);
			if (!codecInfo.isEncoder()) {	// エンコーダーでない(=デコーダー)はスキップする
				continue;
			}
			final String[] types = codecInfo.getSupportedTypes();
			for (int j = 0; j < types.length; j++) {
//				if (DEBUG) Log.i(TAG, "supportedType:" + codecInfo.getName() + ",MIME=" + types[j]);
				if (types[j].equalsIgnoreCase(mimeType)) {
					result = codecInfo;
					break LOOP;
				}
			}
		}
		return result;
	}
 
Example 16
Source File: VideoEncoder.java    From DeviceConnect-Android with MIT License 5 votes vote down vote up
/**
 * 指定された MediaCodecInfo のマイムタイプとカラーフォーマットが一致するか確認します.
 *
 * @param codecInfo 確認する MediaCodecInfo
 * @param mimeType マイムタイプ
 * @param colorFormat カラーフォーマット
 * @return 一致する場合はtrue、それ以外はfalse
 */
private boolean isMediaCodecInfo(MediaCodecInfo codecInfo, String mimeType, int colorFormat) {
    if (!codecInfo.isEncoder()) {
        return false;
    }

    String[] types = codecInfo.getSupportedTypes();
    for (String type : types) {
        if (!type.equalsIgnoreCase(mimeType)) {
            continue;
        }

        try {
            MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(type);
            for (int i = 0; i < capabilities.colorFormats.length; i++) {
                int format = capabilities.colorFormats[i];
                if (colorFormat == format) {
                    return true;
                }
            }
        } catch (Exception e) {
            // ignore.
        }
    }

    return false;
}
 
Example 17
Source File: IjkMediaPlayer.java    From IjkPlayerDemo with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
        return null;

    if (TextUtils.isEmpty(mimeType))
        return null;

    Log.i(TAG, String.format(Locale.US, "onSelectCodec: mime=%s, profile=%d, level=%d", mimeType, profile, level));
    ArrayList<IjkMediaCodecInfo> candidateCodecList = new ArrayList<IjkMediaCodecInfo>();
    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        Log.d(TAG, String.format(Locale.US, "  found codec: %s", codecInfo.getName()));
        if (codecInfo.isEncoder())
            continue;

        String[] types = codecInfo.getSupportedTypes();
        if (types == null)
            continue;

        for(String type: types) {
            if (TextUtils.isEmpty(type))
                continue;

            Log.d(TAG, String.format(Locale.US, "    mime: %s", type));
            if (!type.equalsIgnoreCase(mimeType))
                continue;

            IjkMediaCodecInfo candidate = IjkMediaCodecInfo.setupCandidate(codecInfo, mimeType);
            if (candidate == null)
                continue;

            candidateCodecList.add(candidate);
            Log.i(TAG, String.format(Locale.US, "candidate codec: %s rank=%d", codecInfo.getName(), candidate.mRank));
            candidate.dumpProfileLevels(mimeType);
        }
    }

    if (candidateCodecList.isEmpty()) {
        return null;
    }

    IjkMediaCodecInfo bestCodec = candidateCodecList.get(0);

    for (IjkMediaCodecInfo codec : candidateCodecList) {
        if (codec.mRank > bestCodec.mRank) {
            bestCodec = codec;
        }
    }

    if (bestCodec.mRank < IjkMediaCodecInfo.RANK_LAST_CHANCE) {
        Log.w(TAG, String.format(Locale.US, "unaccetable codec: %s", bestCodec.mCodecInfo.getName()));
        return null;
    }

    Log.i(TAG, String.format(Locale.US, "selected codec: %s rank=%d", bestCodec.mCodecInfo.getName(), bestCodec.mRank));
    return bestCodec.mCodecInfo.getName();
}
 
Example 18
Source File: CodecManager.java    From spydroid-ipcamera with GNU General Public License v3.0 4 votes vote down vote up
/** 
 * Returns an associative array of the supported color formats and the names of the encoders for a given mime type
 * This can take up to sec on certain phones the first time you run it...
 **/
@SuppressLint("NewApi")
static private void findSupportedColorFormats(String mimeType) {
	SparseArray<ArrayList<String>> softwareCodecs = new SparseArray<ArrayList<String>>();
	SparseArray<ArrayList<String>> hardwareCodecs = new SparseArray<ArrayList<String>>();

	if (sSoftwareCodecs.containsKey(mimeType)) {
		return; 
	}

	Log.v(TAG,"Searching supported color formats for mime type \""+mimeType+"\"...");

	// We loop through the encoders, apparently this can take up to a sec (testes on a GS3)
	for(int j = MediaCodecList.getCodecCount() - 1; j >= 0; j--){
		MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(j);
		if (!codecInfo.isEncoder()) continue;

		String[] types = codecInfo.getSupportedTypes();
		for (int i = 0; i < types.length; i++) {
			if (types[i].equalsIgnoreCase(mimeType)) {
				MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);

				boolean software = false;
				for (int k=0;k<SOFTWARE_ENCODERS.length;k++) {
					if (codecInfo.getName().equalsIgnoreCase(SOFTWARE_ENCODERS[i])) {
						software = true;
					}
				}

				// And through the color formats supported
				for (int k = 0; k < capabilities.colorFormats.length; k++) {
					int format = capabilities.colorFormats[k];
					if (software) {
						if (softwareCodecs.get(format) == null) softwareCodecs.put(format, new ArrayList<String>());
						softwareCodecs.get(format).add(codecInfo.getName());
					} else {
						if (hardwareCodecs.get(format) == null) hardwareCodecs.put(format, new ArrayList<String>());
						hardwareCodecs.get(format).add(codecInfo.getName());
					}
				}

			}
		}
	}

	// Logs the supported color formats on the phone
	StringBuilder e = new StringBuilder();
	e.append("Supported color formats on this phone: ");
	for (int i=0;i<softwareCodecs.size();i++) e.append(softwareCodecs.keyAt(i)+", ");
	for (int i=0;i<hardwareCodecs.size();i++) e.append(hardwareCodecs.keyAt(i)+(i==hardwareCodecs.size()-1?".":", "));
	Log.v(TAG, e.toString());

	sSoftwareCodecs.put(mimeType, softwareCodecs);
	sHardwareCodecs.put(mimeType, hardwareCodecs);
	return;
}
 
Example 19
Source File: IjkMediaPlayer.java    From MKVideoPlayer with MIT License 4 votes vote down vote up
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
        return null;

    if (TextUtils.isEmpty(mimeType))
        return null;

    Log.i(TAG, String.format(Locale.US, "onSelectCodec: mime=%s, profile=%d, level=%d", mimeType, profile, level));
    ArrayList<IjkMediaCodecInfo> candidateCodecList = new ArrayList<IjkMediaCodecInfo>();
    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        Log.d(TAG, String.format(Locale.US, "  found codec: %s", codecInfo.getName()));
        if (codecInfo.isEncoder())
            continue;

        String[] types = codecInfo.getSupportedTypes();
        if (types == null)
            continue;

        for(String type: types) {
            if (TextUtils.isEmpty(type))
                continue;

            Log.d(TAG, String.format(Locale.US, "    mime: %s", type));
            if (!type.equalsIgnoreCase(mimeType))
                continue;

            IjkMediaCodecInfo candidate = IjkMediaCodecInfo.setupCandidate(codecInfo, mimeType);
            if (candidate == null)
                continue;

            candidateCodecList.add(candidate);
            Log.i(TAG, String.format(Locale.US, "candidate codec: %s rank=%d", codecInfo.getName(), candidate.mRank));
            candidate.dumpProfileLevels(mimeType);
        }
    }

    if (candidateCodecList.isEmpty()) {
        return null;
    }

    IjkMediaCodecInfo bestCodec = candidateCodecList.get(0);

    for (IjkMediaCodecInfo codec : candidateCodecList) {
        if (codec.mRank > bestCodec.mRank) {
            bestCodec = codec;
        }
    }

    if (bestCodec.mRank < IjkMediaCodecInfo.RANK_LAST_CHANCE) {
        Log.w(TAG, String.format(Locale.US, "unaccetable codec: %s", bestCodec.mCodecInfo.getName()));
        return null;
    }

    Log.i(TAG, String.format(Locale.US, "selected codec: %s rank=%d", bestCodec.mCodecInfo.getName(), bestCodec.mRank));
    return bestCodec.mCodecInfo.getName();
}
 
Example 20
Source File: IjkMediaPlayer.java    From DanDanPlayForAndroid with MIT License 4 votes vote down vote up
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
        return null;

    if (TextUtils.isEmpty(mimeType))
        return null;

    Log.i(TAG, String.format(Locale.US, "onSelectCodec: mime=%s, profile=%d, level=%d", mimeType, profile, level));
    ArrayList<IjkMediaCodecInfo> candidateCodecList = new ArrayList<IjkMediaCodecInfo>();
    int numCodecs = MediaCodecList.getCodecCount();
    for (int i = 0; i < numCodecs; i++) {
        MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
        Log.d(TAG, String.format(Locale.US, "  found codec: %s", codecInfo.getName()));
        if (codecInfo.isEncoder())
            continue;

        String[] types = codecInfo.getSupportedTypes();
        if (types == null)
            continue;

        for(String type: types) {
            if (TextUtils.isEmpty(type))
                continue;

            Log.d(TAG, String.format(Locale.US, "    mime: %s", type));
            if (!type.equalsIgnoreCase(mimeType))
                continue;

            IjkMediaCodecInfo candidate = IjkMediaCodecInfo.setupCandidate(codecInfo, mimeType);
            if (candidate == null)
                continue;

            candidateCodecList.add(candidate);
            Log.i(TAG, String.format(Locale.US, "candidate codec: %s rank=%d", codecInfo.getName(), candidate.mRank));
            candidate.dumpProfileLevels(mimeType);
        }
    }

    if (candidateCodecList.isEmpty()) {
        return null;
    }

    IjkMediaCodecInfo bestCodec = candidateCodecList.get(0);

    for (IjkMediaCodecInfo codec : candidateCodecList) {
        if (codec.mRank > bestCodec.mRank) {
            bestCodec = codec;
        }
    }

    if (bestCodec.mRank < IjkMediaCodecInfo.RANK_LAST_CHANCE) {
        Log.w(TAG, String.format(Locale.US, "unaccetable codec: %s", bestCodec.mCodecInfo.getName()));
        return null;
    }

    Log.i(TAG, String.format(Locale.US, "selected codec: %s rank=%d", bestCodec.mCodecInfo.getName(), bestCodec.mRank));
    return bestCodec.mCodecInfo.getName();
}