transcoding: Add capability check for transcoder tests

For MediaTranscodingManager tests, added checks to
confirm that the source and destination formats are
supported by the codecs created using createDecoderByType
and createEncoderByType, respectively, before transcoding.

Bug: 197267191
Test: atest CtsMediaTranscodingTestCases:
android.media.mediatranscoding.cts.MediaTranscodingManagerTest

Change-Id: I63a1442c41d94965e783ae3d1231e693ad303b62
(cherry picked from commit 105febd6f9f654c209061d68ac98f31949bbc9b5)
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
index 63cb151..c9b2b16 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
@@ -24,6 +24,8 @@
 import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.media.ApplicationMediaCapabilities;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
 import android.media.MediaTranscodingManager;
@@ -338,7 +340,7 @@
     // Tests transcoding to a uri in res folder and expects failure as test could not write to res
     // folder.
     public void testTranscodingToResFolder() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri:  android.resource://android.media.cts/temp.mp4
@@ -352,7 +354,7 @@
 
     // Tests transcoding to a uri in internal cache folder and expects success.
     public void testTranscodingToCacheDir() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri: file:///data/user/0/android.media.cts/cache/temp.mp4
@@ -366,7 +368,7 @@
 
     // Tests transcoding to a uri in internal files directory and expects success.
     public void testTranscodingToInternalFilesDir() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         // Create a file Uri: file:///data/user/0/android.media.cts/files/temp.mp4
@@ -424,14 +426,6 @@
         if (shouldSkip()) {
             return;
         }
-        MediaFormat format = new MediaFormat();
-        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC);
-        format.setInteger(MediaFormat.KEY_WIDTH, 3840);
-        format.setInteger(MediaFormat.KEY_HEIGHT, 2160);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
-        if (!MediaUtils.canDecode(format) || !MediaUtils.canEncode(format) ) {
-            return;
-        }
         transcodeFile(resourceToUri(mContext, R.raw.Video_4K_HEVC_64Frames_Audio,
                 "Video_4K_HEVC_64Frames_Audio.mp4"), false /* testFileDescriptor */);
     }
@@ -468,6 +462,12 @@
         MediaFormat videoTrackFormat = resolver.resolveVideoFormat();
         assertNotNull(videoTrackFormat);
 
+        // Return if the source or target video format is not supported
+        if (!isFormatSupported(srcVideoFormat, false)
+                || !isFormatSupported(videoTrackFormat, true)) {
+            return;
+        }
+
         int pid = android.os.Process.myPid();
         int uid = android.os.Process.myUid();
 
@@ -562,7 +562,7 @@
     }
 
     public void testCancelTranscoding() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testCancelTranscoding");
@@ -653,7 +653,7 @@
     }*/
 
     public void testTranscodingProgressUpdate() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -705,7 +705,7 @@
     }
 
     public void testAddingClientUids() throws Exception {
-        if (shouldSkip()) {
+        if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
             return;
         }
         Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -781,4 +781,56 @@
         extractor.release();
         return videoFormat;
     }
+
+    private boolean isVideoTranscodingSupported(Uri fileUri) throws IOException {
+        MediaFormat sourceFormat = getVideoTrackFormat(fileUri);
+        if (sourceFormat != null) {
+            // Since destination format is not available, we assume width, height and
+            // frame rate same as source format, and mime as AVC for destination format.
+            MediaFormat destinationFormat = new MediaFormat();
+            destinationFormat.setString(MediaFormat.KEY_MIME, MIME_TYPE);
+            destinationFormat.setInteger(MediaFormat.KEY_WIDTH,
+                    sourceFormat.getInteger(MediaFormat.KEY_WIDTH));
+            destinationFormat.setInteger(MediaFormat.KEY_HEIGHT,
+                    sourceFormat.getInteger(MediaFormat.KEY_HEIGHT));
+            if (sourceFormat.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+                destinationFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
+                        sourceFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
+            }
+            return isFormatSupported(sourceFormat, false)
+                    && isFormatSupported(destinationFormat, true);
+        }
+        return false;
+    }
+
+    private boolean isFormatSupported(MediaFormat format, boolean isEncoder) {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        MediaCodec codec = null;
+        try {
+            // The underlying transcoder library uses AMediaCodec_createEncoderByType
+            // to create encoder. So we cannot perform an exhaustive search of
+            // all codecs that support the format. This is because the codec that
+            // advertises support for the format during search may not be the one
+            // instantiated by the transcoder library. So, we have to check whether
+            // the codec returned by createEncoderByType supports the format.
+            // The same point holds for decoder too.
+            if (isEncoder) {
+                codec = MediaCodec.createEncoderByType(mime);
+            } else {
+                codec = MediaCodec.createDecoderByType(mime);
+            }
+            MediaCodecInfo info = codec.getCodecInfo();
+            MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
+            if (caps != null && caps.isFormatSupported(format) && info.isHardwareAccelerated()) {
+                return true;
+            }
+        } catch (IOException e) {
+            Log.d(TAG, "Exception: " + e);
+        } finally {
+            if (codec != null) {
+                codec.release();
+            }
+        }
+        return false;
+    }
 }