• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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