diff --git a/api/current.txt b/api/current.txt index 10562d555f2e5..4df948dba8cea 100644 --- a/api/current.txt +++ b/api/current.txt @@ -20225,6 +20225,24 @@ package android.media { field public static final int VP8Level_Version2 = 4; // 0x4 field public static final int VP8Level_Version3 = 8; // 0x8 field public static final int VP8ProfileMain = 1; // 0x1 + field public static final int VP9Level1 = 0; // 0x0 + field public static final int VP9Level11 = 1; // 0x1 + field public static final int VP9Level2 = 2; // 0x2 + field public static final int VP9Level21 = 4; // 0x4 + field public static final int VP9Level3 = 8; // 0x8 + field public static final int VP9Level31 = 16; // 0x10 + field public static final int VP9Level4 = 32; // 0x20 + field public static final int VP9Level41 = 64; // 0x40 + field public static final int VP9Level5 = 128; // 0x80 + field public static final int VP9Level51 = 256; // 0x100 + field public static final int VP9Level52 = 512; // 0x200 + field public static final int VP9Level6 = 1024; // 0x400 + field public static final int VP9Level61 = 2048; // 0x800 + field public static final int VP9Level62 = 4096; // 0x1000 + field public static final int VP9Profile0 = 0; // 0x0 + field public static final int VP9Profile1 = 1; // 0x1 + field public static final int VP9Profile2 = 2; // 0x2 + field public static final int VP9Profile3 = 3; // 0x3 field public int level; field public int profile; } diff --git a/api/system-current.txt b/api/system-current.txt index dc081bfcf8e3a..9482b954eec94 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -21577,6 +21577,24 @@ package android.media { field public static final int VP8Level_Version2 = 4; // 0x4 field public static final int VP8Level_Version3 = 8; // 0x8 field public static final int VP8ProfileMain = 1; // 0x1 + field public static final int VP9Level1 = 0; // 0x0 + field public static final int VP9Level11 = 1; // 0x1 + field public static final int VP9Level2 = 2; // 0x2 + field public static final int VP9Level21 = 4; // 0x4 + field public static final int VP9Level3 = 8; // 0x8 + field public static final int VP9Level31 = 16; // 0x10 + field public static final int VP9Level4 = 32; // 0x20 + field public static final int VP9Level41 = 64; // 0x40 + field public static final int VP9Level5 = 128; // 0x80 + field public static final int VP9Level51 = 256; // 0x100 + field public static final int VP9Level52 = 512; // 0x200 + field public static final int VP9Level6 = 1024; // 0x400 + field public static final int VP9Level61 = 2048; // 0x800 + field public static final int VP9Level62 = 4096; // 0x1000 + field public static final int VP9Profile0 = 0; // 0x0 + field public static final int VP9Profile1 = 1; // 0x1 + field public static final int VP9Profile2 = 2; // 0x2 + field public static final int VP9Profile3 = 3; // 0x3 field public int level; field public int profile; } diff --git a/api/test-current.txt b/api/test-current.txt index 1bf294bfb1032..2bd9eb25b8a26 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -20233,6 +20233,24 @@ package android.media { field public static final int VP8Level_Version2 = 4; // 0x4 field public static final int VP8Level_Version3 = 8; // 0x8 field public static final int VP8ProfileMain = 1; // 0x1 + field public static final int VP9Level1 = 0; // 0x0 + field public static final int VP9Level11 = 1; // 0x1 + field public static final int VP9Level2 = 2; // 0x2 + field public static final int VP9Level21 = 4; // 0x4 + field public static final int VP9Level3 = 8; // 0x8 + field public static final int VP9Level31 = 16; // 0x10 + field public static final int VP9Level4 = 32; // 0x20 + field public static final int VP9Level41 = 64; // 0x40 + field public static final int VP9Level5 = 128; // 0x80 + field public static final int VP9Level51 = 256; // 0x100 + field public static final int VP9Level52 = 512; // 0x200 + field public static final int VP9Level6 = 1024; // 0x400 + field public static final int VP9Level61 = 2048; // 0x800 + field public static final int VP9Level62 = 4096; // 0x1000 + field public static final int VP9Profile0 = 0; // 0x0 + field public static final int VP9Profile1 = 1; // 0x1 + field public static final int VP9Profile2 = 2; // 0x2 + field public static final int VP9Profile3 = 3; // 0x3 field public int level; field public int profile; } diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 331fde1365992..d9690f005364b 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1735,7 +1735,7 @@ public final class MediaCodecInfo { } private void applyLevelLimits() { - int maxBlocksPerSecond = 0; + long maxBlocksPerSecond = 0; int maxBlocks = 0; int maxBps = 0; int maxDPBBlocks = 0; @@ -2061,11 +2061,11 @@ public final class MediaCodecInfo { 16 /* blockWidth */, 16 /* blockHeight */, 1 /* widthAlignment */, 1 /* heightAlignment */); mFrameRateRange = Range.create(1, maxRate); - } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) || - mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { - maxBlocks = maxBlocksPerSecond = Integer.MAX_VALUE; + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8)) { + maxBlocks = Integer.MAX_VALUE; + maxBlocksPerSecond = Integer.MAX_VALUE; - // TODO: set to 100Mbps for now, need a number for VPX + // TODO: set to 100Mbps for now, need a number for VP8 maxBps = 100000000; // profile levels are not indicative for VPx, but verify @@ -2093,11 +2093,80 @@ public final class MediaCodecInfo { errors &= ~ERROR_NONE_SUPPORTED; } - final int blockSize = - mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP8) ? 16 : 8; + final int blockSize = 16; applyMacroBlockLimits(Short.MAX_VALUE, Short.MAX_VALUE, maxBlocks, maxBlocksPerSecond, blockSize, blockSize, 1 /* widthAlignment */, 1 /* heightAlignment */); + } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)) { + maxBlocksPerSecond = 829440; + maxBlocks = 36864; + maxBps = 200000; + + for (CodecProfileLevel profileLevel: profileLevels) { + long SR = 0; + int FS = 0; + int BR = 0; + switch (profileLevel.level) { + case CodecProfileLevel.VP9Level1: + SR = 829440; FS = 36864; BR = 200; break; + case CodecProfileLevel.VP9Level11: + SR = 2764800; FS = 73728; BR = 800; break; + case CodecProfileLevel.VP9Level2: + SR = 4608000; FS = 122880; BR = 1800; break; + case CodecProfileLevel.VP9Level21: + SR = 9216000; FS = 245760; BR = 3600; break; + case CodecProfileLevel.VP9Level3: + SR = 20736000; FS = 552960; BR = 7200; break; + case CodecProfileLevel.VP9Level31: + SR = 36864000; FS = 983040; BR = 12000; break; + case CodecProfileLevel.VP9Level4: + SR = 83558400; FS = 2228224; BR = 18000; break; + case CodecProfileLevel.VP9Level41: + SR = 160432128; FS = 2228224; BR = 30000; break; + case CodecProfileLevel.VP9Level5: + SR = 311951360; FS = 8912896; BR = 60000; break; + case CodecProfileLevel.VP9Level51: + SR = 588251136; FS = 8912896; BR = 120000; break; + case CodecProfileLevel.VP9Level52: + SR = 1176502272; FS = 8912896; BR = 180000; break; + case CodecProfileLevel.VP9Level6: + SR = 1176502272; FS = 35651584; BR = 180000; break; + case CodecProfileLevel.VP9Level61: + SR = 2353004544L; FS = 35651584; BR = 240000; break; + case CodecProfileLevel.VP9Level62: + SR = 4706009088L; FS = 35651584; BR = 480000; break; + default: + Log.w(TAG, "Unrecognized level " + + profileLevel.level + " for " + mime); + errors |= ERROR_UNRECOGNIZED; + } + switch (profileLevel.profile) { + case CodecProfileLevel.VP9Profile0: + case CodecProfileLevel.VP9Profile1: + case CodecProfileLevel.VP9Profile2: + case CodecProfileLevel.VP9Profile3: + break; + default: + Log.w(TAG, "Unrecognized profile " + + profileLevel.profile + " for " + mime); + errors |= ERROR_UNRECOGNIZED; + } + errors &= ~ERROR_NONE_SUPPORTED; + maxBlocksPerSecond = Math.max(SR, maxBlocksPerSecond); + maxBlocks = Math.max(FS, maxBlocks); + maxBps = Math.max(BR * 1000, maxBps); + } + + final int blockSize = 8; + int maxLengthInBlocks = Utils.divUp(maxBlocks, blockSize); + maxBlocks = Utils.divUp(maxBlocks, blockSize * blockSize); + maxBlocksPerSecond = Utils.divUp(maxBlocksPerSecond, blockSize * blockSize); + + applyMacroBlockLimits( + maxLengthInBlocks, maxLengthInBlocks, + maxBlocks, maxBlocksPerSecond, + blockSize, blockSize, + 1 /* widthAlignment */, 1 /* heightAlignment */); } else if (mime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { maxBlocks = 36864; maxBlocksPerSecond = maxBlocks * 15; @@ -2540,6 +2609,28 @@ public final class MediaCodecInfo { // from OMX_VIDEO_VP8PROFILETYPE public static final int VP8ProfileMain = 0x01; + // from OMX_VIDEO_VP9PROFILETYPE + public static final int VP9Profile0 = 0x00; + public static final int VP9Profile1 = 0x01; + public static final int VP9Profile2 = 0x02; + public static final int VP9Profile3 = 0x03; + + // from OMX_VIDEO_VP9LEVELTYPE + public static final int VP9Level1 = 0x0; + public static final int VP9Level11 = 0x1; + public static final int VP9Level2 = 0x2; + public static final int VP9Level21 = 0x4; + public static final int VP9Level3 = 0x8; + public static final int VP9Level31 = 0x10; + public static final int VP9Level4 = 0x20; + public static final int VP9Level41 = 0x40; + public static final int VP9Level5 = 0x80; + public static final int VP9Level51 = 0x100; + public static final int VP9Level52 = 0x200; + public static final int VP9Level6 = 0x400; + public static final int VP9Level61 = 0x800; + public static final int VP9Level62 = 0x1000; + // from OMX_VIDEO_HEVCPROFILETYPE public static final int HEVCProfileMain = 0x01; public static final int HEVCProfileMain10 = 0x02; @@ -2594,14 +2685,18 @@ public final class MediaCodecInfo { /** * Defined in the OpenMAX IL specs, depending on the type of media * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, - * OMX_VIDEO_MPEG4PROFILETYPE or OMX_VIDEO_VP8PROFILETYPE. + * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE. */ public int profile; /** * Defined in the OpenMAX IL specs, depending on the type of media * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE - * OMX_VIDEO_MPEG4LEVELTYPE or OMX_VIDEO_VP8LEVELTYPE. + * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE. + * + * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may + * not advertise a profile level support. For those VP9 decoders, please use + * {@link VideoCapabilities} to determine the codec capabilities. */ public int level; }; diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java index 2cd3c433407a1..35b083e66e699 100644 --- a/media/java/android/media/Utils.java +++ b/media/java/android/media/Utils.java @@ -174,7 +174,7 @@ class Utils { return (num + den - 1) / den; } - private static long divUp(long num, long den) { + static long divUp(long num, long den) { return (num + den - 1) / den; }