1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.ui.mediapicker; 18 19 import android.hardware.Camera; 20 import android.media.CamcorderProfile; 21 import android.media.MediaRecorder; 22 import android.net.Uri; 23 24 import com.android.messaging.Factory; 25 import com.android.messaging.datamodel.MediaScratchFileProvider; 26 import com.android.messaging.util.ContentType; 27 import com.android.messaging.util.SafeAsyncTask; 28 29 import java.io.FileNotFoundException; 30 31 class MmsVideoRecorder extends MediaRecorder { 32 private static final float VIDEO_OVERSHOOT_SLOP = .85F; 33 34 private static final int BITS_PER_BYTE = 8; 35 36 // We think user will expect to be able to record videos at least this long 37 private static final long MIN_DURATION_LIMIT_SECONDS = 25; 38 39 /** The uri where video is being recorded to */ 40 private Uri mTempVideoUri; 41 42 /** The settings used for video recording */ 43 private final CamcorderProfile mCamcorderProfile; 44 MmsVideoRecorder(final Camera camera, final int cameraIndex, final int orientation, final int maxMessageSize)45 public MmsVideoRecorder(final Camera camera, final int cameraIndex, final int orientation, 46 final int maxMessageSize) 47 throws FileNotFoundException { 48 mCamcorderProfile = 49 CamcorderProfile.get(cameraIndex, CamcorderProfile.QUALITY_LOW); 50 mTempVideoUri = MediaScratchFileProvider.buildMediaScratchSpaceUri( 51 ContentType.getExtension(getContentType())); 52 53 // The video recorder can sometimes return a file that's larger than the max we 54 // say we can handle. Try to handle that overshoot by specifying an 85% limit. 55 final long sizeLimit = (long) (maxMessageSize * VIDEO_OVERSHOOT_SLOP); 56 57 // The QUALITY_LOW profile might not be low enough to allow for video of a reasonable 58 // minimum duration. Adjust a/v bitrates to allow at least MIN_DURATION_LIMIT video 59 // to be recorded. 60 int audioBitRate = mCamcorderProfile.audioBitRate; 61 int videoBitRate = mCamcorderProfile.videoBitRate; 62 final double initialDurationLimit = sizeLimit * BITS_PER_BYTE 63 / (double) (audioBitRate + videoBitRate); 64 if (initialDurationLimit < MIN_DURATION_LIMIT_SECONDS) { 65 // Reduce the suggested bitrates. These bitrates are only requests, if implementation 66 // can't actually hit these goals it will still record video at higher rate and stop when 67 // it hits the size limit. 68 final double bitRateAdjustmentFactor = initialDurationLimit / MIN_DURATION_LIMIT_SECONDS; 69 audioBitRate *= bitRateAdjustmentFactor; 70 videoBitRate *= bitRateAdjustmentFactor; 71 } 72 73 setCamera(camera); 74 setOrientationHint(orientation); 75 setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 76 setVideoSource(MediaRecorder.VideoSource.CAMERA); 77 setOutputFormat(mCamcorderProfile.fileFormat); 78 setOutputFile( 79 Factory.get().getApplicationContext().getContentResolver().openFileDescriptor( 80 mTempVideoUri, "w").getFileDescriptor()); 81 82 // Copy settings from CamcorderProfile to MediaRecorder 83 setAudioEncodingBitRate(audioBitRate); 84 setAudioChannels(mCamcorderProfile.audioChannels); 85 setAudioEncoder(mCamcorderProfile.audioCodec); 86 setAudioSamplingRate(mCamcorderProfile.audioSampleRate); 87 setVideoEncodingBitRate(videoBitRate); 88 setVideoEncoder(mCamcorderProfile.videoCodec); 89 setVideoFrameRate(mCamcorderProfile.videoFrameRate); 90 setVideoSize( 91 mCamcorderProfile.videoFrameWidth, mCamcorderProfile.videoFrameHeight); 92 setMaxFileSize(sizeLimit); 93 } 94 getVideoUri()95 Uri getVideoUri() { 96 return mTempVideoUri; 97 } 98 getVideoWidth()99 int getVideoWidth() { 100 return mCamcorderProfile.videoFrameWidth; 101 } 102 getVideoHeight()103 int getVideoHeight() { 104 return mCamcorderProfile.videoFrameHeight; 105 } 106 cleanupTempFile()107 void cleanupTempFile() { 108 final Uri tempUri = mTempVideoUri; 109 SafeAsyncTask.executeOnThreadPool(new Runnable() { 110 @Override 111 public void run() { 112 Factory.get().getApplicationContext().getContentResolver().delete( 113 tempUri, null, null); 114 } 115 }); 116 mTempVideoUri = null; 117 } 118 getContentType()119 String getContentType() { 120 if (mCamcorderProfile.fileFormat == OutputFormat.MPEG_4) { 121 return ContentType.VIDEO_MP4; 122 } else { 123 // 3GPP is the only other video format with a constant in OutputFormat 124 return ContentType.VIDEO_3GPP; 125 } 126 } 127 } 128