Files
palemoon27/dom/camera/GonkRecorderProfiles.cpp
T
roytam1 86a3aa0b54 import changes from `dev' branch of rmottola/Arctic-Fox:
- missing part of  Bug 1165772: P1. (7311039be4)
- missing gstreamer stuff (54a80d69b2)
- Bug 1214208: Do not use MP3Decoder on B2G. r=alfredo (0a19e7946e)
- Bug 1194014 - Remove redundant includes. r=jya (ccc3753113)
- Bug 1039639 - Add support for Flac on Firefox OS. r=cajbir (7d76197e07)
- Bug 875573 - Add video/x-m4v mime type. r=kentuckyfriedtakahe (6ec8af93e6)
- cleanup (6fb3d5dd26)
- Bug 1180621 - [FxOS] Enable VP9 codec for the Android version after KK. r=sotaro (58f7c2b657)
- Bug 1187247: [MSE] P2. Enable WebM in MediaSource. r=jya (2df0ee1f7a)
- Bug 1187247: [MSE] P1. Continue parsing MediaSegment if buffer starts with SimpleBlock/Block. r=kinetik (574475ed6f)
- Bug 1217170: P1. Rename functions to explicitly reflect what they are doing. r=kentuckyfriedtakahe (70c81a8179)
- Bug 1070216 - Split DOMMediaStream::InitStreamCommon into three. r=roc (1bda71cc88)
- Bug 1215582 - Rename Blacklist to Block list in GStreamerFormatReader. r=gerald (4f08077f5e)
- Bug 1170958 - Destroy track-locked MediaInputPorts when the track ends. r=roc (ff3922a2d6)
- Bug 1070216 - constify DOMMediaStream::Get[Audio/Video]Tracks(). r=roc (ba09f6f191)
- Bug 1070216 - Guard against adding a track owned by one MSG to a stream owned by another. r=padenot (a80deb8b30)
- Bug 1070216 - Implement MediaStream constructors. r=smaug,jib,padenot (3403ef2599)
- Bug 1070216 - Guard against a null MediaInputPort in DOMMediaStream::FindPlaybackDOMTrack(). r=roc (453a9ffbc1)
- Bug 1212783 - Expose TrackPort in DOMMediaStream.h r=roc (fb61c79ae7)
- Bug 1219711 - Ensure MediaStreamTrack.enabled propagates across peer connections. r=jesup (d9d1e54dae)
- Bug 1129051 - Fix double free in Camera Control Listener. Fix webrtc memory leak. r=aosmond (3e9b3bccfd)
- Bug 1152260 - Generate focused event for drivers that do not notify us when using continuous auto focus. r=mikeh (6c7bd42fdc)
- Bug 1175656 - Implement generation of recording posters in Gecko. r=dhylands,bz (51b2c66dc7)
- Bug 1187364 - Part 1. Add ability for camera to pause/resume recording. r=dhylands,bz (c54c735e37)
- Bug 1187364 - Part 2. Ensure that recording is resumed with a key frame. r=mchiang (c1c6048982)
- Bug 1187364 - Part 3. Fix missing end comment in WebIDL. r=me,bz (7faf106cc1)
- Bug 1212783 - Add a MediaStreamTrack to DOMCameraControl. r=aosmond (91e11efd3a)
- Bug 1124338 - Fix possible camera cached parameters invalidation from underlying driver modification. r=aosmond (dea67dc155)
- Bug 1196330 - Do not restart preview if configuration is unchanged. r=dhylands (097644f5d9)
- Bug 1215372 - Filter empty camera face detected events at gonk layer. r=dhylands (733efe50eb)
- Bug 1179726 - Prefer lower resolutions than 4kuhd as the default video recording profile. r=dhylands (27c71273dc)
- Bug 1222122 - Add picture size to verified parameters when reconfiguring the camera. r=dhylands (8c1fac6a4a)
- Bug 1141267 - register CameraThread with profiler, r=aosmond (299592a024)
- Bug 1008483 - removes the RW lock in CameraControlImpl and replaces it with a standard mutex. r=aosmond (45936cb90d)
- Bug 1008483 - Part 2. Readd missing nsPrintfCString.h include which has broken some local builds. r=me (9dd84b0f19)
- Bug 1191731 - Update poster API to allow application control over when poster is saved. r=bz, r=dhylands (73f9e7e0f4)
- Bug 1155648 - Fix documentation for DOMMediaStream::OnTracksAvailable. r=jesup (702828c304)
- Bug 1217170: [MSE] P2. Enable WebM/MSE on systems with no MP4/H264 support. r=kentuckyfriedtakahe (0b814b0708)
- Bug 1213177: Enable WebM on machines where H264 HW decoding is disabled. r=kentuckyfriedtakahe (e64da2ea24)
- add back some sps telemetry (52c2c64f5b)
- missing bit of Bug 1195073: [MSE/webm] P1 (9c45e82c3d)
- Bug 1150305 - sourcebuffer.buffered returns the same object if not changed. r=roc, r=bz, r=jya (6005d56c0c)
- Bug 1215447 - move flag setting from SeekStarted() to Seek(). r=roc. (a646b744c1)
- Bug 1119936 - Audio from FM Radio or Music app ceases to play when switching between front/back camera. r=roc (1a60aa7d69)
- Bug 1186806 - Part 1: Replace nsBaseHashtable::EnumerateRead() with iterators in HTMLFormControlsCollection. r=khuey (ccb8cb180a)
- Bug 1186806 - Part 2: Use NS_IMPL_CYCLE_COLLECTION_TRAVERSE instead of manual traversal in HTMLFormElement. r=khuey (57e6eabf1b)
- Bug 1186806 - Part 3: Replace nsBaseHashtable::EnumerateRead() with iterators in HTMLMediaElement. r=khuey (243ef6e83b)
- Bug 1186806 - Part 4: Replace nsBaseHashtable::EnumerateRead() with iterators in HTMLPropertiesCollection. r=khuey (499bdef85f)
- Bug 1163958 - Reduce the allocation in MediaStreamGraph - patch 3 CLOSED TREE (a557661df1)
- Bug 1219330 - Prevent the creation of TextureClient after shutdown. r=mattwoodrow (a6c047d54f)
- Bug 1205559: Make TextureChild/TextureClient thread-safe. r=nical (307c089631)
- missing bit of 1219330 (0e351ea419)
- nsRefPtr -> RefPtr (07ba248e69)
- Bug 1215023. Part 1 - make MediaDecoder::mOwner a const member. We will check mShuttingDown before calling functions of mOwner. r=kinetik. (da7f201815)
- Bug 1215023. Part 2 - remove null check of mOwner. We check mShuttingDown to know whether it is valid to call functions of mOwner. r=kinetik. (8d28a04bbe)
- Bug 1220558. Part 2 - remove unused members. r=jya. (d3a9ed8c68)
- Bug 1223599 - Remove the throttling argument from AbstractMediaDecoder::NotifyDataArrived(). r=jya. (320323ff1d)
- Bug 1194606 - Make MediaDecoderStateMachine capable of requesting different kind (decoded/raw) of media data. r=jya (1e2b6a5c44)
- Bug 1197075: P3. Decode frames ahead of MDSM requesting them. r=edwin This makes the media.*-decode-ahead pref performs more according to its name. We decode audio and video in advance so a MediaDataPromise can be resolved almost instantly. Default is 2. (b3f56447c4)
- Bug 1189964 - Fix bustage. r=bustage CLOSED TREE (afaa49b4b5)
- Bug 1212149 - e10s support for opening notification settings. r=wchen (f0e7778fb6)
- Bug 1215644 - Use child process volume service cache for available and storage status requests. r=dhylands (dfd49f2ef3)
- bug 1215552 - nsHttpConnectionMgr::PostEvent shouldnt manually ref count r=hurley (5e2f1886e6)
- Bug 1219392 - Capitalize mozilla::unused to avoid conflicts. r=froydnj (0c8bb7f15a)
- bug 1217834 - buzzfeed packet loss r=dragana (e9a60b605f)
- Bug 1168033 - Add a comment to nsHttpConnectionMgr.cpp explaining the assignment of attemptedOptimisticPipeline. r=mcmanus (2451996350)
- bug 1189645 - remove spdy telem r=hurley (cda90abbdb)
- Bug 1148268 - fixed misspelling attribute mActorDestoryed. r=dhyland. (3615d68765)
- Bug 1216031 - Make MediaDecoder::mVideoFrameContainer const. r=kinetik. (a3feb9d6bc)
- missing bits of  Bug 1165515 - Part 13-2 (009e32281f)
- Bug 1131473 - crash in -[NativeMenuItemTarget menuItemHit:]. r=spohl (ea2da6441c)
- Bug 1216416 - Fix -Wimplicit-fallthrough warnings in widget/cocoa. r=spohl (faaa390b20)
- Bug 1181977 - Firefox app menu contains only "Quit" in certain edgecases. r=spohl (0b9d912961)
2022-12-06 13:48:22 +08:00

436 lines
12 KiB
C++

/*
* Copyright (C) 2012-2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "GonkRecorderProfiles.h"
#include "nsMimeTypes.h"
#include "CameraControlImpl.h"
#include "CameraCommon.h"
#ifdef MOZ_WIDGET_GONK
#include "GonkRecorder.h"
#endif
using namespace mozilla;
using namespace android;
namespace mozilla {
struct ProfileConfig {
const char* name;
int quality;
uint32_t priority;
};
#define DEF_GONK_RECORDER_PROFILE(e, n, p) { n, e, p },
static const ProfileConfig ProfileList[] = {
#include "GonkRecorderProfiles.def"
};
static const size_t ProfileListSize = MOZ_ARRAY_LENGTH(ProfileList);
struct ProfileConfigDetect {
const char* name;
uint32_t width;
uint32_t height;
uint32_t priority;
};
#define DEF_GONK_RECORDER_PROFILE_DETECT(n, w, h, p) { n, w, h, p },
static const ProfileConfigDetect ProfileListDetect[] = {
#include "GonkRecorderProfiles.def"
};
static const size_t ProfileListDetectSize = MOZ_ARRAY_LENGTH(ProfileListDetect);
};
/* static */ nsClassHashtable<nsUint32HashKey, ProfileHashtable> GonkRecorderProfile::sProfiles;
/* static */ android::MediaProfiles* sMediaProfiles = nullptr;
static MediaProfiles*
GetMediaProfiles()
{
if (!sMediaProfiles) {
sMediaProfiles = MediaProfiles::getInstance();
}
MOZ_ASSERT(sMediaProfiles);
return sMediaProfiles;
}
static bool
IsProfileSupported(uint32_t aCameraId, int aQuality)
{
MediaProfiles* profiles = GetMediaProfiles();
return profiles->hasCamcorderProfile(static_cast<int>(aCameraId),
static_cast<camcorder_quality>(aQuality));
}
static int
GetProfileParameter(uint32_t aCameraId, int aQuality, const char* aParameter)
{
MediaProfiles* profiles = GetMediaProfiles();
return profiles->getCamcorderProfileParamByName(aParameter, static_cast<int>(aCameraId),
static_cast<camcorder_quality>(aQuality));
}
/* static */ bool
GonkRecorderVideo::Translate(video_encoder aCodec, nsAString& aCodecName)
{
switch (aCodec) {
case VIDEO_ENCODER_H263:
aCodecName.AssignASCII("h263");
break;
case VIDEO_ENCODER_H264:
aCodecName.AssignASCII("h264");
break;
case VIDEO_ENCODER_MPEG_4_SP:
aCodecName.AssignASCII("mpeg4sp");
break;
default:
return false;
}
return true;
}
int
GonkRecorderVideo::GetProfileParameter(const char* aParameter)
{
return ::GetProfileParameter(mCameraId, mQuality, aParameter);
}
GonkRecorderVideo::GonkRecorderVideo(uint32_t aCameraId, int aQuality)
: mCameraId(aCameraId)
, mQuality(aQuality)
, mIsValid(false)
{
mPlatformEncoder = static_cast<video_encoder>(GetProfileParameter("vid.codec"));
bool isValid = Translate(mPlatformEncoder, mCodec);
int v = GetProfileParameter("vid.width");
if (v >= 0) {
mSize.width = v;
} else {
isValid = false;
}
v = GetProfileParameter("vid.height");
if (v >= 0) {
mSize.height = v;
} else {
isValid = false;
}
v = GetProfileParameter("vid.bps");
if (v >= 0) {
mBitsPerSecond = v;
} else {
isValid = false;
}
v = GetProfileParameter("vid.fps");
if (v >= 0) {
mFramesPerSecond = v;
} else {
isValid = false;
}
mIsValid = isValid;
}
/* static */ bool
GonkRecorderAudio::Translate(audio_encoder aCodec, nsAString& aCodecName)
{
switch (aCodec) {
case AUDIO_ENCODER_AMR_NB:
aCodecName.AssignASCII("amrnb");
break;
case AUDIO_ENCODER_AMR_WB:
aCodecName.AssignASCII("amrwb");
break;
case AUDIO_ENCODER_AAC:
aCodecName.AssignASCII("aac");
break;
default:
return false;
}
return true;
}
int
GonkRecorderAudio::GetProfileParameter(const char* aParameter)
{
return ::GetProfileParameter(mCameraId, mQuality, aParameter);
}
GonkRecorderAudio::GonkRecorderAudio(uint32_t aCameraId, int aQuality)
: mCameraId(aCameraId)
, mQuality(aQuality)
, mIsValid(false)
{
mPlatformEncoder = static_cast<audio_encoder>(GetProfileParameter("aud.codec"));
bool isValid = Translate(mPlatformEncoder, mCodec);
int v = GetProfileParameter("aud.ch");
if (v >= 0) {
mChannels = v;
} else {
isValid = false;
}
v = GetProfileParameter("aud.bps");
if (v >= 0) {
mBitsPerSecond = v;
} else {
isValid = false;
}
v = GetProfileParameter("aud.hz");
if (v >= 0) {
mSamplesPerSecond = v;
} else {
isValid = false;
}
mIsValid = isValid;
}
/* static */ bool
GonkRecorderProfile::Translate(output_format aContainer, nsAString& aContainerName)
{
switch (aContainer) {
case OUTPUT_FORMAT_THREE_GPP:
aContainerName.AssignASCII("3gp");
break;
case OUTPUT_FORMAT_MPEG_4:
aContainerName.AssignASCII("mp4");
break;
default:
return false;
}
return true;
}
/* static */ bool
GonkRecorderProfile::GetMimeType(output_format aContainer, nsAString& aMimeType)
{
switch (aContainer) {
case OUTPUT_FORMAT_THREE_GPP:
aMimeType.AssignASCII(VIDEO_3GPP);
break;
case OUTPUT_FORMAT_MPEG_4:
aMimeType.AssignASCII(VIDEO_MP4);
break;
default:
return false;
}
return true;
}
int
GonkRecorderProfile::GetProfileParameter(const char* aParameter)
{
return ::GetProfileParameter(mCameraId, mQuality, aParameter);
}
GonkRecorderProfile::GonkRecorderProfile(uint32_t aCameraId,
int aQuality)
: GonkRecorderProfileBase<GonkRecorderAudio, GonkRecorderVideo>(aCameraId,
aQuality)
, mCameraId(aCameraId)
, mQuality(aQuality)
, mIsValid(false)
{
mOutputFormat = static_cast<output_format>(GetProfileParameter("file.format"));
bool isValid = Translate(mOutputFormat, mContainer);
isValid = GetMimeType(mOutputFormat, mMimeType) ? isValid : false;
mIsValid = isValid && mAudio.IsValid() && mVideo.IsValid();
}
/* static */ PLDHashOperator
GonkRecorderProfile::Enumerate(const nsAString& aProfileName,
GonkRecorderProfile* aProfile,
void* aUserArg)
{
nsTArray<RefPtr<ICameraControl::RecorderProfile>>* profiles =
static_cast<nsTArray<RefPtr<ICameraControl::RecorderProfile>>*>(aUserArg);
MOZ_ASSERT(profiles);
profiles->AppendElement(aProfile);
return PL_DHASH_NEXT;
}
/* static */
already_AddRefed<GonkRecorderProfile>
GonkRecorderProfile::CreateProfile(uint32_t aCameraId, int aQuality)
{
if (!IsProfileSupported(aCameraId, aQuality)) {
DOM_CAMERA_LOGI("Profile %d not supported by platform\n", aQuality);
return nullptr;
}
RefPtr<GonkRecorderProfile> profile = new GonkRecorderProfile(aCameraId, aQuality);
if (!profile->IsValid()) {
DOM_CAMERA_LOGE("Profile %d is not valid\n", aQuality);
return nullptr;
}
return profile.forget();
}
/* static */
ProfileHashtable*
GonkRecorderProfile::GetProfileHashtable(uint32_t aCameraId)
{
ProfileHashtable* profiles = sProfiles.Get(aCameraId);
if (!profiles) {
profiles = new ProfileHashtable();
sProfiles.Put(aCameraId, profiles);
/* First handle the profiles with a known enum. We can process those
efficently because MediaProfiles indexes their profiles that way. */
int highestKnownQuality = CAMCORDER_QUALITY_LIST_START - 1;
for (size_t i = 0; i < ProfileListSize; ++i) {
const ProfileConfig& p = ProfileList[i];
if (p.quality > highestKnownQuality) {
highestKnownQuality = p.quality;
}
RefPtr<GonkRecorderProfile> profile = CreateProfile(aCameraId, p.quality);
if (!profile) {
continue;
}
DOM_CAMERA_LOGI("Profile %d '%s' supported by platform\n", p.quality, p.name);
profile->mName.AssignASCII(p.name);
profile->mPriority = p.priority;
profiles->Put(profile->GetName(), profile);
}
/* However not all of the potentially supported profiles have a known
enum on all of our supported platforms because some entries may
be missing from MediaProfiles.h. As such, we can't rely upon
having the CAMCORDER_QUALITY_* enums for those profiles. We need
to map the profiles to a name by matching the width and height of
the video resolution to our configured values.
In theory there may be collisions given that there can be multiple
resolutions sharing the same name (e.g. 800x480 and 768x480 are both
wvga). In practice this should not happen because there should be
only one WVGA profile given there is only one enum for it. In the
situation there is a collision, it will merely select the last
detected profile. */
for (int q = highestKnownQuality + 1; q <= CAMCORDER_QUALITY_LIST_END; ++q) {
RefPtr<GonkRecorderProfile> profile = CreateProfile(aCameraId, q);
if (!profile) {
continue;
}
const ICameraControl::Size& s = profile->GetVideo().GetSize();
size_t match;
for (match = 0; match < ProfileListDetectSize; ++match) {
const ProfileConfigDetect& p = ProfileListDetect[match];
if (s.width == p.width && s.height == p.height) {
DOM_CAMERA_LOGI("Profile %d '%s' supported by platform\n", q, p.name);
profile->mName.AssignASCII(p.name);
profile->mPriority = p.priority;
profiles->Put(profile->GetName(), profile);
break;
}
}
if (match == ProfileListDetectSize) {
DOM_CAMERA_LOGW("Profile %d size %u x %u is not recognized\n",
q, s.width, s.height);
}
}
}
return profiles;
}
/* static */ nsresult
GonkRecorderProfile::GetAll(uint32_t aCameraId,
nsTArray<RefPtr<ICameraControl::RecorderProfile>>& aProfiles)
{
ProfileHashtable* profiles = GetProfileHashtable(aCameraId);
if (!profiles) {
return NS_ERROR_FAILURE;
}
aProfiles.Clear();
profiles->EnumerateRead(Enumerate, static_cast<void*>(&aProfiles));
return NS_OK;
}
#ifdef MOZ_WIDGET_GONK
nsresult
GonkRecorderProfile::ConfigureRecorder(GonkRecorder& aRecorder)
{
static const size_t SIZE = 256;
char buffer[SIZE];
// set all the params
CHECK_SETARG(aRecorder.setAudioSource(AUDIO_SOURCE_CAMCORDER));
CHECK_SETARG(aRecorder.setVideoSource(VIDEO_SOURCE_CAMERA));
CHECK_SETARG(aRecorder.setOutputFormat(mOutputFormat));
CHECK_SETARG(aRecorder.setVideoFrameRate(mVideo.GetFramesPerSecond()));
CHECK_SETARG(aRecorder.setVideoSize(mVideo.GetSize().width, mVideo.GetSize().height));
CHECK_SETARG(aRecorder.setVideoEncoder(mVideo.GetPlatformEncoder()));
CHECK_SETARG(aRecorder.setAudioEncoder(mAudio.GetPlatformEncoder()));
snprintf(buffer, SIZE, "video-param-encoding-bitrate=%d", mVideo.GetBitsPerSecond());
CHECK_SETARG(aRecorder.setParameters(String8(buffer)));
snprintf(buffer, SIZE, "audio-param-encoding-bitrate=%d", mAudio.GetBitsPerSecond());
CHECK_SETARG(aRecorder.setParameters(String8(buffer)));
snprintf(buffer, SIZE, "audio-param-number-of-channels=%d", mAudio.GetChannels());
CHECK_SETARG(aRecorder.setParameters(String8(buffer)));
snprintf(buffer, SIZE, "audio-param-sampling-rate=%d", mAudio.GetSamplesPerSecond());
CHECK_SETARG(aRecorder.setParameters(String8(buffer)));
return NS_OK;
}
/* static */ nsresult
GonkRecorderProfile::ConfigureRecorder(android::GonkRecorder& aRecorder,
uint32_t aCameraId,
const nsAString& aProfileName)
{
ProfileHashtable* profiles = GetProfileHashtable(aCameraId);
if (!profiles) {
return NS_ERROR_FAILURE;
}
GonkRecorderProfile* profile;
if (!profiles->Get(aProfileName, &profile)) {
return NS_ERROR_INVALID_ARG;
}
return profile->ConfigureRecorder(aRecorder);
}
#endif