/** * 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. }
@SuppressWarnings("deprecation") @SuppressLint("NewApi") private static LinkedList<MediaCodecInfo> getMediaCodecList() { LinkedList<MediaCodecInfo> infoList = new LinkedList<MediaCodecInfo>(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); Collections.addAll(infoList, mcl.getCodecInfos()); } else { for (int i = 0; i < MediaCodecList.getCodecCount(); i++) { infoList.add(MediaCodecList.getCodecInfoAt(i)); } } return infoList; }
/** * 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; }
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; }
static { bannedYuvCodecs = new ArrayList<String>(); // Banned H264 encoders/decoders // Crashes bannedYuvCodecs.add("OMX.SEC.avc.enc"); bannedYuvCodecs.add("OMX.SEC.h263.enc"); // Don't support 3.1 profile used by Jitsi bannedYuvCodecs.add("OMX.Nvidia.h264.decode"); // bannedYuvCodecs.add("OMX.SEC.avc.dec"); // Banned VP8 encoders/decoders bannedYuvCodecs.add("OMX.SEC.vp8.dec"); // This one works only for res 176x144 bannedYuvCodecs.add("OMX.google.vpx.encoder"); for (int codecIndex = 0, codecCount = MediaCodecList.getCodecCount(); codecIndex < codecCount; codecIndex++) { MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(codecIndex); logger.info( "Discovered codec: " + codecInfo.getName() + "/" + Arrays.toString(codecInfo.getSupportedTypes())); CodecInfo ci = CodecInfo.getCodecInfo(codecInfo); if (ci != null) { codecs.add(ci); ci.setBanned(bannedYuvCodecs.contains(ci.getName())); } } logger.info("Selected H264 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_H264, true)); logger.info("Selected H264 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_H264, false)); logger.info("Selected H263 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_H263, true)); logger.info("Selected H263 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_H263, false)); logger.info("Selected VP8 encoder: " + getCodecForType(MEDIA_CODEC_TYPE_VP8, true)); logger.info("Selected VP8 decoder: " + getCodecForType(MEDIA_CODEC_TYPE_VP8, false)); }
@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); } }