Bug 1193075 - add viewport constraints for independent scrolling in tab sharing. r=smaug, r=jesup

--HG--
extra : transplant_source : %F8%AE%16%B7D%EFN%CC%16%A7%0C%B9%07%3F%D4%7B%E5%3Co%97
This commit is contained in:
Jan-Ivar Bruaroey 2015-10-22 17:03:47 -04:00
parent ae6d7ff3ef
commit 8a441a9cf1
7 changed files with 113 additions and 63 deletions

View File

@ -1878,6 +1878,15 @@ MediaManager::GetUserMedia(nsPIDOMWindow* aWindow,
break;
case dom::MediaSourceEnum::Browser:
// If no window id is passed in then default to the caller's window.
// Functional defaults are helpful in tests, but also a natural outcome
// of the constraints API's limited semantics for requiring input.
if (!vc.mBrowserWindow.WasPassed()) {
nsPIDOMWindow *outer = aWindow->GetOuterWindow();
vc.mBrowserWindow.Construct(outer->WindowID());
}
// | Fall through
// V
case dom::MediaSourceEnum::Screen:
case dom::MediaSourceEnum::Application:
case dom::MediaSourceEnum::Window:

View File

@ -72,9 +72,9 @@ var tests = [
var mustSupport = [
'width', 'height', 'frameRate', 'facingMode', 'deviceId',
// Yet to add:
// 'aspectRatio', 'frameRate', 'volume', 'sampleRate', 'sampleSize',
// 'echoCancellation', 'latency', 'groupId'
// Yet to add:
// 'aspectRatio', 'frameRate', 'volume', 'sampleRate', 'sampleSize',
// 'echoCancellation', 'latency', 'groupId'
// http://fluffy.github.io/w3c-screen-share/#screen-based-video-constraints
// OBE by http://w3c.github.io/mediacapture-screen-share
@ -82,6 +82,7 @@ var mustSupport = [
// Experimental https://bugzilla.mozilla.org/show_bug.cgi?id=1131568#c3
'browserWindow', 'scrollWithPage',
'viewportOffsetX', 'viewportOffsetY', 'viewportWidth', 'viewportHeight'
];
/**

View File

@ -31,9 +31,17 @@ using namespace mozilla::gfx;
NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
MediaEngineTabVideoSource::MediaEngineTabVideoSource()
: mData(NULL), mDataSize(0), mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
{
}
: mBufWidthMax(0)
, mBufHeightMax(0)
, mWindowId(0)
, mScrollWithPage(false)
, mViewportOffsetX(0)
, mViewportOffsetY(0)
, mViewportWidth(0)
, mViewportHeight(0)
, mTimePerFrame(0)
, mDataSize(0)
, mMonitor("MediaEngineTabVideoSource") {}
nsresult
MediaEngineTabVideoSource::StartRunnable::Run()
@ -123,23 +131,39 @@ MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstrain
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId)
{
// windowId and scrollWithPage are not proper constraints, so just read them.
// They have no well-defined behavior in advanced, so ignore them there.
// windowId is not a proper constraint, so just read it.
// It has no well-defined behavior in advanced, so ignore it there.
mWindowId = aConstraints.mBrowserWindow.WasPassed() ?
aConstraints.mBrowserWindow.Value() : -1;
return Restart(aConstraints, aPrefs, aDeviceId);
}
nsresult
MediaEngineTabVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
const mozilla::MediaEnginePrefs& aPrefs,
const nsString& aDeviceId)
{
// scrollWithPage is not proper a constraint, so just read it.
// It has no well-defined behavior in advanced, so ignore it there.
mScrollWithPage = aConstraints.mScrollWithPage.WasPassed() ?
aConstraints.mScrollWithPage.Value() : true;
aConstraints.mScrollWithPage.Value() : false;
FlattenedConstraints c(aConstraints);
mBufWidthMax = c.mWidth.Clamp(c.mWidth.mIdeal.WasPassed() ?
c.mWidth.mIdeal.Value() : DEFAULT_TABSHARE_VIDEO_MAX_WIDTH);
mBufHeightMax = c.mHeight.Clamp(c.mHeight.mIdeal.WasPassed() ?
c.mHeight.mIdeal.Value() : DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT);
double frameRate = c.mFrameRate.Clamp(c.mFrameRate.mIdeal.WasPassed() ?
c.mFrameRate.mIdeal.Value() : DEFAULT_TABSHARE_VIDEO_FRAMERATE);
mBufWidthMax = c.mWidth.Get(DEFAULT_TABSHARE_VIDEO_MAX_WIDTH);
mBufHeightMax = c.mHeight.Get(DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT);
double frameRate = c.mFrameRate.Get(DEFAULT_TABSHARE_VIDEO_FRAMERATE);
mTimePerFrame = std::max(10, int(1000.0 / (frameRate > 0? frameRate : 1)));
if (!mScrollWithPage) {
mViewportOffsetX = c.mViewportOffsetX.Get(0);
mViewportOffsetY = c.mViewportOffsetY.Get(0);
mViewportWidth = c.mViewportWidth.Get(INT32_MAX);
mViewportHeight = c.mViewportHeight.Get(INT32_MAX);
}
return NS_OK;
}
@ -192,30 +216,32 @@ MediaEngineTabVideoSource::Draw() {
return;
}
int32_t innerWidth, innerHeight;
win->GetInnerWidth(&innerWidth);
win->GetInnerHeight(&innerHeight);
if (innerWidth == 0 || innerHeight == 0) {
if (mScrollWithPage || mViewportWidth == INT32_MAX) {
win->GetInnerWidth(&mViewportWidth);
}
if (mScrollWithPage || mViewportHeight == INT32_MAX) {
win->GetInnerHeight(&mViewportHeight);
}
if (!mViewportWidth || !mViewportHeight) {
return;
}
float pixelRatio;
win->GetDevicePixelRatio(&pixelRatio);
const int deviceInnerWidth = (int)(pixelRatio * innerWidth);
const int deviceInnerHeight = (int)(pixelRatio * innerHeight);
IntSize size;
{
float pixelRatio;
win->GetDevicePixelRatio(&pixelRatio);
const int32_t deviceWidth = (int32_t)(pixelRatio * mViewportWidth);
const int32_t deviceHeight = (int32_t)(pixelRatio * mViewportHeight);
if ((deviceInnerWidth <= mBufWidthMax) && (deviceInnerHeight <= mBufHeightMax)) {
size = IntSize(deviceInnerWidth, deviceInnerHeight);
} else {
if ((deviceWidth <= mBufWidthMax) && (deviceHeight <= mBufHeightMax)) {
size = IntSize(deviceWidth, deviceHeight);
} else {
const float scaleWidth = (float)mBufWidthMax / (float)deviceWidth;
const float scaleHeight = (float)mBufHeightMax / (float)deviceHeight;
const float scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight;
const float scaleWidth = (float)mBufWidthMax / (float)deviceInnerWidth;
const float scaleHeight = (float)mBufHeightMax / (float)deviceInnerHeight;
const float scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight;
size = IntSize((int)(scale * deviceInnerWidth), (int)(scale * deviceInnerHeight));
size = IntSize((int)(scale * deviceWidth), (int)(scale * deviceHeight));
}
}
gfxImageFormat format = gfxImageFormat::RGB24;
@ -225,28 +251,30 @@ MediaEngineTabVideoSource::Draw() {
mDataSize = stride * size.height;
mData = static_cast<unsigned char*>(malloc(mDataSize));
}
if (!mData) {
return;
}
RefPtr<nsPresContext> presContext;
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext) {
return;
nsCOMPtr<nsIPresShell> presShell;
{
RefPtr<nsPresContext> presContext;
nsIDocShell* docshell = win->GetDocShell();
if (docshell) {
docshell->GetPresContext(getter_AddRefs(presContext));
}
if (!presContext) {
return;
}
presShell = presContext->PresShell();
}
nscolor bgColor = NS_RGB(255, 255, 255);
nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
uint32_t renderDocFlags = 0;
if (!mScrollWithPage) {
renderDocFlags |= nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
}
nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)innerWidth),
nsPresContext::CSSPixelsToAppUnits((float)innerHeight));
uint32_t renderDocFlags = mScrollWithPage? 0 :
nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
RefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
RefPtr<DrawTarget> dt =
@ -259,8 +287,8 @@ MediaEngineTabVideoSource::Draw() {
return;
}
RefPtr<gfxContext> context = new gfxContext(dt);
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/innerWidth),
(((float) size.height)/innerHeight)));
context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/mViewportWidth),
(((float) size.height)/mViewportHeight)));
NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
@ -291,15 +319,6 @@ MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream*, mozilla::TrackID)
return NS_OK;
}
nsresult
MediaEngineTabVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
const mozilla::MediaEnginePrefs& aPrefs,
const nsString& aDeviceId)
{
// TODO
return NS_OK;
}
nsresult
MediaEngineTabVideoSource::Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t)
{

View File

@ -76,11 +76,15 @@ protected:
~MediaEngineTabVideoSource() {}
private:
int mBufWidthMax;
int mBufHeightMax;
int32_t mBufWidthMax;
int32_t mBufHeightMax;
int64_t mWindowId;
bool mScrollWithPage;
int mTimePerFrame;
int32_t mViewportOffsetX;
int32_t mViewportOffsetY;
int32_t mViewportWidth;
int32_t mViewportHeight;
int32_t mTimePerFrame;
ScopedFreePtr<unsigned char> mData;
size_t mDataSize;
nsCOMPtr<nsIDOMWindow> mWindow;

View File

@ -48,6 +48,9 @@ struct NormalizedConstraintSet
template<class ConstrainRange>
void SetFrom(const ConstrainRange& aOther);
ValueType Clamp(ValueType n) const { return std::max(mMin, std::min(n, mMax)); }
ValueType Get(ValueType defaultValue) const {
return Clamp(mIdeal.WasPassed() ? mIdeal.Value() : defaultValue);
}
bool Intersects(const Range& aOther) const {
return mMax >= aOther.mMin && mMin <= aOther.mMax;
}
@ -72,12 +75,17 @@ struct NormalizedConstraintSet
// Do you need to add your constraint here? Only if your code uses flattening
LongRange mWidth, mHeight;
DoubleRange mFrameRate;
LongRange mViewportOffsetX, mViewportOffsetY, mViewportWidth, mViewportHeight;
NormalizedConstraintSet(const dom::MediaTrackConstraintSet& aOther,
bool advanced)
: mWidth(aOther.mWidth, advanced)
, mHeight(aOther.mHeight, advanced)
, mFrameRate(aOther.mFrameRate, advanced) {}
, mFrameRate(aOther.mFrameRate, advanced)
, mViewportOffsetX(aOther.mViewportOffsetX, advanced)
, mViewportOffsetY(aOther.mViewportOffsetY, advanced)
, mViewportWidth(aOther.mViewportWidth, advanced)
, mViewportHeight(aOther.mViewportHeight, advanced) {}
};
struct FlattenedConstraints : public NormalizedConstraintSet

View File

@ -50,6 +50,10 @@ dictionary MediaTrackConstraintSet {
long long browserWindow;
boolean scrollWithPage;
ConstrainDOMString deviceId;
ConstrainLong viewportOffsetX;
ConstrainLong viewportOffsetY;
ConstrainLong viewportWidth;
ConstrainLong viewportHeight;
};
dictionary MediaTrackConstraints : MediaTrackConstraintSet {

View File

@ -29,7 +29,12 @@ dictionary MediaTrackSupportedConstraints {
boolean mediaSource = true;
// Experimental https://bugzilla.mozilla.org/show_bug.cgi?id=1131568#c3
// https://bugzilla.mozilla.org/show_bug.cgi?id=1193075
boolean browserWindow = true;
boolean scrollWithPage = true;
boolean viewportOffsetX = true;
boolean viewportOffsetY = true;
boolean viewportWidth = true;
boolean viewportHeight = true;
};