diff options
| author | 2021-01-08 19:54:37 +0000 | |
|---|---|---|
| committer | 2021-01-08 19:54:37 +0000 | |
| commit | 3e0290b3ad0cc497414d24f601a2ccb33ed5e183 (patch) | |
| tree | 0b438e7083160572ece93069830980b250987376 | |
| parent | eab713e3517d60ea08f63c85d69d1be1acf65c01 (diff) | |
| parent | 57c0f56bf7d0f13b9db05e516ec32c5a1bcc3f02 (diff) | |
Merge "transcoding: Use CamcorderProfile bitrate for transcoding."
| -rw-r--r-- | apex/media/framework/java/android/media/MediaTranscodeManager.java | 87 |
1 files changed, 84 insertions, 3 deletions
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java index d449289f156f..3d706e40bc0b 100644 --- a/apex/media/framework/java/android/media/MediaTranscodeManager.java +++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java @@ -109,6 +109,9 @@ public final class MediaTranscodeManager { /** Interval between trying to reconnect to the service. */ private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40; + /** Default bpp(bits-per-pixel) to use for calculating default bitrate. */ + private static final float BPP = 0.25f; + /** * Default transcoding type. * @hide @@ -1002,15 +1005,93 @@ public final class MediaTranscodeManager { if (!shouldTranscode()) { return null; } - // TODO(hkuang): Only modified the video codec type, and use fixed bitrate for now. - // May switch to transcoding profile when it's available. + MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint); videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); - videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); + + int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH); + int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT); + if (width <= 0 || height <= 0) { + throw new IllegalArgumentException( + "Source Width and height must be larger than 0"); + } + + // TODO(hkuang): Remove the hardcoded frameRate after b/176940364 is fixed. + float frameRate = (float) 30.0; + /*mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE, frameRate); + if (frameRate <= 0) { + throw new IllegalArgumentException( + "frameRate must be larger than 0"); + }*/ + + int bitrate = getAVCBitrate(width, height, frameRate); + videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); return videoTrackFormat; } /** + * Generate a default bitrate with the fixed bpp(bits-per-pixel) 0.25. + * This maps to: + * 1080P@30fps -> 16Mbps + * 1080P@60fps-> 32Mbps + * 4K@30fps -> 62Mbps + */ + private static int getDefaultBitrate(int width, int height, float frameRate) { + return (int) (width * height * frameRate * BPP); + } + + /** + * Query the bitrate from CamcorderProfile. If there are two profiles that match the + * width/height/framerate, we will use the higher one to get better quality. + * Return default bitrate if could not find any match profile. + */ + private static int getAVCBitrate(int width, int height, float frameRate) { + int bitrate = -1; + int[] cameraIds = {0, 1}; + + // Profiles ordered in decreasing order of preference. + int[] preferQualities = { + CamcorderProfile.QUALITY_2160P, + CamcorderProfile.QUALITY_1080P, + CamcorderProfile.QUALITY_720P, + CamcorderProfile.QUALITY_480P, + CamcorderProfile.QUALITY_LOW, + }; + + for (int cameraId : cameraIds) { + for (int quality : preferQualities) { + // Check if camera id has profile for the quality level. + if (!CamcorderProfile.hasProfile(cameraId, quality)) { + continue; + } + CamcorderProfile profile = CamcorderProfile.get(cameraId, quality); + // Check the width/height/framerate/codec, also consider portrait case. + if (((width == profile.videoFrameWidth + && height == profile.videoFrameHeight) + || (height == profile.videoFrameWidth + && width == profile.videoFrameHeight)) + && (int) frameRate == profile.videoFrameRate + && profile.videoCodec == MediaRecorder.VideoEncoder.H264) { + if (bitrate < profile.videoBitRate) { + bitrate = profile.videoBitRate; + } + break; + } + } + } + + if (bitrate == -1) { + Log.w(TAG, "Failed to find CamcorderProfile for w: " + width + "h: " + height + + " fps: " + + frameRate); + bitrate = getDefaultBitrate(width, height, frameRate); + } + Log.d(TAG, "Using bitrate " + bitrate + " for " + width + " " + height + " " + + frameRate); + return bitrate; + } + + /** * Retrieves the audio track format to be used for transcoding. * * @return the audio track format to be used if transcoding should be performed, and |