mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 842715: Refactor gUM prefs use to be on mainthread, and prepare for constraints r=derf
This commit is contained in:
parent
f22ad604ac
commit
c92ed777f4
@ -20,6 +20,7 @@ namespace mozilla {
|
||||
*/
|
||||
class MediaEngineVideoSource;
|
||||
class MediaEngineAudioSource;
|
||||
struct MediaEnginePrefs;
|
||||
|
||||
enum MediaEngineState {
|
||||
kAllocated,
|
||||
@ -39,6 +40,11 @@ class MediaEngine
|
||||
public:
|
||||
virtual ~MediaEngine() {}
|
||||
|
||||
static const int DEFAULT_VIDEO_FPS = 30;
|
||||
static const int DEFAULT_VIDEO_MIN_FPS = 10;
|
||||
static const int DEFAULT_VIDEO_WIDTH = 640;
|
||||
static const int DEFAULT_VIDEO_HEIGHT = 480;
|
||||
|
||||
/* Populate an array of video sources in the nsTArray. Also include devices
|
||||
* that are currently unavailable. */
|
||||
virtual void EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >*) = 0;
|
||||
@ -63,7 +69,7 @@ public:
|
||||
virtual void GetUUID(nsAString&) = 0;
|
||||
|
||||
/* This call reserves but does not start the device. */
|
||||
virtual nsresult Allocate() = 0;
|
||||
virtual nsresult Allocate(const MediaEnginePrefs &aPrefs) = 0;
|
||||
|
||||
/* Release the device back to the system. */
|
||||
virtual nsresult Deallocate() = 0;
|
||||
@ -113,27 +119,17 @@ protected:
|
||||
/**
|
||||
* Video source and friends.
|
||||
*/
|
||||
enum MediaEngineVideoCodecType {
|
||||
kVideoCodecH263,
|
||||
kVideoCodecVP8,
|
||||
kVideoCodecI420
|
||||
};
|
||||
|
||||
struct MediaEngineVideoOptions {
|
||||
uint32_t mWidth;
|
||||
uint32_t mHeight;
|
||||
uint32_t mMaxFPS;
|
||||
MediaEngineVideoCodecType codecType;
|
||||
struct MediaEnginePrefs {
|
||||
int32_t mWidth;
|
||||
int32_t mHeight;
|
||||
int32_t mFPS;
|
||||
int32_t mMinFPS;
|
||||
};
|
||||
|
||||
class MediaEngineVideoSource : public MediaEngineSource
|
||||
{
|
||||
public:
|
||||
virtual ~MediaEngineVideoSource() {}
|
||||
|
||||
/* Return a MediaEngineVideoOptions struct with appropriate values for all
|
||||
* fields. */
|
||||
virtual const MediaEngineVideoOptions *GetOptions() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -30,14 +30,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultVideoSource, nsITimerCallback)
|
||||
* Default video source.
|
||||
*/
|
||||
|
||||
MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource(int32_t aWidth,
|
||||
int32_t aHeight,
|
||||
int32_t aFPS)
|
||||
MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource()
|
||||
: mTimer(nullptr)
|
||||
{
|
||||
mOpts.mWidth = aWidth;
|
||||
mOpts.mHeight = aHeight;
|
||||
mOpts.mMaxFPS = aFPS;
|
||||
mState = kReleased;
|
||||
}
|
||||
|
||||
@ -59,12 +54,13 @@ MediaEngineDefaultVideoSource::GetUUID(nsAString& aUUID)
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineDefaultVideoSource::Allocate()
|
||||
MediaEngineDefaultVideoSource::Allocate(const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
if (mState != kReleased) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mOpts = aPrefs;
|
||||
mState = kAllocated;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -79,12 +75,6 @@ MediaEngineDefaultVideoSource::Deallocate()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const MediaEngineVideoOptions *
|
||||
MediaEngineDefaultVideoSource::GetOptions()
|
||||
{
|
||||
return &mOpts;
|
||||
}
|
||||
|
||||
static void AllocateSolidColorFrame(layers::PlanarYCbCrImage::Data& aData,
|
||||
int aWidth, int aHeight,
|
||||
int aY, int aCb, int aCr)
|
||||
@ -150,7 +140,7 @@ MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
|
||||
// AddTrack takes ownership of segment
|
||||
VideoSegment *segment = new VideoSegment();
|
||||
segment->AppendFrame(image.forget(), USECS_PER_S / mOpts.mMaxFPS,
|
||||
segment->AppendFrame(image.forget(), USECS_PER_S / mOpts.mFPS,
|
||||
gfxIntSize(mOpts.mWidth, mOpts.mHeight));
|
||||
mSource->AddTrack(aID, VIDEO_RATE, 0, segment);
|
||||
|
||||
@ -161,7 +151,7 @@ MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
mTrackID = aID;
|
||||
|
||||
// Start timer for subsequent frames
|
||||
mTimer->InitWithCallback(this, 1000 / mOpts.mMaxFPS, nsITimer::TYPE_REPEATING_SLACK);
|
||||
mTimer->InitWithCallback(this, 1000 / mOpts.mFPS, nsITimer::TYPE_REPEATING_SLACK);
|
||||
mState = kStarted;
|
||||
|
||||
return NS_OK;
|
||||
@ -250,7 +240,7 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
|
||||
|
||||
// AddTrack takes ownership of segment
|
||||
VideoSegment segment;
|
||||
segment.AppendFrame(ycbcr_image.forget(), USECS_PER_S / mOpts.mMaxFPS,
|
||||
segment.AppendFrame(ycbcr_image.forget(), USECS_PER_S / mOpts.mFPS,
|
||||
gfxIntSize(mOpts.mWidth, mOpts.mHeight));
|
||||
mSource->AppendToTrack(mTrackID, &segment);
|
||||
|
||||
@ -301,7 +291,7 @@ MediaEngineDefaultAudioSource::GetUUID(nsAString& aUUID)
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineDefaultAudioSource::Allocate()
|
||||
MediaEngineDefaultAudioSource::Allocate(const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
if (mState != kReleased) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -393,45 +383,14 @@ MediaEngineDefaultAudioSource::Notify(nsITimer* aTimer)
|
||||
void
|
||||
MediaEngineDefault::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources) {
|
||||
MutexAutoLock lock(mMutex);
|
||||
int32_t found = false;
|
||||
int32_t len = mVSources.Length();
|
||||
|
||||
int32_t width = MediaEngineDefaultVideoSource::DEFAULT_VIDEO_WIDTH;
|
||||
int32_t height = MediaEngineDefaultVideoSource::DEFAULT_VIDEO_HEIGHT;
|
||||
int32_t fps = MediaEngineDefaultVideoSource::DEFAULT_VIDEO_FPS;
|
||||
// We once had code here to find a VideoSource with the same settings and re-use that.
|
||||
// This no longer is possible since the resolution is being set in Allocate().
|
||||
|
||||
// FIX - these should be passed in originating in prefs and/or getUserMedia constraints
|
||||
// Bug 778801
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
nsRefPtr<MediaEngineVideoSource> newSource = new MediaEngineDefaultVideoSource();
|
||||
mVSources.AppendElement(newSource);
|
||||
aVSources->AppendElement(newSource);
|
||||
|
||||
if (branch) {
|
||||
// these very rarely change
|
||||
branch->GetIntPref("media.navigator.video.default_width", &width);
|
||||
branch->GetIntPref("media.navigator.video.default_height", &height);
|
||||
branch->GetIntPref("media.navigator.video.default_fps", &fps);
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
nsRefPtr<MediaEngineVideoSource> source = mVSources.ElementAt(i);
|
||||
aVSources->AppendElement(source);
|
||||
const MediaEngineVideoOptions *opts = source->GetOptions();
|
||||
if (source->IsAvailable() &&
|
||||
opts->mWidth == width && opts->mHeight == height && opts->mMaxFPS == fps) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// All streams are currently busy (or wrong resolution), just make a new one.
|
||||
if (!found) {
|
||||
nsRefPtr<MediaEngineVideoSource> newSource =
|
||||
new MediaEngineDefaultVideoSource(width, height, fps);
|
||||
mVSources.AppendElement(newSource);
|
||||
aVSources->AppendElement(newSource);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -34,14 +34,13 @@ class MediaEngineDefaultVideoSource : public nsITimerCallback,
|
||||
public MediaEngineVideoSource
|
||||
{
|
||||
public:
|
||||
MediaEngineDefaultVideoSource(int aWidth, int aHeight, int aFPS);
|
||||
MediaEngineDefaultVideoSource();
|
||||
~MediaEngineDefaultVideoSource();
|
||||
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
|
||||
virtual const MediaEngineVideoOptions *GetOptions();
|
||||
virtual nsresult Allocate();
|
||||
virtual nsresult Allocate(const MediaEnginePrefs &aPrefs);
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop(SourceMediaStream*, TrackID);
|
||||
@ -73,7 +72,7 @@ protected:
|
||||
|
||||
SourceMediaStream* mSource;
|
||||
layers::PlanarYCbCrImage* mImage;
|
||||
MediaEngineVideoOptions mOpts;
|
||||
MediaEnginePrefs mOpts;
|
||||
int mCb;
|
||||
int mCr;
|
||||
};
|
||||
@ -88,7 +87,7 @@ public:
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
|
||||
virtual nsresult Allocate();
|
||||
virtual nsresult Allocate(const MediaEnginePrefs &aPrefs);
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop(SourceMediaStream*, TrackID);
|
||||
|
@ -43,36 +43,6 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
int32_t width = MediaEngineWebRTCVideoSource::DEFAULT_VIDEO_WIDTH;
|
||||
int32_t height = MediaEngineWebRTCVideoSource::DEFAULT_VIDEO_HEIGHT;
|
||||
int32_t fps = MediaEngineWebRTCVideoSource::DEFAULT_VIDEO_FPS;
|
||||
int32_t minfps = MediaEngineWebRTCVideoSource::DEFAULT_VIDEO_MIN_FPS;
|
||||
|
||||
// FIX - these should be passed in originating in prefs and/or getUserMedia constraints
|
||||
// Bug 778801
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
|
||||
if (branch) {
|
||||
branch->GetIntPref("media.navigator.video.default_width", &width);
|
||||
branch->GetIntPref("media.navigator.video.default_height", &height);
|
||||
branch->GetIntPref("media.navigator.video.default_fps", &fps);
|
||||
branch->GetIntPref("media.navigator.video.default_min_fps", &minfps);
|
||||
}
|
||||
}
|
||||
LOG(("%s: %dx%d @%dfps (min %d)", __FUNCTION__, width, height, fps, minfps));
|
||||
|
||||
bool changed = false;
|
||||
if (width != mWidth || height != mHeight || fps != mFPS || minfps != mMinFPS) {
|
||||
changed = true;
|
||||
}
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mFPS = fps;
|
||||
mMinFPS = minfps;
|
||||
|
||||
if (!mVideoEngine) {
|
||||
if (!(mVideoEngine = webrtc::VideoEngine::Create())) {
|
||||
return;
|
||||
@ -162,17 +132,16 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
||||
if (uniqueId[0] == '\0') {
|
||||
// In case a device doesn't set uniqueId!
|
||||
strncpy(uniqueId, deviceName, sizeof(uniqueId));
|
||||
uniqueId[sizeof(uniqueId)-1] = '\0'; // strncpy isn't safe
|
||||
uniqueId[sizeof(uniqueId)-1] = '\0'; // strncpy isn't safe
|
||||
}
|
||||
|
||||
nsRefPtr<MediaEngineWebRTCVideoSource> vSource;
|
||||
NS_ConvertUTF8toUTF16 uuid(uniqueId);
|
||||
if (!changed && mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
|
||||
if (mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
|
||||
// We've already seen this device, just append.
|
||||
aVSources->AppendElement(vSource.get());
|
||||
} else {
|
||||
vSource = new MediaEngineWebRTCVideoSource(mVideoEngine, i,
|
||||
width, height, fps, minfps);
|
||||
vSource = new MediaEngineWebRTCVideoSource(mVideoEngine, i);
|
||||
mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
|
||||
aVSources->AppendElement(vSource);
|
||||
}
|
||||
|
@ -56,27 +56,18 @@ class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource,
|
||||
public nsRunnable
|
||||
{
|
||||
public:
|
||||
static const int DEFAULT_VIDEO_FPS = 60;
|
||||
static const int DEFAULT_VIDEO_MIN_FPS = 10;
|
||||
static const int DEFAULT_VIDEO_WIDTH = 640;
|
||||
static const int DEFAULT_VIDEO_HEIGHT = 480;
|
||||
|
||||
// ViEExternalRenderer.
|
||||
virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int);
|
||||
virtual int DeliverFrame(unsigned char*, int, uint32_t, int64_t);
|
||||
|
||||
MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr,
|
||||
int aIndex,
|
||||
int aWidth = DEFAULT_VIDEO_WIDTH, int aHeight = DEFAULT_VIDEO_HEIGHT,
|
||||
int aFps = DEFAULT_VIDEO_FPS, int aMinFps = DEFAULT_VIDEO_MIN_FPS)
|
||||
MediaEngineWebRTCVideoSource(webrtc::VideoEngine* aVideoEnginePtr, int aIndex)
|
||||
: mVideoEngine(aVideoEnginePtr)
|
||||
, mCaptureIndex(aIndex)
|
||||
, mCapabilityChosen(false)
|
||||
, mWidth(aWidth)
|
||||
, mHeight(aHeight)
|
||||
, mWidth(0)
|
||||
, mHeight(0)
|
||||
, mFps(-1)
|
||||
, mMinFps(-1)
|
||||
, mMonitor("WebRTCCamera.Monitor")
|
||||
, mFps(aFps)
|
||||
, mMinFps(aMinFps)
|
||||
, mInitDone(false)
|
||||
, mInSnapshotMode(false)
|
||||
, mSnapshotPath(NULL) {
|
||||
@ -88,8 +79,7 @@ public:
|
||||
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
virtual const MediaEngineVideoOptions *GetOptions();
|
||||
virtual nsresult Allocate();
|
||||
virtual nsresult Allocate(const MediaEnginePrefs &aPrefs);
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop(SourceMediaStream*, TrackID);
|
||||
@ -141,8 +131,9 @@ private:
|
||||
webrtc::CaptureCapability mCapability; // Doesn't work on OS X.
|
||||
|
||||
int mCaptureIndex;
|
||||
bool mCapabilityChosen;
|
||||
int mWidth, mHeight;
|
||||
int mFps; // Track rate (30 fps by default)
|
||||
int mMinFps; // Min rate we want to accept
|
||||
|
||||
// mMonitor protects mImage access/changes, and transitions of mState
|
||||
// from kStarted to kStopped (which are combined with EndTrack() and
|
||||
@ -151,8 +142,6 @@ private:
|
||||
mozilla::ReentrantMonitor mMonitor; // Monitor for processing WebRTC frames.
|
||||
nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
|
||||
|
||||
int mFps; // Track rate (30 fps by default)
|
||||
int mMinFps; // Min rate we want to accept
|
||||
bool mInitDone;
|
||||
bool mInSnapshotMode;
|
||||
nsString* mSnapshotPath;
|
||||
@ -167,8 +156,7 @@ private:
|
||||
char mDeviceName[KMaxDeviceNameLength];
|
||||
char mUniqueId[KMaxUniqueIdLength];
|
||||
|
||||
void ChooseCapability(uint32_t aWidth, uint32_t aHeight, uint32_t aMinFPS);
|
||||
MediaEngineVideoOptions mOpts;
|
||||
void ChooseCapability(const MediaEnginePrefs &aPrefs);
|
||||
};
|
||||
|
||||
class MediaEngineWebRTCAudioSource : public MediaEngineAudioSource,
|
||||
@ -198,7 +186,7 @@ public:
|
||||
virtual void GetName(nsAString&);
|
||||
virtual void GetUUID(nsAString&);
|
||||
|
||||
virtual nsresult Allocate();
|
||||
virtual nsresult Allocate(const MediaEnginePrefs &aPrefs);
|
||||
virtual nsresult Deallocate();
|
||||
virtual nsresult Start(SourceMediaStream*, TrackID);
|
||||
virtual nsresult Stop(SourceMediaStream*, TrackID);
|
||||
@ -288,9 +276,6 @@ private:
|
||||
bool mVideoEngineInit;
|
||||
bool mAudioEngineInit;
|
||||
|
||||
// the last set of selection vars for video sources
|
||||
int mHeight, mWidth, mFPS, mMinFPS;
|
||||
|
||||
// Store devices we've already seen in a hashtable for quick return.
|
||||
// Maps UUID to MediaEngineSource (one set for audio, one for video).
|
||||
nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCVideoSource > mVideoSources;
|
||||
|
@ -101,7 +101,7 @@ MediaEngineWebRTCAudioSource::Config(bool aEchoOn, uint32_t aEcho,
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineWebRTCAudioSource::Allocate()
|
||||
MediaEngineWebRTCAudioSource::Allocate(const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
if (mState == kReleased && mInitDone) {
|
||||
webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
|
||||
|
@ -55,6 +55,11 @@ MediaEngineWebRTCVideoSource::DeliverFrame(
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mWidth*mHeight*3/2 == size);
|
||||
if (mWidth*mHeight*3/2 != size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create a video frame and append it to the track.
|
||||
ImageFormat format = PLANAR_YCBCR;
|
||||
|
||||
@ -119,11 +124,24 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
TrackTicks delta = target - aLastEndTime;
|
||||
LOGFRAME(("NotifyPull, desired = %ld, target = %ld, delta = %ld %s", (int64_t) aDesiredTime,
|
||||
(int64_t) target, (int64_t) delta, image ? "" : "<null>"));
|
||||
|
||||
// Bug 846188 We may want to limit incoming frames to the requested frame rate
|
||||
// mFps - if you want 30FPS, and the camera gives you 60FPS, this could
|
||||
// cause issues.
|
||||
// We may want to signal if the actual frame rate is below mMinFPS -
|
||||
// cameras often don't return the requested frame rate especially in low
|
||||
// light; we should consider surfacing this so that we can switch to a
|
||||
// lower resolution (which may up the frame rate)
|
||||
|
||||
// Don't append if we've already provided a frame that supposedly goes past the current aDesiredTime
|
||||
// Doing so means a negative delta and thus messes up handling of the graph
|
||||
if (delta > 0) {
|
||||
// NULL images are allowed
|
||||
segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight));
|
||||
if (image) {
|
||||
segment.AppendFrame(image.forget(), delta, gfxIntSize(mWidth, mHeight));
|
||||
} else {
|
||||
segment.AppendFrame(nullptr, delta, gfxIntSize(0,0));
|
||||
}
|
||||
// This can fail if either a) we haven't added the track yet, or b)
|
||||
// we've removed or finished the track.
|
||||
if (aSource->AppendToTrack(aID, &(segment))) {
|
||||
@ -133,21 +151,19 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
||||
}
|
||||
|
||||
void
|
||||
MediaEngineWebRTCVideoSource::ChooseCapability(uint32_t aWidth, uint32_t aHeight, uint32_t aMinFPS)
|
||||
MediaEngineWebRTCVideoSource::ChooseCapability(const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
int num = mViECapture->NumberOfCapabilities(mUniqueId, KMaxUniqueIdLength);
|
||||
|
||||
NS_WARN_IF_FALSE(!mCapabilityChosen,"Shouldn't select capability of a device twice");
|
||||
LOG(("ChooseCapability: prefs: %dx%d @%d-%dfps", aPrefs.mWidth, aPrefs.mHeight, aPrefs.mFPS, aPrefs.mMinFPS));
|
||||
|
||||
if (num <= 0) {
|
||||
// Set to default values
|
||||
mCapability.width = mOpts.mWidth = aWidth;
|
||||
mCapability.height = mOpts.mHeight = aHeight;
|
||||
mCapability.maxFPS = mOpts.mMaxFPS = DEFAULT_VIDEO_FPS;
|
||||
mOpts.codecType = kVideoCodecI420;
|
||||
mCapability.width = aPrefs.mWidth;
|
||||
mCapability.height = aPrefs.mHeight;
|
||||
mCapability.maxFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
|
||||
// Mac doesn't support capabilities.
|
||||
mCapabilityChosen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -160,31 +176,26 @@ MediaEngineWebRTCVideoSource::ChooseCapability(uint32_t aWidth, uint32_t aHeight
|
||||
mViECapture->GetCaptureCapability(mUniqueId, KMaxUniqueIdLength, i, cap);
|
||||
if (higher) {
|
||||
if (i == 0 ||
|
||||
(mOpts.mWidth > cap.width && mOpts.mHeight > cap.height)) {
|
||||
mOpts.mWidth = cap.width;
|
||||
mOpts.mHeight = cap.height;
|
||||
mOpts.mMaxFPS = cap.maxFPS;
|
||||
(mCapability.width > cap.width && mCapability.height > cap.height)) {
|
||||
// closer than the current choice
|
||||
mCapability = cap;
|
||||
// FIXME: expose expected capture delay?
|
||||
}
|
||||
if (cap.width <= aWidth && cap.height <= aHeight) {
|
||||
if (cap.width <= (uint32_t) aPrefs.mWidth && cap.height <= (uint32_t) aPrefs.mHeight) {
|
||||
higher = false;
|
||||
}
|
||||
} else {
|
||||
if (cap.width > aWidth || cap.height > aHeight || cap.maxFPS < aMinFPS) {
|
||||
if (cap.width > (uint32_t) aPrefs.mWidth || cap.height > (uint32_t) aPrefs.mHeight ||
|
||||
cap.maxFPS < (uint32_t) aPrefs.mMinFPS) {
|
||||
continue;
|
||||
}
|
||||
if (mOpts.mWidth < cap.width && mOpts.mHeight < cap.height) {
|
||||
mOpts.mWidth = cap.width;
|
||||
mOpts.mHeight = cap.height;
|
||||
mOpts.mMaxFPS = cap.maxFPS;
|
||||
if (mCapability.width < cap.width && mCapability.height < cap.height) {
|
||||
mCapability = cap;
|
||||
// FIXME: expose expected capture delay?
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(("chose cap %dx%d @%dfps", mOpts.mWidth, mOpts.mHeight, mOpts.mMaxFPS));
|
||||
mCapabilityChosen = true;
|
||||
LOG(("chose cap %dx%d @%dfps", mCapability.width, mCapability.height, mCapability.maxFPS));
|
||||
}
|
||||
|
||||
void
|
||||
@ -202,15 +213,15 @@ MediaEngineWebRTCVideoSource::GetUUID(nsAString& aUUID)
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineWebRTCVideoSource::Allocate()
|
||||
MediaEngineWebRTCVideoSource::Allocate(const MediaEnginePrefs &aPrefs)
|
||||
{
|
||||
LOG((__FUNCTION__));
|
||||
if (!mCapabilityChosen) {
|
||||
// XXX these should come from constraints
|
||||
ChooseCapability(mWidth, mHeight, mMinFps);
|
||||
}
|
||||
|
||||
if (mState == kReleased && mInitDone) {
|
||||
// Note: if shared, we don't allow a later opener to affect the resolution.
|
||||
// (This may change depending on spec changes for Constraints/settings)
|
||||
|
||||
ChooseCapability(aPrefs);
|
||||
|
||||
if (mViECapture->AllocateCaptureDevice(mUniqueId, KMaxUniqueIdLength, mCaptureIndex)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -262,15 +273,6 @@ MediaEngineWebRTCVideoSource::Deallocate()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const MediaEngineVideoOptions*
|
||||
MediaEngineWebRTCVideoSource::GetOptions()
|
||||
{
|
||||
if (!mCapabilityChosen) {
|
||||
ChooseCapability(mWidth, mHeight, mMinFps);
|
||||
}
|
||||
return &mOpts;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
|
||||
{
|
||||
@ -445,7 +447,9 @@ MediaEngineWebRTCVideoSource::Init()
|
||||
mDeviceName[0] = '\0'; // paranoia
|
||||
mUniqueId[0] = '\0';
|
||||
|
||||
(void) mFps; // fix compile warning for this being unused. (remove once used)
|
||||
// fix compile warning for these being unused. (remove once used)
|
||||
(void) mFps;
|
||||
(void) mMinFps;
|
||||
|
||||
LOG((__FUNCTION__));
|
||||
if (mVideoEngine == NULL) {
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIPopupWindowManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
// For PR_snprintf
|
||||
@ -454,6 +452,7 @@ public:
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
MediaEnginePrefs &aPrefs,
|
||||
MediaDevice* aAudioDevice, MediaDevice* aVideoDevice)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
@ -462,22 +461,24 @@ public:
|
||||
, mError(aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
, mDeviceChosen(true)
|
||||
, mBackendChosen(false)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
if (mAudio) {
|
||||
mAudioDevice = aAudioDevice;
|
||||
}
|
||||
if (mVideo) {
|
||||
mVideoDevice = aVideoDevice;
|
||||
}
|
||||
{
|
||||
if (mAudio) {
|
||||
mAudioDevice = aAudioDevice;
|
||||
}
|
||||
if (mVideo) {
|
||||
mVideoDevice = aVideoDevice;
|
||||
}
|
||||
}
|
||||
|
||||
GetUserMediaRunnable(bool aAudio, bool aVideo, bool aPicture,
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener)
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
MediaEnginePrefs &aPrefs)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
, mPicture(aPicture)
|
||||
@ -485,9 +486,11 @@ public:
|
||||
, mError(aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(false)
|
||||
, mManager(MediaManager::GetInstance()) {}
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{}
|
||||
|
||||
/**
|
||||
* The caller can also choose to provide their own backend instead of
|
||||
@ -497,6 +500,7 @@ public:
|
||||
already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
|
||||
uint64_t aWindowID, GetUserMediaCallbackMediaStreamListener *aListener,
|
||||
MediaEnginePrefs &aPrefs,
|
||||
MediaEngine* aBackend)
|
||||
: mAudio(aAudio)
|
||||
, mVideo(aVideo)
|
||||
@ -505,10 +509,12 @@ public:
|
||||
, mError(aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mListener(aListener)
|
||||
, mPrefs(aPrefs)
|
||||
, mDeviceChosen(false)
|
||||
, mBackendChosen(true)
|
||||
, mBackend(aBackend)
|
||||
, mManager(MediaManager::GetInstance()) {}
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{}
|
||||
|
||||
~GetUserMediaRunnable() {
|
||||
if (mBackendChosen) {
|
||||
@ -678,7 +684,7 @@ public:
|
||||
{
|
||||
nsresult rv;
|
||||
if (aAudioSource) {
|
||||
rv = aAudioSource->Allocate();
|
||||
rv = aAudioSource->Allocate(mPrefs);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Failed to allocate audiosource %d",rv));
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(
|
||||
@ -688,7 +694,7 @@ public:
|
||||
}
|
||||
}
|
||||
if (aVideoSource) {
|
||||
rv = aVideoSource->Allocate();
|
||||
rv = aVideoSource->Allocate(mPrefs);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Failed to allocate videosource %d\n",rv));
|
||||
if (aAudioSource) {
|
||||
@ -714,7 +720,7 @@ public:
|
||||
void
|
||||
ProcessGetUserMediaSnapshot(MediaEngineSource* aSource, int aDuration)
|
||||
{
|
||||
nsresult rv = aSource->Allocate();
|
||||
nsresult rv = aSource->Allocate(mPrefs);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(
|
||||
mSuccess, mError, NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"), mWindowID
|
||||
@ -746,6 +752,7 @@ private:
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
|
||||
nsRefPtr<MediaDevice> mAudioDevice;
|
||||
nsRefPtr<MediaDevice> mVideoDevice;
|
||||
MediaEnginePrefs mPrefs;
|
||||
|
||||
bool mDeviceChosen;
|
||||
bool mBackendChosen;
|
||||
@ -769,8 +776,7 @@ public:
|
||||
: mSuccess(aSuccess)
|
||||
, mError(aError)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{}
|
||||
~GetUserMediaDevicesRunnable() {}
|
||||
{}
|
||||
|
||||
NS_IMETHOD
|
||||
Run()
|
||||
@ -817,10 +823,65 @@ private:
|
||||
nsRefPtr<MediaManager> mManager;
|
||||
};
|
||||
|
||||
MediaManager::MediaManager()
|
||||
: mMediaThread(nullptr)
|
||||
, mMutex("mozilla::MediaManager")
|
||||
, mBackend(nullptr) {
|
||||
mPrefs.mWidth = MediaEngine::DEFAULT_VIDEO_WIDTH;
|
||||
mPrefs.mHeight = MediaEngine::DEFAULT_VIDEO_HEIGHT;
|
||||
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
|
||||
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
if (branch) {
|
||||
GetPrefs(branch, nullptr);
|
||||
}
|
||||
}
|
||||
LOG(("%s: default prefs: %dx%d @%dfps (min %d)", __FUNCTION__,
|
||||
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS));
|
||||
|
||||
mActiveWindows.Init();
|
||||
mActiveCallbacks.Init();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(MediaManager, nsIMediaManagerService, nsIObserver)
|
||||
|
||||
/* static */ StaticRefPtr<MediaManager> MediaManager::sSingleton;
|
||||
|
||||
// NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
|
||||
// thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
|
||||
// from MediaManager thread.
|
||||
/* static */ MediaManager*
|
||||
MediaManager::Get() {
|
||||
if (!sSingleton) {
|
||||
sSingleton = new MediaManager();
|
||||
|
||||
NS_NewThread(getter_AddRefs(sSingleton->mMediaThread));
|
||||
LOG(("New Media thread for gum"));
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread");
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
|
||||
}
|
||||
// else MediaManager won't work properly and will leak (see bug 837874)
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->AddObserver("media.navigator.video.default_width", sSingleton, false);
|
||||
prefs->AddObserver("media.navigator.video.default_height", sSingleton, false);
|
||||
prefs->AddObserver("media.navigator.video.default_fps", sSingleton, false);
|
||||
prefs->AddObserver("media.navigator.video.default_minfps", sSingleton, false);
|
||||
}
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<MediaManager>
|
||||
MediaManager::GetInstance()
|
||||
{
|
||||
@ -966,23 +1027,24 @@ MediaManager::GetUserMedia(bool aPrivileged, nsPIDOMWindow* aWindow,
|
||||
*
|
||||
* If a fake stream was requested, we force the use of the default backend.
|
||||
*/
|
||||
// XXX take options from constraints instead of prefs
|
||||
if (fake) {
|
||||
// Fake stream from default backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, onSuccess.forget(), onError.forget(), windowID, listener,
|
||||
audio, video, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs,
|
||||
new MediaEngineDefault()
|
||||
);
|
||||
} else if (audiodevice || videodevice) {
|
||||
// Stream from provided device.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID, listener,
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs,
|
||||
static_cast<MediaDevice*>(audiodevice.get()),
|
||||
static_cast<MediaDevice*>(videodevice.get())
|
||||
);
|
||||
} else {
|
||||
// Stream from default device from WebRTC backend.
|
||||
gUMRunnable = new GetUserMediaRunnable(
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID, listener
|
||||
audio, video, picture, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs
|
||||
);
|
||||
}
|
||||
|
||||
@ -1156,6 +1218,27 @@ MediaManager::RemoveFromWindowList(uint64_t aWindowID,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaManager::GetPref(nsIPrefBranch *aBranch, const char *aPref,
|
||||
const char *aData, int32_t *aVal)
|
||||
{
|
||||
int32_t temp;
|
||||
if (aData == nullptr || strcmp(aPref,aData) == 0) {
|
||||
if (NS_SUCCEEDED(aBranch->GetIntPref(aPref, &temp))) {
|
||||
*aVal = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaManager::GetPrefs(nsIPrefBranch *aBranch, const char *aData)
|
||||
{
|
||||
GetPref(aBranch, "media.navigator.video.default_width", aData, &mPrefs.mWidth);
|
||||
GetPref(aBranch, "media.navigator.video.default_height", aData, &mPrefs.mHeight);
|
||||
GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
|
||||
GetPref(aBranch, "media.navigator.video.default_minfps", aData, &mPrefs.mMinFPS);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
@ -1163,12 +1246,27 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
NS_ASSERTION(NS_IsMainThread(), "Observer invoked off the main thread");
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
|
||||
if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
||||
nsCOMPtr<nsIPrefBranch> branch( do_QueryInterface(aSubject) );
|
||||
if (branch) {
|
||||
GetPrefs(branch,NS_ConvertUTF16toUTF8(aData).get());
|
||||
LOG(("%s: %dx%d @%dfps (min %d)", __FUNCTION__,
|
||||
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS));
|
||||
}
|
||||
} else if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||
obs->RemoveObserver(this, "xpcom-shutdown");
|
||||
obs->RemoveObserver(this, "getUserMedia:response:allow");
|
||||
obs->RemoveObserver(this, "getUserMedia:response:deny");
|
||||
obs->RemoveObserver(this, "getUserMedia:revoke");
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
prefs->RemoveObserver("media.navigator.video.default_width", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_height", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_fps", this);
|
||||
prefs->RemoveObserver("media.navigator.video.default_minfps", this);
|
||||
}
|
||||
|
||||
// Close off any remaining active windows.
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
@ -1178,9 +1276,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "getUserMedia:response:allow")) {
|
||||
} else if (!strcmp(aTopic, "getUserMedia:response:allow")) {
|
||||
nsString key(aData);
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) {
|
||||
@ -1225,9 +1322,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
// Reuse the same thread to save memory.
|
||||
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "getUserMedia:response:deny")) {
|
||||
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
|
||||
nsString errorMessage(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
|
||||
if (aSubject) {
|
||||
@ -1249,9 +1345,8 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
static_cast<GetUserMediaRunnable*>(runnable.get());
|
||||
gUMRunnable->Denied(errorMessage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, "getUserMedia:revoke")) {
|
||||
} else if (!strcmp(aTopic, "getUserMedia:revoke")) {
|
||||
nsresult rv;
|
||||
uint64_t windowID = nsString(aData).ToInteger64(&rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsObserverService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMNavigatorUserMedia.h"
|
||||
@ -379,25 +381,8 @@ public:
|
||||
// NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
|
||||
// thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
|
||||
// from MediaManager thread.
|
||||
static MediaManager* Get() {
|
||||
if (!sSingleton) {
|
||||
sSingleton = new MediaManager();
|
||||
static MediaManager* Get();
|
||||
|
||||
NS_NewThread(getter_AddRefs(sSingleton->mMediaThread));
|
||||
MM_LOG(("New Media thread for gum"));
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread");
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(sSingleton, "xpcom-shutdown", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:response:allow", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:response:deny", false);
|
||||
obs->AddObserver(sSingleton, "getUserMedia:revoke", false);
|
||||
}
|
||||
// else MediaManager won't work properly and will leak (see bug 837874)
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
static nsIThread* GetThread() {
|
||||
return Get()->mMediaThread;
|
||||
}
|
||||
@ -431,20 +416,20 @@ public:
|
||||
nsIDOMGetUserMediaErrorCallback* onError);
|
||||
void OnNavigation(uint64_t aWindowID);
|
||||
|
||||
MediaEnginePrefs mPrefs;
|
||||
|
||||
private:
|
||||
WindowTable *GetActiveWindows() {
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
|
||||
return &mActiveWindows;
|
||||
}
|
||||
|
||||
void GetPref(nsIPrefBranch *aBranch, const char *aPref,
|
||||
const char *aData, int32_t *aVal);
|
||||
void GetPrefs(nsIPrefBranch *aBranch, const char *aData);
|
||||
|
||||
// Make private because we want only one instance of this class
|
||||
MediaManager()
|
||||
: mMediaThread(nullptr)
|
||||
, mMutex("mozilla::MediaManager")
|
||||
, mBackend(nullptr) {
|
||||
mActiveWindows.Init();
|
||||
mActiveCallbacks.Init();
|
||||
}
|
||||
MediaManager();
|
||||
|
||||
~MediaManager() {
|
||||
delete mBackend;
|
||||
|
@ -180,6 +180,10 @@ pref("media.gstreamer.enabled", true);
|
||||
#endif
|
||||
#ifdef MOZ_WEBRTC
|
||||
pref("media.navigator.enabled", true);
|
||||
pref("media.navigator.video.default_width",640);
|
||||
pref("media.navigator.video.default_height",480);
|
||||
pref("media.navigator.video.default_fps",30);
|
||||
pref("media.navigator.video.default_minfps",10);
|
||||
pref("media.peerconnection.enabled", true);
|
||||
pref("media.navigator.permission.disabled", false);
|
||||
pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:23.21.150.121\"}]");
|
||||
|
Loading…
Reference in New Issue
Block a user