michael@0: /* michael@0: * Copyright (C) 2012 Mozilla Foundation michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #include "GonkRecorderProfiles.h" michael@0: #include michael@0: #include "GonkRecorder.h" michael@0: #include "CameraControlImpl.h" michael@0: #include "CameraCommon.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace android; michael@0: michael@0: #define DEF_GONK_RECORDER_PROFILE(e, n) e##_INDEX, michael@0: enum { michael@0: #include "GonkRecorderProfiles.def" michael@0: PROFILE_COUNT michael@0: }; michael@0: michael@0: #define DEF_GONK_RECORDER_PROFILE(e, n) { n, e }, michael@0: static struct { michael@0: const char* name; michael@0: int quality; michael@0: } ProfileList[] = { michael@0: #include "GonkRecorderProfiles.def" michael@0: { nullptr, 0 } michael@0: }; michael@0: michael@0: static MediaProfiles* sMediaProfiles = nullptr; michael@0: michael@0: static bool michael@0: IsQualitySupported(uint32_t aCameraId, uint32_t aQualityIndex) michael@0: { michael@0: if (!sMediaProfiles) { michael@0: sMediaProfiles = MediaProfiles::getInstance(); michael@0: } michael@0: camcorder_quality q = static_cast(ProfileList[aQualityIndex].quality); michael@0: return sMediaProfiles->hasCamcorderProfile(static_cast(aCameraId), q); michael@0: } michael@0: michael@0: static int michael@0: GetProfileParam(uint32_t aCameraId, uint32_t aQualityIndex, const char* aParam) michael@0: { michael@0: if (!sMediaProfiles) { michael@0: sMediaProfiles = MediaProfiles::getInstance(); michael@0: } michael@0: camcorder_quality q = static_cast(ProfileList[aQualityIndex].quality); michael@0: return sMediaProfiles->getCamcorderProfileParamByName(aParam, static_cast(aCameraId), q); michael@0: } michael@0: michael@0: /** michael@0: * Recorder profile. michael@0: */ michael@0: static RecorderProfile::FileFormat michael@0: TranslateFileFormat(output_format aFileFormat) michael@0: { michael@0: switch (aFileFormat) { michael@0: case OUTPUT_FORMAT_THREE_GPP: return RecorderProfile::THREE_GPP; michael@0: case OUTPUT_FORMAT_MPEG_4: return RecorderProfile::MPEG4; michael@0: default: return RecorderProfile::UNKNOWN; michael@0: } michael@0: } michael@0: michael@0: GonkRecorderProfile::GonkRecorderProfile(uint32_t aCameraId, uint32_t aQualityIndex) michael@0: : RecorderProfileBase(aCameraId, aQualityIndex) michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); michael@0: mPlatformOutputFormat = static_cast(GetProfileParam(mCameraId, mQualityIndex, "file.format")); michael@0: mFileFormat = TranslateFileFormat(mPlatformOutputFormat); michael@0: if (aQualityIndex < PROFILE_COUNT) { michael@0: mName = ProfileList[aQualityIndex].name; michael@0: DOM_CAMERA_LOGI("Created camera %d profile index %d: '%s'\n", mCameraId, mQualityIndex, mName); michael@0: } michael@0: } michael@0: michael@0: GonkRecorderProfile::~GonkRecorderProfile() michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); michael@0: } michael@0: michael@0: nsresult michael@0: GonkRecorderProfile::ConfigureRecorder(GonkRecorder* aRecorder) michael@0: { michael@0: static const size_t SIZE = 256; michael@0: char buffer[SIZE]; michael@0: michael@0: // set all the params michael@0: CHECK_SETARG(aRecorder->setAudioSource(AUDIO_SOURCE_CAMCORDER)); michael@0: CHECK_SETARG(aRecorder->setVideoSource(VIDEO_SOURCE_CAMERA)); michael@0: CHECK_SETARG(aRecorder->setOutputFormat(GetOutputFormat())); michael@0: CHECK_SETARG(aRecorder->setVideoFrameRate(mVideo.GetFramerate())); michael@0: CHECK_SETARG(aRecorder->setVideoSize(mVideo.GetWidth(), mVideo.GetHeight())); michael@0: CHECK_SETARG(aRecorder->setVideoEncoder(mVideo.GetPlatformCodec())); michael@0: CHECK_SETARG(aRecorder->setAudioEncoder(mAudio.GetPlatformCodec())); michael@0: michael@0: snprintf(buffer, SIZE, "video-param-encoding-bitrate=%d", mVideo.GetBitrate()); michael@0: CHECK_SETARG(aRecorder->setParameters(String8(buffer))); michael@0: michael@0: snprintf(buffer, SIZE, "audio-param-encoding-bitrate=%d", mAudio.GetBitrate()); michael@0: CHECK_SETARG(aRecorder->setParameters(String8(buffer))); michael@0: michael@0: snprintf(buffer, SIZE, "audio-param-number-of-channels=%d", mAudio.GetChannels()); michael@0: CHECK_SETARG(aRecorder->setParameters(String8(buffer))); michael@0: michael@0: snprintf(buffer, SIZE, "audio-param-sampling-rate=%d", mAudio.GetSamplerate()); michael@0: CHECK_SETARG(aRecorder->setParameters(String8(buffer))); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /** michael@0: * Recorder audio profile. michael@0: */ michael@0: static RecorderAudioProfile::Codec michael@0: TranslateAudioCodec(audio_encoder aCodec) michael@0: { michael@0: switch (aCodec) { michael@0: case AUDIO_ENCODER_AMR_NB: return RecorderAudioProfile::AMRNB; michael@0: case AUDIO_ENCODER_AMR_WB: return RecorderAudioProfile::AMRWB; michael@0: case AUDIO_ENCODER_AAC: return RecorderAudioProfile::AAC; michael@0: default: return RecorderAudioProfile::UNKNOWN; michael@0: } michael@0: } michael@0: michael@0: GonkRecorderAudioProfile::GonkRecorderAudioProfile(uint32_t aCameraId, uint32_t aQualityIndex) michael@0: : RecorderAudioProfile(aCameraId, aQualityIndex) michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); michael@0: mPlatformCodec = static_cast(GetProfileParam(mCameraId, mQualityIndex, "aud.codec")); michael@0: mCodec = TranslateAudioCodec(mPlatformCodec); michael@0: mBitrate = GetProfileParam(mCameraId, mQualityIndex, "aud.bps"); michael@0: mSamplerate = GetProfileParam(mCameraId, mQualityIndex, "aud.hz"); michael@0: mChannels = GetProfileParam(mCameraId, mQualityIndex, "aud.ch"); michael@0: } michael@0: michael@0: GonkRecorderAudioProfile::~GonkRecorderAudioProfile() michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); michael@0: } michael@0: michael@0: /** michael@0: * Recorder video profile. michael@0: */ michael@0: static RecorderVideoProfile::Codec michael@0: TranslateVideoCodec(video_encoder aCodec) michael@0: { michael@0: switch (aCodec) { michael@0: case VIDEO_ENCODER_H263: return RecorderVideoProfile::H263; michael@0: case VIDEO_ENCODER_H264: return RecorderVideoProfile::H264; michael@0: case VIDEO_ENCODER_MPEG_4_SP: return RecorderVideoProfile::MPEG4SP; michael@0: default: return RecorderVideoProfile::UNKNOWN; michael@0: } michael@0: } michael@0: michael@0: GonkRecorderVideoProfile::GonkRecorderVideoProfile(uint32_t aCameraId, uint32_t aQualityIndex) michael@0: : RecorderVideoProfile(aCameraId, aQualityIndex) michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraId=%d, mQualityIndex=%d\n", __func__, __LINE__, this, mCameraId, mQualityIndex); michael@0: mPlatformCodec = static_cast(GetProfileParam(mCameraId, mQualityIndex, "vid.codec")); michael@0: mCodec = TranslateVideoCodec(mPlatformCodec); michael@0: mBitrate = GetProfileParam(mCameraId, mQualityIndex, "vid.bps"); michael@0: mFramerate = GetProfileParam(mCameraId, mQualityIndex, "vid.fps"); michael@0: mWidth = GetProfileParam(mCameraId, mQualityIndex, "vid.width"); michael@0: mHeight = GetProfileParam(mCameraId, mQualityIndex, "vid.height"); michael@0: } michael@0: michael@0: GonkRecorderVideoProfile::~GonkRecorderVideoProfile() michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); michael@0: } michael@0: michael@0: GonkRecorderProfileManager::GonkRecorderProfileManager(uint32_t aCameraId) michael@0: : RecorderProfileManager(aCameraId) michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); michael@0: mMaxQualityIndex = sizeof(ProfileList) / sizeof(ProfileList[0]) - 1; michael@0: } michael@0: michael@0: GonkRecorderProfileManager::~GonkRecorderProfileManager() michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this); michael@0: } michael@0: michael@0: bool michael@0: GonkRecorderProfileManager::IsSupported(uint32_t aQualityIndex) const michael@0: { michael@0: if (!IsQualitySupported(mCameraId, aQualityIndex)) { michael@0: // This profile is not supported michael@0: return false; michael@0: } michael@0: michael@0: int width = GetProfileParam(mCameraId, aQualityIndex, "vid.width"); michael@0: int height = GetProfileParam(mCameraId, aQualityIndex, "vid.height"); michael@0: if (width == -1 || height == -1) { michael@0: // This would be unexpected, but we handle it just in case michael@0: DOM_CAMERA_LOGE("Camera %d recorder profile %d has width=%d, height=%d\n", mCameraId, aQualityIndex, width, height); michael@0: return false; michael@0: } michael@0: michael@0: for (uint32_t i = 0; i < mSupportedSizes.Length(); ++i) { michael@0: if (static_cast(width) == mSupportedSizes[i].width && michael@0: static_cast(height) == mSupportedSizes[i].height) michael@0: { michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: already_AddRefed michael@0: GonkRecorderProfileManager::Get(uint32_t aQualityIndex) const michael@0: { michael@0: // This overrides virtual RecorderProfileManager::Get(...) michael@0: DOM_CAMERA_LOGT("%s:%d : aQualityIndex=%d\n", __func__, __LINE__, aQualityIndex); michael@0: nsRefPtr profile = new GonkRecorderProfile(mCameraId, aQualityIndex); michael@0: return profile.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: GonkRecorderProfileManager::Get(const char* aProfileName) const michael@0: { michael@0: DOM_CAMERA_LOGT("%s:%d : aProfileName='%s'\n", __func__, __LINE__, aProfileName); michael@0: for (uint32_t i = 0; i < mMaxQualityIndex; ++i) { michael@0: if (strcmp(ProfileList[i].name, aProfileName) == 0) { michael@0: nsRefPtr profile = nullptr; michael@0: if (IsSupported(i)) { michael@0: profile = new GonkRecorderProfile(mCameraId, i); michael@0: return profile.forget(); michael@0: } michael@0: return nullptr; michael@0: } michael@0: } michael@0: michael@0: DOM_CAMERA_LOGW("Couldn't file recorder profile named '%s'\n", aProfileName); michael@0: return nullptr; michael@0: }