/** * select the first codec that match a specific MIME type * * @param mimeType * @return */ private static final MediaCodecInfo selectAudioCodec(final String mimeType) { if (DEBUG) Log.v(TAG, "selectAudioCodec:"); MediaCodecInfo result = null; // get the list of available codecs final int numCodecs = MediaCodecList.getCodecCount(); LOOP: for (int i = 0; i < numCodecs; i++) { final MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); if (!codecInfo.isEncoder()) { // skipp decoder 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)) { if (result == null) { result = codecInfo; break LOOP; } } } } return result; }
private static DecoderProperties findDecoder(String mime, String[] supportedCodecPrefixes) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return null; // MediaCodec.setParameters is missing. } for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) { MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); if (info.isEncoder()) { continue; } String name = null; for (String mimeType : info.getSupportedTypes()) { if (mimeType.equals(mime)) { name = info.getName(); break; } } if (name == null) { continue; // No HW support in this codec; try the next one. } Logging.v(TAG, "Found candidate decoder " + name); // Check if this is supported decoder. boolean supportedCodec = false; for (String codecPrefix : supportedCodecPrefixes) { if (name.startsWith(codecPrefix)) { supportedCodec = true; break; } } if (!supportedCodec) { continue; } // Check if codec supports either yuv420 or nv12. CodecCapabilities capabilities = info.getCapabilitiesForType(mime); for (int colorFormat : capabilities.colorFormats) { Logging.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat)); } for (int supportedColorFormat : supportedColorList) { for (int codecColorFormat : capabilities.colorFormats) { if (codecColorFormat == supportedColorFormat) { // Found supported HW decoder. Logging.d( TAG, "Found target decoder " + name + ". Color: 0x" + Integer.toHexString(codecColorFormat)); return new DecoderProperties(name, codecColorFormat); } } } } return null; // No HW decoder. }
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)) { Log.i(TAG, "found codec " + info.getName() + " for mime " + mime); return true; } } } return false; }
/** * 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; }
@SuppressWarnings("RedundantThrows") public static String dumpDecoders() throws Exception { String str = ""; for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { continue; } str += "Decoder: " + codecInfo.getName() + "\n"; for (String type : codecInfo.getSupportedTypes()) { str += "\t" + type + "\n"; CodecCapabilities caps = codecInfo.getCapabilitiesForType(type); for (CodecProfileLevel profile : caps.profileLevels) { str += "\t\t" + profile.profile + " " + profile.level + "\n"; } } } return str; }
// We declare this method as explicitly throwing Exception // since some bad decoders can throw IllegalArgumentExceptions unexpectedly // and we want to be sure all callers are handling this possibility @SuppressWarnings("RedundantThrows") private static MediaCodecInfo findKnownSafeDecoder(String mimeType, int requiredProfile) throws Exception { for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { continue; } // Check for explicitly blacklisted decoders if (isDecoderInList(blacklistedDecoderPrefixes, codecInfo.getName())) { LimeLog.info("Skipping blacklisted decoder: " + codecInfo.getName()); continue; } // Find a decoder that supports the requested video format for (String mime : codecInfo.getSupportedTypes()) { if (mime.equalsIgnoreCase(mimeType)) { LimeLog.info("Examining decoder capabilities of " + codecInfo.getName()); CodecCapabilities caps = codecInfo.getCapabilitiesForType(mime); if (requiredProfile != -1) { for (CodecProfileLevel profile : caps.profileLevels) { if (profile.profile == requiredProfile) { LimeLog.info("Decoder " + codecInfo.getName() + " supports required profile"); return codecInfo; } } LimeLog.info("Decoder " + codecInfo.getName() + " does NOT support required profile"); } else { return codecInfo; } } } } return null; }
private boolean supports(String mimeType, int profile, int level, boolean testLevel) { int numCodecs = MediaCodecList.getCodecCount(); for (int i = 0; i < numCodecs; i++) { MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i); if (codecInfo.isEncoder()) { continue; } if (!supportsMimeType(codecInfo, mimeType)) { continue; } CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType); for (CodecProfileLevel profileLevel : capabilities.profileLevels) { if (profileLevel.profile == profile && (!testLevel || profileLevel.level >= level)) { return true; } } } return false; }
private static MediaCodecInfo findPreferredDecoder() { // This is a different algorithm than the other findXXXDecoder functions, // because we want to evaluate the decoders in our list's order // rather than MediaCodecList's order for (String preferredDecoder : preferredDecoders) { for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { continue; } // Check for preferred decoders if (preferredDecoder.equalsIgnoreCase(codecInfo.getName())) { LimeLog.info("Preferred decoder choice is " + codecInfo.getName()); return codecInfo; } } } return null; }
public static MediaCodecInfo findFirstDecoder(String mimeType) { for (MediaCodecInfo codecInfo : getMediaCodecList()) { // Skip encoders if (codecInfo.isEncoder()) { continue; } // Check for explicitly blacklisted decoders if (isDecoderInList(blacklistedDecoderPrefixes, codecInfo.getName())) { LimeLog.info("Skipping blacklisted decoder: " + codecInfo.getName()); continue; } // Find a decoder that supports the specified video format for (String mime : codecInfo.getSupportedTypes()) { if (mime.equalsIgnoreCase(mimeType)) { LimeLog.info("First decoder choice is " + codecInfo.getName()); return codecInfo; } } } return null; }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mSurfaceView = (SurfaceView) findViewById(R.id.surface_view); // mSurfaceView.setBackgroundColor(Color.RED); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener( new View.OnClickListener() { private VideoPlayer mVideoPlayer = null; @Override public void onClick(View view) { if (mVideoPlayer != null) { mVideoPlayer.stop(); } mVideoPlayer = new VideoPlayer( MainActivity.mSelectedEncoder, mSurfaceView.getHolder().getSurface(), BASE_FOLDER + MainActivity.mSelectedFile); VideoPlayer.PlayTask task = new VideoPlayer.PlayTask(mVideoPlayer); task.execute(); // Snackbar.make(view, "Replace with your own action", // Snackbar.LENGTH_LONG) // .setAction("Action", null).show(); } }); List<String> decodersNames = new ArrayList<String>(); for (int i = 0; i < MediaCodecList.getCodecCount(); ++i) { MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i); Log.d(TAG, "onCreate: info " + i + info.getName()); if (!info.isEncoder() && (info.getName().contains("avc") || info.getName().contains("AVC") || info.getName().contains("h264") || info.getName().contains("H264"))) { decodersNames.add(info.getName()); } // mEncodersNames. = info.getName(); // String[] types = info.getSupportedTypes(); // String allTypes = ""; // for ( String type: types ) // { // allTypes += type + "; "; // } // Log.d(TAG, "XXXXXX - " + // "Name: " + info.getName() + ", " + // "Types: " + allTypes + ", " + // (info.isEncoder() ? "Encoder" : "Decoder")); } { mEncodersNames = new String[decodersNames.size()]; decodersNames.toArray(mEncodersNames); Spinner spinner = (Spinner) findViewById(R.id.listEncoders); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mEncodersNames); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Apply the adapter to the spinner. spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); } { File f = new File(new String(BASE_FOLDER)); File filesDir = f; // getFilesDir() Log.d(TAG, "searching for files in " + filesDir.toString()); mFilesNames = com.android.grafika.MiscUtils.getFiles(filesDir, "*"); Log.d(TAG, "files: " + mFilesNames.toString()); for (String file : mFilesNames) { Log.d(TAG, file); } Spinner spinner = (Spinner) findViewById(R.id.listFiles); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mFilesNames); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // Apply the adapter to the spinner. spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); } }
public boolean isEncoder() { return codecInfo.isEncoder(); }