/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.messaging.ui.mediapicker; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaRecorder; import android.net.Uri; import com.android.messaging.Factory; import com.android.messaging.datamodel.MediaScratchFileProvider; import com.android.messaging.util.ContentType; import com.android.messaging.util.SafeAsyncTask; import java.io.FileNotFoundException; class MmsVideoRecorder extends MediaRecorder { private static final float VIDEO_OVERSHOOT_SLOP = .85F; private static final int BITS_PER_BYTE = 8; // We think user will expect to be able to record videos at least this long private static final long MIN_DURATION_LIMIT_SECONDS = 25; /** The uri where video is being recorded to */ private Uri mTempVideoUri; /** The settings used for video recording */ private final CamcorderProfile mCamcorderProfile; public MmsVideoRecorder(final Camera camera, final int cameraIndex, final int orientation, final int maxMessageSize) throws FileNotFoundException { mCamcorderProfile = CamcorderProfile.get(cameraIndex, CamcorderProfile.QUALITY_LOW); mTempVideoUri = MediaScratchFileProvider.buildMediaScratchSpaceUri( ContentType.getExtension(getContentType())); // The video recorder can sometimes return a file that's larger than the max we // say we can handle. Try to handle that overshoot by specifying an 85% limit. final long sizeLimit = (long) (maxMessageSize * VIDEO_OVERSHOOT_SLOP); // The QUALITY_LOW profile might not be low enough to allow for video of a reasonable // minimum duration. Adjust a/v bitrates to allow at least MIN_DURATION_LIMIT video // to be recorded. int audioBitRate = mCamcorderProfile.audioBitRate; int videoBitRate = mCamcorderProfile.videoBitRate; final double initialDurationLimit = sizeLimit * BITS_PER_BYTE / (double) (audioBitRate + videoBitRate); if (initialDurationLimit < MIN_DURATION_LIMIT_SECONDS) { // Reduce the suggested bitrates. These bitrates are only requests, if implementation // can't actually hit these goals it will still record video at higher rate and stop when // it hits the size limit. final double bitRateAdjustmentFactor = initialDurationLimit / MIN_DURATION_LIMIT_SECONDS; audioBitRate *= bitRateAdjustmentFactor; videoBitRate *= bitRateAdjustmentFactor; } setCamera(camera); setOrientationHint(orientation); setAudioSource(MediaRecorder.AudioSource.CAMCORDER); setVideoSource(MediaRecorder.VideoSource.CAMERA); setOutputFormat(mCamcorderProfile.fileFormat); setOutputFile( Factory.get().getApplicationContext().getContentResolver().openFileDescriptor( mTempVideoUri, "w").getFileDescriptor()); // Copy settings from CamcorderProfile to MediaRecorder setAudioEncodingBitRate(audioBitRate); setAudioChannels(mCamcorderProfile.audioChannels); setAudioEncoder(mCamcorderProfile.audioCodec); setAudioSamplingRate(mCamcorderProfile.audioSampleRate); setVideoEncodingBitRate(videoBitRate); setVideoEncoder(mCamcorderProfile.videoCodec); setVideoFrameRate(mCamcorderProfile.videoFrameRate); setVideoSize( mCamcorderProfile.videoFrameWidth, mCamcorderProfile.videoFrameHeight); setMaxFileSize(sizeLimit); } Uri getVideoUri() { return mTempVideoUri; } int getVideoWidth() { return mCamcorderProfile.videoFrameWidth; } int getVideoHeight() { return mCamcorderProfile.videoFrameHeight; } void cleanupTempFile() { final Uri tempUri = mTempVideoUri; SafeAsyncTask.executeOnThreadPool(new Runnable() { @Override public void run() { Factory.get().getApplicationContext().getContentResolver().delete( tempUri, null, null); } }); mTempVideoUri = null; } String getContentType() { if (mCamcorderProfile.fileFormat == OutputFormat.MPEG_4) { return ContentType.VIDEO_MP4; } else { // 3GPP is the only other video format with a constant in OutputFormat return ContentType.VIDEO_3GPP; } } }