dom/camera/GonkRecorderProfiles.cpp

changeset 0
6474c204b198
     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 +}

mercurial