Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e0290b3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "transcoding: Use CamcorderProfile bitrate for transcoding."

parents eab713e3 57c0f56b
Loading
Loading
Loading
Loading
+84 −3
Original line number Diff line number Diff line
@@ -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,14 +1005,92 @@ 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.
             *