1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/camera/GonkRecorderProfiles.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,248 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 Mozilla Foundation 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#include "GonkRecorderProfiles.h" 1.21 +#include <media/MediaProfiles.h> 1.22 +#include "GonkRecorder.h" 1.23 +#include "CameraControlImpl.h" 1.24 +#include "CameraCommon.h" 1.25 + 1.26 +using namespace mozilla; 1.27 +using namespace android; 1.28 + 1.29 +#define DEF_GONK_RECORDER_PROFILE(e, n) e##_INDEX, 1.30 +enum { 1.31 + #include "GonkRecorderProfiles.def" 1.32 + PROFILE_COUNT 1.33 +}; 1.34 + 1.35 +#define DEF_GONK_RECORDER_PROFILE(e, n) { n, e }, 1.36 +static struct { 1.37 + const char* name; 1.38 + int quality; 1.39 +} ProfileList[] = { 1.40 + #include "GonkRecorderProfiles.def" 1.41 + { nullptr, 0 } 1.42 +}; 1.43 + 1.44 +static MediaProfiles* sMediaProfiles = nullptr; 1.45 + 1.46 +static bool 1.47 +IsQualitySupported(uint32_t aCameraId, uint32_t aQualityIndex) 1.48 +{ 1.49 + if (!sMediaProfiles) { 1.50 + sMediaProfiles = MediaProfiles::getInstance(); 1.51 + } 1.52 + camcorder_quality q = static_cast<camcorder_quality>(ProfileList[aQualityIndex].quality); 1.53 + return sMediaProfiles->hasCamcorderProfile(static_cast<int>(aCameraId), q); 1.54 +} 1.55 + 1.56 +static int 1.57 +GetProfileParam(uint32_t aCameraId, uint32_t aQualityIndex, const char* aParam) 1.58 +{ 1.59 + if (!sMediaProfiles) { 1.60 + sMediaProfiles = MediaProfiles::getInstance(); 1.61 + } 1.62 + camcorder_quality q = static_cast<camcorder_quality>(ProfileList[aQualityIndex].quality); 1.63 + return sMediaProfiles->getCamcorderProfileParamByName(aParam, static_cast<int>(aCameraId), q); 1.64 +} 1.65 + 1.66 +/** 1.67 + * Recorder profile. 1.68 + */ 1.69 +static RecorderProfile::FileFormat 1.70 +TranslateFileFormat(output_format aFileFormat) 1.71 +{ 1.72 + switch (aFileFormat) { 1.73 + case OUTPUT_FORMAT_THREE_GPP: return RecorderProfile::THREE_GPP; 1.74 + case OUTPUT_FORMAT_MPEG_4: return RecorderProfile::MPEG4; 1.75 + default: return RecorderProfile::UNKNOWN; 1.76 + } 1.77 +} 1.78 + 1.79 +GonkRecorderProfile::GonkRecorderProfile(uint32_t aCameraId, uint32_t aQualityIndex) 1.80 + : RecorderProfileBase<GonkRecorderAudioProfile, GonkRecorderVideoProfile>(aCameraId, aQualityIndex) 1.81 +{ 1.82 + DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); 1.83 + mPlatformOutputFormat = static_cast<output_format>(GetProfileParam(mCameraId, mQualityIndex, "file.format")); 1.84 + mFileFormat = TranslateFileFormat(mPlatformOutputFormat); 1.85 + if (aQualityIndex < PROFILE_COUNT) { 1.86 + mName = ProfileList[aQualityIndex].name; 1.87 + DOM_CAMERA_LOGI("Created camera %d profile index %d: '%s'\n", mCameraId, mQualityIndex, mName); 1.88 + } 1.89 +} 1.90 + 1.91 +GonkRecorderProfile::~GonkRecorderProfile() 1.92 +{ 1.93 + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); 1.94 +} 1.95 + 1.96 +nsresult 1.97 +GonkRecorderProfile::ConfigureRecorder(GonkRecorder* aRecorder) 1.98 +{ 1.99 + static const size_t SIZE = 256; 1.100 + char buffer[SIZE]; 1.101 + 1.102 + // set all the params 1.103 + CHECK_SETARG(aRecorder->setAudioSource(AUDIO_SOURCE_CAMCORDER)); 1.104 + CHECK_SETARG(aRecorder->setVideoSource(VIDEO_SOURCE_CAMERA)); 1.105 + CHECK_SETARG(aRecorder->setOutputFormat(GetOutputFormat())); 1.106 + CHECK_SETARG(aRecorder->setVideoFrameRate(mVideo.GetFramerate())); 1.107 + CHECK_SETARG(aRecorder->setVideoSize(mVideo.GetWidth(), mVideo.GetHeight())); 1.108 + CHECK_SETARG(aRecorder->setVideoEncoder(mVideo.GetPlatformCodec())); 1.109 + CHECK_SETARG(aRecorder->setAudioEncoder(mAudio.GetPlatformCodec())); 1.110 + 1.111 + snprintf(buffer, SIZE, "video-param-encoding-bitrate=%d", mVideo.GetBitrate()); 1.112 + CHECK_SETARG(aRecorder->setParameters(String8(buffer))); 1.113 + 1.114 + snprintf(buffer, SIZE, "audio-param-encoding-bitrate=%d", mAudio.GetBitrate()); 1.115 + CHECK_SETARG(aRecorder->setParameters(String8(buffer))); 1.116 + 1.117 + snprintf(buffer, SIZE, "audio-param-number-of-channels=%d", mAudio.GetChannels()); 1.118 + CHECK_SETARG(aRecorder->setParameters(String8(buffer))); 1.119 + 1.120 + snprintf(buffer, SIZE, "audio-param-sampling-rate=%d", mAudio.GetSamplerate()); 1.121 + CHECK_SETARG(aRecorder->setParameters(String8(buffer))); 1.122 + 1.123 + return NS_OK; 1.124 +} 1.125 + 1.126 +/** 1.127 + * Recorder audio profile. 1.128 + */ 1.129 +static RecorderAudioProfile::Codec 1.130 +TranslateAudioCodec(audio_encoder aCodec) 1.131 +{ 1.132 + switch (aCodec) { 1.133 + case AUDIO_ENCODER_AMR_NB: return RecorderAudioProfile::AMRNB; 1.134 + case AUDIO_ENCODER_AMR_WB: return RecorderAudioProfile::AMRWB; 1.135 + case AUDIO_ENCODER_AAC: return RecorderAudioProfile::AAC; 1.136 + default: return RecorderAudioProfile::UNKNOWN; 1.137 + } 1.138 +} 1.139 + 1.140 +GonkRecorderAudioProfile::GonkRecorderAudioProfile(uint32_t aCameraId, uint32_t aQualityIndex) 1.141 + : RecorderAudioProfile(aCameraId, aQualityIndex) 1.142 +{ 1.143 + DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); 1.144 + mPlatformCodec = static_cast<audio_encoder>(GetProfileParam(mCameraId, mQualityIndex, "aud.codec")); 1.145 + mCodec = TranslateAudioCodec(mPlatformCodec); 1.146 + mBitrate = GetProfileParam(mCameraId, mQualityIndex, "aud.bps"); 1.147 + mSamplerate = GetProfileParam(mCameraId, mQualityIndex, "aud.hz"); 1.148 + mChannels = GetProfileParam(mCameraId, mQualityIndex, "aud.ch"); 1.149 +} 1.150 + 1.151 +GonkRecorderAudioProfile::~GonkRecorderAudioProfile() 1.152 +{ 1.153 + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); 1.154 +} 1.155 + 1.156 +/** 1.157 + * Recorder video profile. 1.158 + */ 1.159 +static RecorderVideoProfile::Codec 1.160 +TranslateVideoCodec(video_encoder aCodec) 1.161 +{ 1.162 + switch (aCodec) { 1.163 + case VIDEO_ENCODER_H263: return RecorderVideoProfile::H263; 1.164 + case VIDEO_ENCODER_H264: return RecorderVideoProfile::H264; 1.165 + case VIDEO_ENCODER_MPEG_4_SP: return RecorderVideoProfile::MPEG4SP; 1.166 + default: return RecorderVideoProfile::UNKNOWN; 1.167 + } 1.168 +} 1.169 + 1.170 +GonkRecorderVideoProfile::GonkRecorderVideoProfile(uint32_t aCameraId, uint32_t aQualityIndex) 1.171 + : RecorderVideoProfile(aCameraId, aQualityIndex) 1.172 +{ 1.173 + DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); 1.174 + mPlatformCodec = static_cast<video_encoder>(GetProfileParam(mCameraId, mQualityIndex, "vid.codec")); 1.175 + mCodec = TranslateVideoCodec(mPlatformCodec); 1.176 + mBitrate = GetProfileParam(mCameraId, mQualityIndex, "vid.bps"); 1.177 + mFramerate = GetProfileParam(mCameraId, mQualityIndex, "vid.fps"); 1.178 + mWidth = GetProfileParam(mCameraId, mQualityIndex, "vid.width"); 1.179 + mHeight = GetProfileParam(mCameraId, mQualityIndex, "vid.height"); 1.180 +} 1.181 + 1.182 +GonkRecorderVideoProfile::~GonkRecorderVideoProfile() 1.183 +{ 1.184 + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); 1.185 +} 1.186 + 1.187 +GonkRecorderProfileManager::GonkRecorderProfileManager(uint32_t aCameraId) 1.188 + : RecorderProfileManager(aCameraId) 1.189 +{ 1.190 + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); 1.191 + mMaxQualityIndex = sizeof(ProfileList) / sizeof(ProfileList[0]) - 1; 1.192 +} 1.193 + 1.194 +GonkRecorderProfileManager::~GonkRecorderProfileManager() 1.195 +{ 1.196 + DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); 1.197 +} 1.198 + 1.199 +bool 1.200 +GonkRecorderProfileManager::IsSupported(uint32_t aQualityIndex) const 1.201 +{ 1.202 + if (!IsQualitySupported(mCameraId, aQualityIndex)) { 1.203 + // This profile is not supported 1.204 + return false; 1.205 + } 1.206 + 1.207 + int width = GetProfileParam(mCameraId, aQualityIndex, "vid.width"); 1.208 + int height = GetProfileParam(mCameraId, aQualityIndex, "vid.height"); 1.209 + if (width == -1 || height == -1) { 1.210 + // This would be unexpected, but we handle it just in case 1.211 + DOM_CAMERA_LOGE("Camera %d recorder profile %d has width=%d, height=%d\n", mCameraId, aQualityIndex, width, height); 1.212 + return false; 1.213 + } 1.214 + 1.215 + for (uint32_t i = 0; i < mSupportedSizes.Length(); ++i) { 1.216 + if (static_cast<uint32_t>(width) == mSupportedSizes[i].width && 1.217 + static_cast<uint32_t>(height) == mSupportedSizes[i].height) 1.218 + { 1.219 + return true; 1.220 + } 1.221 + } 1.222 + return false; 1.223 +} 1.224 + 1.225 +already_AddRefed<RecorderProfile> 1.226 +GonkRecorderProfileManager::Get(uint32_t aQualityIndex) const 1.227 +{ 1.228 + // This overrides virtual RecorderProfileManager::Get(...) 1.229 + DOM_CAMERA_LOGT("%s:%d : aQualityIndex=%d\n", __func__, __LINE__, aQualityIndex); 1.230 + nsRefPtr<RecorderProfile> profile = new GonkRecorderProfile(mCameraId, aQualityIndex); 1.231 + return profile.forget(); 1.232 +} 1.233 + 1.234 +already_AddRefed<GonkRecorderProfile> 1.235 +GonkRecorderProfileManager::Get(const char* aProfileName) const 1.236 +{ 1.237 + DOM_CAMERA_LOGT("%s:%d : aProfileName='%s'\n", __func__, __LINE__, aProfileName); 1.238 + for (uint32_t i = 0; i < mMaxQualityIndex; ++i) { 1.239 + if (strcmp(ProfileList[i].name, aProfileName) == 0) { 1.240 + nsRefPtr<GonkRecorderProfile> profile = nullptr; 1.241 + if (IsSupported(i)) { 1.242 + profile = new GonkRecorderProfile(mCameraId, i); 1.243 + return profile.forget(); 1.244 + } 1.245 + return nullptr; 1.246 + } 1.247 + } 1.248 + 1.249 + DOM_CAMERA_LOGW("Couldn't file recorder profile named '%s'\n", aProfileName); 1.250 + return nullptr; 1.251 +}