Last active
January 3, 2024 07:31
-
-
Save aelqsimi/f773d63fd5f234df7892276e3b05e5f8 to your computer and use it in GitHub Desktop.
Fetch mediacodec infos and get capabilities and supported features. The output is writed to the log and a file at the same time
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.nativemediacodectest; | |
import android.app.Activity; | |
import android.app.ProgressDialog; | |
import android.content.Intent; | |
import android.content.SharedPreferences; | |
import android.media.MediaCodecInfo; | |
import android.media.MediaCodecList; | |
import android.os.AsyncTask; | |
import android.os.Build; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.ProgressBar; | |
import android.widget.Toast; | |
import com.ektacom.nativemediacodectest.Activities.LogActivity; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.lang.ref.WeakReference; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback; | |
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_IntraRefresh; | |
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback; | |
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_TunneledPlayback; | |
public class TestMediaCodecInfoAsyncTask extends AsyncTask<String, String, String> { | |
private String TAG = TestMediaCodecInfoAsyncTask.class.getName(); | |
private WeakReference<ProgressBar> progressBarRef; | |
private WeakReference<Activity> activityRef; | |
public TestMediaCodecInfoAsyncTask(ProgressBar progressBar, Activity activity){ | |
this.progressBarRef = new WeakReference<>(progressBar); | |
this.activityRef = new WeakReference<>(activity); | |
} | |
@Override | |
protected void onPreExecute() { | |
super.onPreExecute(); | |
ProgressBar progressBar = progressBarRef.get(); | |
progressBar.setVisibility(View.VISIBLE); | |
} | |
@Override | |
protected void onPostExecute(String path) { | |
super.onPostExecute(path); | |
ProgressBar progressBar = progressBarRef.get(); | |
progressBar.setVisibility(View.INVISIBLE); | |
Activity mActivity = activityRef.get(); | |
Intent intent = new Intent(mActivity, LogActivity.class); | |
intent.putExtra("path",path); | |
mActivity.startActivity(intent); | |
} | |
/** | |
* Override this method to perform a computation on a background thread. The | |
* specified parameters are the parameters passed to {@link #execute} | |
* by the caller of this task. | |
* <p> | |
* This method can call {@link #publishProgress} to publish updates | |
* on the UI thread. | |
* | |
* @param args The parameters of the task. | |
* @return A result, defined by the subclass of this task. | |
* @see #onPreExecute() | |
* @see #onPostExecute | |
* @see #publishProgress | |
*/ | |
@Override | |
protected String doInBackground(String... args) { | |
String name = args[0]; | |
String path = ""; | |
if(name.length()>0) { | |
path = Utils.codecsPath +name+".txt"; | |
MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS); | |
MediaCodecInfo[] codecInfos = list.getCodecInfos(); | |
try (FileOutputStream stream = new FileOutputStream(path)) { | |
for (MediaCodecInfo info : codecInfos) { | |
if (name.equalsIgnoreCase(info.getName())) { | |
publishProgress("=== " + info.getName() + " ===\n"); | |
stream.write(("=== " + info.getName() + " ===\n").getBytes()); | |
boolean isEncoder = info.isEncoder(); | |
publishProgress("is Encoder = " + isEncoder); | |
stream.write(("is Encoder = " + isEncoder + "\n").getBytes()); | |
// list codec support media types | |
String[] types = info.getSupportedTypes(); | |
for (String type : types) { | |
publishProgress("Supported types = " + type); | |
stream.write(("Supported types = " + type + "\n").getBytes()); | |
// max instances | |
/* TODO API >= 23 */ | |
int max = -1; | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |
max = info.getCapabilitiesForType(type).getMaxSupportedInstances(); | |
publishProgress("Max instances for " + type + " = " + max); | |
stream.write(("Max instances for " + type + " = " + max + "\n").getBytes()); | |
stream.write(("---\n\n").getBytes()); | |
} | |
publishProgress("Supported colors for " + type + " :"); | |
stream.write(("Supported colors for " + type + " :\n").getBytes()); | |
// colors | |
Class<MediaCodecInfo.CodecCapabilities> c = MediaCodecInfo.CodecCapabilities.class; | |
int colors[] = info.getCapabilitiesForType(type).colorFormats; | |
for (int color : colors) { | |
for (Field f : c.getDeclaredFields()) { | |
int mod = f.getModifiers(); | |
if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) { | |
if (String.valueOf(color).equalsIgnoreCase(String.valueOf(f.get(null)))) { | |
publishProgress(" Support color number " + color + " aka " + f.getName()); | |
stream.write((" Support color number " + color + " aka " + f.getName() + "\n").getBytes()); | |
stream.write(("\n").getBytes()); | |
} | |
} | |
} | |
} | |
stream.write(("---\n\n").getBytes()); | |
// get capabilities of the given media type of the current codec | |
MediaCodecInfo.CodecCapabilities capabilitiesForType = info.getCapabilitiesForType(type); | |
publishProgress("Default format = " + capabilitiesForType.getDefaultFormat().toString()); | |
stream.write(("Default format = " + capabilitiesForType.getDefaultFormat().toString() + "\n").getBytes()); | |
stream.write(("---\n\n").getBytes()); | |
/* TODO API >= 24 */ | |
publishProgress("Features :"); | |
stream.write(("Features :\n").getBytes()); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
publishProgress(" IntraRefresh support = " + capabilitiesForType.isFeatureSupported(FEATURE_IntraRefresh)); | |
} | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | |
stream.write((" IntraRefresh support = " + capabilitiesForType.isFeatureSupported(FEATURE_IntraRefresh) + "\n").getBytes()); | |
stream.write(("---\n\n").getBytes()); | |
} | |
MediaCodecInfo.VideoCapabilities videoCapabilities = capabilitiesForType.getVideoCapabilities(); | |
if (videoCapabilities != null) { | |
// get video capabilities | |
publishProgress("Video capabilities :"); | |
stream.write(("Video capabilities :\n").getBytes()); | |
if(isEncoder) { | |
publishProgress(" BitrateRange = " + videoCapabilities.getBitrateRange()); | |
stream.write((" BitrateRange = " + videoCapabilities.getBitrateRange() + "\n").getBytes()); | |
} | |
publishProgress(" SupportedHeights = " + videoCapabilities.getSupportedHeights()); | |
stream.write((" Supported Heights = " + videoCapabilities.getSupportedHeights() + "\n").getBytes()); | |
publishProgress(" SupportedWidths = " + videoCapabilities.getSupportedWidths()); | |
stream.write((" Supported Widths = " + videoCapabilities.getSupportedWidths() + "\n").getBytes()); | |
publishProgress(" HeightAlignment = " + videoCapabilities.getHeightAlignment()); | |
stream.write((" Height Alignment = " + videoCapabilities.getHeightAlignment() + "\n").getBytes()); | |
publishProgress(" Width Alignment = " + videoCapabilities.getWidthAlignment()); | |
stream.write((" Width Alignment = " + videoCapabilities.getWidthAlignment() + "\n").getBytes()); | |
stream.write(("---\n\n").getBytes()); | |
// get profile & level capabilities | |
publishProgress("Video capabilities profile levels:"); | |
stream.write(("Video capabilities profile levels:\n").getBytes()); | |
String s1 = info.getName().substring(info.getName().indexOf(".", info.getName().indexOf(".") + 1) + 1); | |
String codecName = s1.substring(0, s1.indexOf(".")); | |
Class<MediaCodecInfo.CodecProfileLevel> cc = MediaCodecInfo.CodecProfileLevel.class; | |
for (int k = 0; k < capabilitiesForType.profileLevels.length; k++) { | |
for (Field f : cc.getDeclaredFields()) { | |
int mod = f.getModifiers(); | |
if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && Modifier.isFinal(mod)) { | |
if ((f.getName().toLowerCase().contains(codecName) || f.getName().toLowerCase().contains(type.substring(type.indexOf("/") + 1, type.length()))) && f.getName().toLowerCase().contains("profile")) { | |
if (String.valueOf(capabilitiesForType.profileLevels[k].profile).equalsIgnoreCase(f.get(null) + "")) { | |
publishProgress(" profile = " + capabilitiesForType.profileLevels[k].profile + " aka " + f.getName()); | |
stream.write((" profile = " + capabilitiesForType.profileLevels[k].profile + " aka " + f.getName() + "\n").getBytes()); | |
for (Field f2 : cc.getDeclaredFields()) { | |
int mod2 = f2.getModifiers(); | |
if (Modifier.isStatic(mod2) && Modifier.isPublic(mod2) && Modifier.isFinal(mod2)) { | |
if ((f2.getName().toLowerCase().contains(codecName) || f2.getName().toLowerCase().contains(type.substring(type.indexOf("/") + 1, type.length()))) && !f2.getName().toLowerCase().contains("profile")) { | |
if (String.valueOf(capabilitiesForType.profileLevels[k].level).equalsIgnoreCase(f2.get(null) + "")) { | |
publishProgress(" level = " + capabilitiesForType.profileLevels[k].level + " aka " + f2.getName()); | |
stream.write((" level = " + capabilitiesForType.profileLevels[k].level + " aka " + f2.getName() + "\n").getBytes()); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
if(!isEncoder) { | |
//Valid features | |
publishProgress("Features :"); | |
stream.write(("Features :\n").getBytes()); | |
publishProgress(" Adaptive playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_AdaptivePlayback)); | |
stream.write((" Adaptive playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_AdaptivePlayback) + "\n").getBytes()); | |
publishProgress(" Secure playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_SecurePlayback)); | |
stream.write((" Secure playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_SecurePlayback) + "\n").getBytes()); | |
publishProgress(" Tunneled playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_TunneledPlayback)); | |
stream.write((" Tunneled playback support = " + capabilitiesForType.isFeatureSupported(FEATURE_TunneledPlayback) + "\n").getBytes()); | |
} | |
} | |
publishProgress( | |
"=============\n"); | |
} | |
} | |
stream.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
return path; | |
} | |
protected void onProgressUpdate(String... log) { | |
Log.i(TAG, log[0]); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment