Merge m-i to m-c, a=merge

This commit is contained in:
Phil Ringnalda 2016-01-23 17:42:50 -08:00
commit a747e7e178
3700 changed files with 208202 additions and 18196 deletions

View File

@ -154,10 +154,12 @@ install-manifests: $(addprefix install-,$(install_manifests))
# If we're using the hybrid FasterMake/RecursiveMake backend, we want
# to recurse in the faster/ directory in parallel of install manifests.
# But dist/idl needs to happen before (cf. dependencies in
# config/faster/rules.mk)
ifneq (,$(filter FasterMake+RecursiveMake,$(BUILD_BACKENDS)))
install-manifests: faster
.PHONY: faster
faster:
faster: install-dist/idl
$(MAKE) -C faster FASTER_RECURSIVE_MAKE=1
endif
@ -181,7 +183,7 @@ endif
$(addprefix $(call py_action,process_install_manifest,$(if $(NO_REMOVE),--no-remove )$*) ,$(wildcard _build_manifests/install/$(subst /,_,$*)))
# Dummy wrapper rule to allow the faster backend to piggy back
install-dist_%: install-dist/% ;
$(addprefix install-,$(subst /,_,$(filter dist/%,$(install_manifests)))): install-dist_%: install-dist/% ;
# For compatibility
.PHONY: install-tests

View File

@ -677,7 +677,7 @@ getRoleCB(AtkObject *aAtkObj)
#include "RoleMap.h"
default:
MOZ_CRASH("Unknown role.");
};
}
#undef ROLE

View File

@ -251,7 +251,7 @@ ia2Accessible::role(long* aRole)
#include "RoleMap.h"
default:
MOZ_CRASH("Unknown role.");
};
}
#undef ROLE

View File

@ -452,7 +452,7 @@ AccessibleWrap::get_accRole(
#include "RoleMap.h"
default:
MOZ_CRASH("Unknown role.");
};
}
#undef ROLE

View File

@ -346,7 +346,7 @@ xpcAccessible::GetBounds(int32_t* aX, int32_t* aY,
*aX = rect.x;
*aY = rect.y;
*aWidth = rect.width;
*aHeight = rect.height;;
*aHeight = rect.height;
return NS_OK;
}

View File

@ -26,6 +26,8 @@ const appInfo = Cc["@mozilla.org/xre/app-info;1"].
const vc = Cc["@mozilla.org/xpcom/version-comparator;1"].
getService(Ci.nsIVersionComparator);
const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
const Startup = Cu.import("resource://gre/modules/sdk/system/Startup.js", {}).exports;
@ -48,18 +50,12 @@ function setResourceSubstitution(domain, uri) {
// Utility function that synchronously reads local resource from the given
// `uri` and returns content string.
function readURI(uri) {
let ioservice = Cc['@mozilla.org/network/io-service;1'].
getService(Ci.nsIIOService);
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(uri, 'UTF-8'),
loadUsingSystemPrincipal: true
});
let channel = ioservice.newChannel2(uri,
'UTF-8',
null,
null, // aLoadingNode
systemPrincipal,
null, // aTriggeringPrincipal
Ci.nsILoadInfo.SEC_NORMAL,
Ci.nsIContentPolicy.TYPE_OTHER);
let stream = channel.open();
let stream = channel.open2();
let cstream = Cc['@mozilla.org/intl/converter-input-stream;1'].
createInstance(Ci.nsIConverterInputStream);

View File

@ -81,7 +81,7 @@ function readURISync(uri, charset) {
let channel = NetUtil.newChannel({
uri: NetUtil.newURI(uri, charset),
loadUsingSystemPrincipal: true});
let stream = channel.open();
let stream = channel.open2();
let count = stream.available();
let data = NetUtil.readInputStreamToString(stream, count, { charset : charset });

View File

@ -15,8 +15,8 @@
"unpack": true
},
{
"size": 193213220,
"digest": "58b8ebd8de923117831dcbba71172a53e26c25bd16c2b2bb363a1254f2cd4e87f95e2c5f41e2dce10e18e43a17e0a395637c9ddcbf1e27673582792f9095c62e",
"size": 80164520,
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

View File

@ -1046,16 +1046,33 @@ var PageInfoListener = {
document = content.document;
}
let imageElement = message.objects.imageElement;
let pageInfoData = {metaViewRows: this.getMetaInfo(document),
docInfo: this.getDocumentInfo(document),
feeds: this.getFeedsInfo(document, strings),
windowInfo: this.getWindowInfo(window)};
windowInfo: this.getWindowInfo(window),
imageInfo: this.getImageInfo(imageElement)};
sendAsyncMessage("PageInfo:data", pageInfoData);
// Separate step so page info dialog isn't blank while waiting for this to finish.
this.getMediaInfo(document, window, strings);
},
getImageInfo: function(imageElement) {
let imageInfo = null;
if (imageElement) {
imageInfo = {
currentSrc: imageElement.currentSrc,
width: imageElement.width,
height: imageElement.height,
imageText: imageElement.title || imageElement.alt
};
}
return imageInfo;
},
getMetaInfo: function(document) {
let metaViewRows = [];

View File

@ -1069,6 +1069,9 @@ nsContextMenu.prototype = {
},
viewImageInfo: function() {
// Don't need to pass in ownerDocument.defaultView.top.document here;
// window.gBrowser.selectedBrowser.currentURI.spec does the job without
// using CPOWs
BrowserPageInfo(null, "mediaTab", this.target);
},

View File

@ -349,7 +349,7 @@ function onLoadPageInfo()
.notifyObservers(window, "page-info-dialog-loaded", null);
}
function loadPageInfo(frameOuterWindowID)
function loadPageInfo(frameOuterWindowID, imageElement)
{
let mm = window.opener.gBrowser.selectedBrowser.messageManager;
@ -361,7 +361,8 @@ function loadPageInfo(frameOuterWindowID)
// Look for pageInfoListener in content.js. Sends message to listener with arguments.
mm.sendAsyncMessage("PageInfo:getData", {strings: gStrings,
frameOuterWindowID: frameOuterWindowID});
frameOuterWindowID: frameOuterWindowID},
{ imageElement });
let pageInfoData;
@ -375,6 +376,8 @@ function loadPageInfo(frameOuterWindowID)
docInfo.documentURIObject.originCharset);
gDocInfo = docInfo;
gImageElement = pageInfoData.imageInfo;
var titleFormat = windowInfo.isTopWindow ? "pageInfo.page.title"
: "pageInfo.frame.title";
document.title = gBundle.getFormattedString(titleFormat, [docInfo.location]);
@ -478,19 +481,11 @@ function loadTab(args)
// If the "View Image Info" context menu item was used, the related image
// element is provided as an argument. This can't be a background image.
let imageElement = args && args.imageElement;
if (imageElement) {
gImageElement = {currentSrc: imageElement.currentSrc,
width: imageElement.width, height: imageElement.height,
imageText: imageElement.title || imageElement.alt};
}
else {
gImageElement = null;
}
let frameOuterWindowID = args && args.frameOuterWindowID;
/* Load the page info */
loadPageInfo(frameOuterWindowID);
loadPageInfo(frameOuterWindowID, imageElement);
var initialTab = (args && args.initialTab) || "generalTab";
var radioGroup = document.getElementById("viewGroup");

View File

@ -42,7 +42,7 @@
<description when-mixedcontent="active-loaded">&identity.activeLoaded;</description>
<description class="identity-popup-warning-yellow"
when-ciphers="weak">&identity.weakEncryption;</description>
<description when-loginforms="insecure">&identity.insecureLoginForms;</description>
<description when-loginforms="insecure">&identity.insecureLoginForms2;</description>
</vbox>
</vbox>
<button id="identity-popup-security-expander"

View File

@ -83,38 +83,21 @@ var gMainPane = {
setEventListener("e10sAutoStart", "command",
gMainPane.enableE10SChange);
let e10sCheckbox = document.getElementById("e10sAutoStart");
e10sCheckbox.checked = Services.appinfo.browserTabsRemoteAutostart;
// If e10s is blocked for some reason unrelated to prefs, we want to disable
// the checkbox.
if (!Services.appinfo.browserTabsRemoteAutostart) {
let e10sBlockedReason = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
let appinfo = Services.appinfo.QueryInterface(Ci.nsIObserver);
appinfo.observe(e10sBlockedReason, "getE10SBlocked", "")
if (e10sBlockedReason.data) {
if (e10sBlockedReason.data == "Safe mode") {
// If the only reason we're disabled is because of safe mode, then
// we want to allow the user to un-toggle the pref.
// We're relying on the nsAppRunner code only specifying "Safe mode"
// as the reason if the pref is otherwise enabled, and there are no
// other reasons to block e10s.
// Update the checkbox to reflect the pref state.
e10sCheckbox.checked = true;
} else {
e10sCheckbox.disabled = true;
let updateChannel = UpdateUtils.UpdateChannel;
// only add this label on developer channels
if (updateChannel == "default" ||
updateChannel == "nightly" ||
updateChannel == "aurora") {
e10sCheckbox.label += " (disabled: " + e10sBlockedReason.data + ")";
}
}
}
let e10sPref = document.getElementById("browser.tabs.remote.autostart");
let e10sTempPref = document.getElementById("e10sTempPref");
let e10sForceEnable = document.getElementById("e10sForceEnable");
let preffedOn = e10sPref.value || e10sTempPref.value || e10sForceEnable.value;
if (preffedOn) {
// The checkbox is checked if e10s is preffed on.
e10sCheckbox.checked = true;
// but if it's force disabled, then the checkbox is disabled.
e10sCheckbox.disabled = !Services.appinfo.browserTabsRemoteAutostart;
}
// If E10S is blocked because of safe mode, we want the checkbox to be
// enabled
#endif
#ifdef MOZ_DEV_EDITION

View File

@ -16,6 +16,9 @@
<preference id="e10sTempPref"
name="browser.tabs.remote.autostart.2"
type="bool"/>
<preference id="e10sForceEnable"
name="browser.tabs.remote.force-enable"
type="bool"/>
#endif
<!-- Startup -->

View File

@ -14,8 +14,8 @@
"unpack": true
},
{
"size": 193213220,
"digest": "58b8ebd8de923117831dcbba71172a53e26c25bd16c2b2bb363a1254f2cd4e87f95e2c5f41e2dce10e18e43a17e0a395637c9ddcbf1e27673582792f9095c62e",
"size": 80164520,
"digest": "26fd5301aaf6174a0e4f2ac3a8d19f39573f78a051aa78e876c065d60421b2b62207c11fbf1f20f92ba61acc4b9ce58d05409bf5af886943891b04c3d22f5e04",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

View File

@ -10,8 +10,8 @@
"unpack": true
},
{
"size": 215952362,
"digest": "5e9825dbe83b2a157879076da70fc5c989a1638e30d3b14a9901b166db09013c356a9dc4eaf6c16209a1832d9cb1c67ca869e9b9003cab8355a7f03b3dc08775",
"size": 93295855,
"digest": "2b8fd0c1ba337a7035090c420305a7892e663ce6781569b100b36fa21cc26146e67f44a34c7715f0004f48bbe46c232bbbf2928c9d0595243d2584530770b504",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

View File

@ -19,6 +19,7 @@ XPCSHELL_TESTS_MANIFESTS += ['chrome/test/xpcshell/xpcshell.ini']
BROWSER_CHROME_MANIFESTS += [
'chrome/test/mochitest/browser.ini',
]
MARIONETTE_LOOP_MANIFESTS += ['manifest.ini']
with Files('**'):
BUG_COMPONENT = ('Loop', 'Client')

View File

@ -748,7 +748,7 @@ you can use these alternative items. Otherwise, their values should be empty. -
<!ENTITY identity.connectionFile "This page is stored on your computer.">
<!ENTITY identity.connectionVerified1 "You are securely connected to this site, run by:">
<!ENTITY identity.connectionInternal "This is a secure &brandShortName; page.">
<!ENTITY identity.insecureLoginForms "Your login could be compromised.">
<!ENTITY identity.insecureLoginForms2 "Logins entered on this page could be compromised.">
<!-- Strings for connection state warnings. -->
<!ENTITY identity.activeBlocked "&brandShortName; has blocked parts of this page that are not secure.">

View File

@ -68,10 +68,6 @@ endif
# toolkit/content/buildconfig.html and browser/locales/jar.mn.
ACDEFINES += -DBUILD_FASTER
# Generic rule to fall back to the recursive make backend
$(TOPOBJDIR)/%: FORCE
$(MAKE) -C $(dir $@) $(notdir $@)
# Files under the faster/ sub-directory, however, are not meant to use the
# fallback
$(TOPOBJDIR)/faster/%: ;
@ -83,6 +79,13 @@ $(TOPOBJDIR)/dist/%:
mkdir -p $(@D)
cp $< $@
# Generic rule to fall back to the recursive make backend.
# This needs to stay after other $(TOPOBJDIR)/* rules because GNU Make
# <3.82 apply pattern rules in definition order, not stem length like
# modern GNU Make.
$(TOPOBJDIR)/%: FORCE
$(MAKE) -C $(dir $@) $(notdir $@)
# Install files using install manifests
#
# The list of base directories is given in INSTALL_MANIFESTS. The
@ -114,8 +117,12 @@ $(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
$(TOPOBJDIR)/toolkit/xre/platform.ini: $(TOPOBJDIR)/config/buildid
# The xpidl target in config/makefiles/xpidl requires the install manifest for
# dist/idl to have been processed.
# dist/idl to have been processed. When using the hybrid
# FasterMake/RecursiveMake backend, this dependency is handled in the top-level
# Makefile.
ifndef FASTER_RECURSIVE_MAKE
$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(TOPOBJDIR)/install-dist_idl
endif
# It also requires all the install manifests for dist/bin to have been processed
# because it adds interfaces.manifest references with buildlist.py.
$(TOPOBJDIR)/config/makefiles/xpidl/xpidl: $(addprefix install-,$(filter dist/bin%,$(INSTALL_MANIFESTS)))

View File

@ -44,6 +44,11 @@ static RedirEntry kRedirMap[] = {
"buildconfig", "chrome://global/content/buildconfig.html",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT
},
{
"checkerboard", "chrome://global/content/aboutCheckerboard.xhtml",
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
nsIAboutModule::ALLOW_SCRIPT
},
{ "config", "chrome://global/content/config.xul", 0 },
#ifdef MOZ_CRASHREPORTER
{ "crashes", "chrome://global/content/crashes.xhtml", 0 },

View File

@ -24,12 +24,9 @@ protected:
virtual ~nsAboutRedirector() {}
};
#define NS_ABOUT_REDIRECTOR_MODULE_CID \
{ /* f0acde16-1dd1-11b2-9e35-f5786fff5a66*/ \
0xf0acde16, \
0x1dd1, \
0x11b2, \
{0x9e, 0x35, 0xf5, 0x78, 0x6f, 0xff, 0x5a, 0x66} \
}
/* 56ebedd4-6ccf-48e8-bdae-adc77f044567 */
#define NS_ABOUT_REDIRECTOR_MODULE_CID \
{ 0x56ebedd4, 0x6ccf, 0x48e8, \
{ 0xbd, 0xae, 0xad, 0xc7, 0x7f, 0x04, 0x45, 0x67 } }
#endif // nsAboutRedirector_h__

View File

@ -163,6 +163,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "about", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "addons", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "checkerboard", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "config", &kNS_ABOUT_REDIRECTOR_MODULE_CID },
#ifdef MOZ_CRASHREPORTER
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "crashes", &kNS_ABOUT_REDIRECTOR_MODULE_CID },

View File

@ -5,43 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "js/TypeDecls.h"
#include "nsGlobalWindow.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
#include "nsString.h"
#include "xpcpublic.h"
#include "nsContentUtils.h"
namespace mozilla {
struct FeedWriterEnabled {
static bool IsEnabled(JSContext* cx, JSObject* aGlobal)
{
// Make sure the global is a window
nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
if (!win) {
return false;
}
// Make sure that the principal is about:feeds.
nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
NS_ENSURE_TRUE(principal, false);
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
if (!uri) {
return false;
}
// First check the scheme to avoid getting long specs in the common case.
bool isAbout = false;
uri->SchemeIs("about", &isAbout);
if (!isAbout) {
return false;
}
// Now check the spec itself
nsAutoCString spec;
uri->GetSpec(spec);
return spec.EqualsLiteral("about:feeds");
return nsContentUtils::IsSpecificAboutPage(aGlobal, "about:feeds");
}
};

View File

@ -239,10 +239,15 @@ dom::Element*
nsIContent::GetEditingHost()
{
// If this isn't editable, return nullptr.
NS_ENSURE_TRUE(IsEditableInternal(), nullptr);
if (!IsEditableInternal()) {
return nullptr;
}
nsIDocument* doc = GetComposedDoc();
NS_ENSURE_TRUE(doc, nullptr);
if (!doc) {
return nullptr;
}
// If this is in designMode, we should return <body>
if (doc->HasFlag(NODE_IS_EDITABLE) && !IsInShadowTree()) {
return doc->GetBodyElement();

View File

@ -40,6 +40,25 @@ using namespace mozilla;
#define kVisibilityChange "visibilitychange"
class VisibilityChangeListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
void RemoveListener();
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
private:
virtual ~VisibilityChangeListener() {}
nsWeakPtr mWindow;
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
};
NS_IMPL_ISUPPORTS(VisibilityChangeListener, nsIDOMEventListener)
VisibilityChangeListener::VisibilityChangeListener(nsPIDOMWindow* aWindow)
@ -756,6 +775,11 @@ RemotePermissionRequest::RemotePermissionRequest(
mListener->SetCallback(this);
}
RemotePermissionRequest::~RemotePermissionRequest()
{
MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when RemotePermissionRequest is destroyed.");
}
void
RemotePermissionRequest::DoCancel()
{

View File

@ -21,6 +21,7 @@
class nsPIDOMWindow;
class nsContentPermissionRequestProxy;
class VisibilityChangeListener;
// Forward declare IPC::Principal here which is defined in
// PermissionMessageUtils.h. Include this file will transitively includes
@ -32,25 +33,6 @@ namespace IPC {
class Principal;
} // namespace IPC
class VisibilityChangeListener final : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
explicit VisibilityChangeListener(nsPIDOMWindow* aWindow);
void RemoveListener();
void SetCallback(nsIContentPermissionRequestCallback* aCallback);
already_AddRefed<nsIContentPermissionRequestCallback> GetCallback();
private:
virtual ~VisibilityChangeListener() {}
nsWeakPtr mWindow;
nsCOMPtr<nsIContentPermissionRequestCallback> mCallback;
};
namespace mozilla {
namespace dom {
@ -216,10 +198,7 @@ public:
bool IPCOpen() const { return mIPCOpen && !mDestroyed; }
private:
virtual ~RemotePermissionRequest()
{
MOZ_ASSERT(!mIPCOpen, "Protocol must not be open when RemotePermissionRequest is destroyed.");
}
virtual ~RemotePermissionRequest();
void DoAllow(JS::HandleValue aChoices);
void DoCancel();

View File

@ -8894,3 +8894,37 @@ nsContentUtils::SerializeNodeToMarkup(nsINode* aRoot,
}
}
}
bool
nsContentUtils::IsSpecificAboutPage(JSObject* aGlobal, const char* aUri)
{
// aUri must start with about: or this isn't the right function to be using.
MOZ_ASSERT(strncmp(aUri, "about:", 6) == 0);
// Make sure the global is a window
nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
if (!win) {
return false;
}
// Make sure that the principal is about:feeds.
nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
NS_ENSURE_TRUE(principal, false);
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
if (!uri) {
return false;
}
// First check the scheme to avoid getting long specs in the common case.
bool isAbout = false;
uri->SchemeIs("about", &isAbout);
if (!isAbout) {
return false;
}
// Now check the spec itself
nsAutoCString spec;
uri->GetSpec(spec);
return spec.EqualsASCII(aUri);
}

View File

@ -2565,6 +2565,14 @@ public:
bool aDescendentsOnly,
nsAString& aOut);
/*
* Returns true iff the provided JSObject is a global, and its URI matches
* the provided about: URI.
* @param aGlobal the JSObject whose URI to check, if it is a global.
* @param aUri the URI to match, e.g. "about:feeds"
*/
static bool IsSpecificAboutPage(JSObject* aGlobal, const char* aUri);
private:
static bool InitializeEventTable();

View File

@ -1622,6 +1622,9 @@ nsGlobalWindow::FreeInnerObjects()
// other members that the window destroyed observers could
// re-create.
NotifyDOMWindowDestroyed(this);
if (auto* reporter = nsWindowMemoryReporter::Get()) {
reporter->ObserveDOMWindowDetached(this);
}
mInnerObjectsFreed = true;
@ -2932,8 +2935,9 @@ nsGlobalWindow::DetachFromDocShell()
inner->FreeInnerObjects();
}
// Make sure that this is called before we null out the document.
NotifyDOMWindowDestroyed(this);
if (auto* reporter = nsWindowMemoryReporter::Get()) {
reporter->ObserveDOMWindowDetached(this);
}
NotifyWindowIDDestroyed("outer-window-destroyed");
@ -11039,7 +11043,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
fireMozStorageChanged = mLocalStorage == changingStorage;
if (fireMozStorageChanged) {
eventType.AssignLiteral("MozLocalStorageChanged");
};
}
break;
}
default:

View File

@ -1437,7 +1437,7 @@ nsObjectLoadingContent::ObjectState() const
case eFallbackVulnerableNoUpdate:
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
}
};
}
NS_NOTREACHED("unknown type?");
return NS_EVENT_STATE_LOADING;
}
@ -2422,7 +2422,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
case eType_Null:
// Handled below, silence compiler warnings
break;
};
}
//
// Loaded, handle notifications and fallback

View File

@ -17,6 +17,7 @@
#include "js/TypeDecls.h"
#include "nsRefPtrHashtable.h"
// Only fired for inner windows.
#define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
#define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
#define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"

View File

@ -111,10 +111,6 @@ nsWindowMemoryReporter::Init()
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (os) {
// DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
// when a window's docshell is set to nullptr.
os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
/* weakRef = */ true);
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
/* weakRef = */ true);
os->AddObserver(sWindowReporter, "cycle-collector-begin",
@ -127,6 +123,12 @@ nsWindowMemoryReporter::Init()
RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
}
/* static */ nsWindowMemoryReporter*
nsWindowMemoryReporter::Get()
{
return sWindowReporter;
}
static already_AddRefed<nsIURI>
GetWindowURI(nsIDOMWindow *aWindow)
{
@ -614,9 +616,7 @@ NS_IMETHODIMP
nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
const char16_t *aData)
{
if (!strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC)) {
ObserveDOMWindowDetached(aSubject);
} else if (!strcmp(aTopic, "after-minimize-memory-usage")) {
if (!strcmp(aTopic, "after-minimize-memory-usage")) {
ObserveAfterMinimizeMemoryUsage();
} else if (!strcmp(aTopic, "cycle-collector-begin")) {
if (mCheckTimer) {
@ -638,9 +638,9 @@ nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
}
void
nsWindowMemoryReporter::ObserveDOMWindowDetached(nsISupports* aWindow)
nsWindowMemoryReporter::ObserveDOMWindowDetached(nsGlobalWindow* aWindow)
{
nsWeakPtr weakWindow = do_GetWeakReference(aWindow);
nsWeakPtr weakWindow = do_GetWeakReference(static_cast<nsIDOMEventTarget*>(aWindow));
if (!weakWindow) {
NS_WARNING("Couldn't take weak reference to a window?");
return;

View File

@ -158,6 +158,9 @@ public:
static void UnlinkGhostWindows();
#endif
static nsWindowMemoryReporter* Get();
void ObserveDOMWindowDetached(nsGlobalWindow* aWindow);
private:
~nsWindowMemoryReporter();
@ -199,7 +202,6 @@ private:
*/
uint32_t GetGhostTimeout();
void ObserveDOMWindowDetached(nsISupports* aWindow);
void ObserveAfterMinimizeMemoryUsage();
/**

View File

@ -80,10 +80,6 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::Activity',
},
'MozAbortablePromise': {
'nativeType': 'mozilla::dom::AbortablePromise',
},
'AbstractWorker': {
'concrete': False
},

View File

@ -5037,11 +5037,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional)
if descriptor.interface.identifier.name == "AbortablePromise":
raise TypeError("Need to figure out what argument conversion "
"should look like for AbortablePromise: %s" %
sourceDescription)
# This is an interface that we implement as a concrete class
# or an XPCOM interface.
@ -7149,8 +7144,7 @@ class CGPerSignatureCall(CGThing):
# Hack for making Promise.prototype.then work well over Xrays.
if (not static and
(descriptor.name == "Promise" or
descriptor.name == "MozAbortablePromise") and
descriptor.name == "Promise" and
idlNode.isMethod() and
idlNode.identifier.name == "then"):
cgThings.append(CGGeneric(dedent(
@ -7162,7 +7156,7 @@ class CGPerSignatureCall(CGThing):
needsUnwrap = False
argsPost = []
if isConstructor:
if descriptor.name == "Promise" or descriptor.name == "MozAbortablePromise":
if descriptor.name == "Promise":
# Hack for Promise for now: pass in our desired proto so the
# implementation can create the reflector with the right proto.
argsPost.append("desiredProto")

View File

@ -1256,7 +1256,7 @@ MatchByVaryHeader(mozIStorageConnection* aConn,
ErrorResult errorResult;
cachedHeaders->Append(name, value, errorResult);
if (errorResult.Failed()) { return errorResult.StealNSResult(); };
if (errorResult.Failed()) { return errorResult.StealNSResult(); }
}
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }

View File

@ -140,7 +140,7 @@ void MurmurHash3_x86_32 ( const void * key, int len,
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
}
//----------
// finalization
@ -233,7 +233,7 @@ void MurmurHash3_x86_128 ( const void * key, const int len,
case 2: k1 ^= tail[ 1] << 8;
case 1: k1 ^= tail[ 0] << 0;
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
};
}
//----------
// finalization
@ -318,7 +318,7 @@ void MurmurHash3_x64_128 ( const void * key, const int len,
case 2: k1 ^= uint64_t(tail[ 1]) << 8;
case 1: k1 ^= uint64_t(tail[ 0]) << 0;
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
};
}
//----------
// finalization

View File

@ -1324,8 +1324,7 @@ IsFormatAndTypeUnpackable(GLenum format, GLenum type, bool isWebGL2)
switch (format) {
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
if (!isWebGL2)
return false;
return isWebGL2;
case LOCAL_GL_ALPHA:
case LOCAL_GL_RED:
case LOCAL_GL_RED_INTEGER:

View File

@ -192,7 +192,7 @@ GetDirectoryListingTask::Work()
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
isLink || isSpecial) {
continue;
};
}
if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
NS_FAILED(currFile->IsDirectory(&isDir))) ||
!(isFile || isDir)) {

View File

@ -10299,7 +10299,7 @@ DatabaseConnection::Close()
AssertIsOnConnectionThread();
MOZ_ASSERT(mStorageConnection);
MOZ_ASSERT(!mDEBUGSavepointCount);
MOZ_ASSERT(!mInWriteTransaction);
MOZ_RELEASE_ASSERT(!mInWriteTransaction);
PROFILER_LABEL("IndexedDB",
"DatabaseConnection::Close",

View File

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIPushObserverNotification.idl',
'nsIPushNotifier.idl',
'nsIPushService.idl',
]

View File

@ -0,0 +1,41 @@
#include "nsISupports.idl"
interface nsIPrincipal;
/**
* Fires service worker events for push messages sent to content subscriptions,
* and XPCOM observer notifications for system subscriptions. This service
* can only be used from the parent process.
*/
[scriptable, uuid(b00dfdeb-14e5-425b-adc7-b531442e3216)]
interface nsIPushNotifier : nsISupports
{
void notifyPush(in ACString scope, in nsIPrincipal principal);
void notifyPushWithData(in ACString scope, in nsIPrincipal principal,
[optional] in uint32_t dataLen,
[array, size_is(dataLen)] in uint8_t data);
void notifySubscriptionChange(in ACString scope, in nsIPrincipal principal);
};
/**
* A push message sent to a system subscription, used as the subject of a
* `push-message` observer notification. System subscriptions are created by
* the system principal, and do not use worker events.
*
* This interface resembles the `PushMessageData` WebIDL interface.
*/
[scriptable, uuid(136dc8fd-8c56-4176-9170-eaa86b6ba99e)]
interface nsIPushMessage : nsISupports
{
/** Extracts the data as a UTF-8 text string. */
DOMString text();
/** Extracts the data as a JSON value. */
[implicit_jscontext] jsval json();
/** Extracts the raw binary data. */
void binary([optional] out uint32_t dataLen,
[array, retval, size_is(dataLen)] out uint8_t data);
};

View File

@ -1,40 +0,0 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* A push message received by an `nsIPushService`, used as the subject of a
* `push-notification` observer notification.
*/
[scriptable, uuid(56f57607-28b6-44b0-aa56-3d4d3c88be15)]
interface nsIPushObserverNotification : nsISupports
{
/* The URL that receives push messages from an application server. */
attribute string pushEndpoint;
/**
* The notification version sent by the application server. This is a
* monotonically increasing number.
*/
attribute long long version;
/**
* The notification payload. Delivery is not guaranteed; if the browser is
* offline when the application server sends the push message, the payload
* may be discarded.
*/
attribute string data;
/**
* How many times has a push event occured against this pushEndpoint
*/
attribute long long pushCount;
/**
* The last time a push occured against this this pushEndpoint
*/
attribute long long lastPush;
};

View File

@ -81,9 +81,8 @@ interface nsIPushService : nsISupports
* The |endpoint| property of the subscription record is a URL string
* that can be used to send push messages to subscribers.
*
* Each incoming message fires a `push-notification` observer
* notification, with an `nsIPushObserverNotification` as the subject and
* the |scope| as the data.
* Each incoming message fires a `push-message` observer notification, with
* an `nsIPushMessage` as the subject and the |scope| as the data.
*
* If the server drops a subscription, a `push-subscription-change` observer
* will be fired, with the subject set to `null` and the data set to |scope|.

View File

@ -163,6 +163,10 @@
#include "mozilla/dom/GamepadService.h"
#endif
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushNotifier.h"
#endif
#include "mozilla/dom/File.h"
#include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
#include "mozilla/dom/icc/IccChild.h"
@ -1804,7 +1808,7 @@ ContentChild::SendPMobileConnectionConstructor(PMobileConnectionChild* aActor,
static_cast<MobileConnectionChild*>(aActor)->AddRef();
return PContentChild::SendPMobileConnectionConstructor(aActor, aClientId);
#else
MOZ_CRASH("No support for mobileconnection on this platform!");;
MOZ_CRASH("No support for mobileconnection on this platform!");
#endif
}
@ -1815,7 +1819,7 @@ ContentChild::AllocPMobileConnectionChild(const uint32_t& aClientId)
MOZ_CRASH("No one should be allocating PMobileConnectionChild actors");
return nullptr;
#else
MOZ_CRASH("No support for mobileconnection on this platform!");;
MOZ_CRASH("No support for mobileconnection on this platform!");
#endif
}
@ -3217,5 +3221,62 @@ ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
return true;
}
bool
ContentChild::RecvPush(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal, Nothing());
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
bool
ContentChild::RecvPushWithData(const nsCString& aScope,
const IPC::Principal& aPrincipal,
InfallibleTArray<uint8_t>&& aData)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifyPushWorkers(aScope, aPrincipal,
Some(aData));
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
bool
ContentChild::RecvPushSubscriptionChange(const nsCString& aScope,
const IPC::Principal& aPrincipal)
{
#ifndef MOZ_SIMPLEPUSH
nsCOMPtr<nsIPushNotifier> pushNotifierIface =
do_GetService("@mozilla.org/push/Notifier;1");
if (NS_WARN_IF(!pushNotifierIface)) {
return true;
}
PushNotifier* pushNotifier =
static_cast<PushNotifier*>(pushNotifierIface.get());
nsresult rv = pushNotifier->NotifySubscriptionChangeWorkers(aScope,
aPrincipal);
Unused << NS_WARN_IF(NS_FAILED(rv));
#endif
return true;
}
} // namespace dom
} // namespace mozilla

View File

@ -526,6 +526,19 @@ public:
virtual bool RecvEndDragSession(const bool& aDoneDrag,
const bool& aUserCancelled) override;
virtual bool
RecvPush(const nsCString& aScope,
const IPC::Principal& aPrincipal) override;
virtual bool
RecvPushWithData(const nsCString& aScope,
const IPC::Principal& aPrincipal,
InfallibleTArray<uint8_t>&& aData) override;
virtual bool
RecvPushSubscriptionChange(const nsCString& aScope,
const IPC::Principal& aPrincipal) override;
#ifdef ANDROID
gfx::IntSize GetScreenSize() { return mScreenSize; }
#endif

View File

@ -728,6 +728,21 @@ child:
*/
async NotifyGMPsChanged();
/**
* Send a `push` event without data to a service worker in the child.
*/
Push(nsCString scope, Principal principal);
/**
* Send a `push` event with data to a service worker in the child.
*/
PushWithData(nsCString scope, Principal principal, uint8_t[] data);
/**
* Send a `pushsubscriptionchange` event to a service worker in the child.
*/
PushSubscriptionChange(nsCString scope, Principal principal);
parent:
/**
* Tell the content process some attributes of itself. This is

View File

@ -12,6 +12,7 @@ const {
} = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
/** This little class ensures that redirects maintain an https:// origin */
@ -44,17 +45,16 @@ function ResourceLoader(res, rej) {
ResourceLoader.load = function(uri, doc) {
return new Promise((resolve, reject) => {
let listener = new ResourceLoader(resolve, reject);
let ioService = Cc['@mozilla.org/network/io-service;1']
.getService(Ci.nsIIOService);
let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
// the '2' identifies this as a script load
let ioChannel = ioService.newChannelFromURI2(uri, doc, doc.nodePrincipal,
systemPrincipal, 0,
Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT);
let ioChannel = NetUtil.newChannel({
uri: uri,
loadingNode: doc,
securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_SCRIPT
});
ioChannel.loadGroup = doc.documentLoadGroup.QueryInterface(Ci.nsILoadGroup);
ioChannel.notificationCallbacks = new RedirectHttpsOnly();
ioChannel.asyncOpen(listener, null);
ioChannel.asyncOpen2(listener);
});
};

View File

@ -674,20 +674,7 @@ public:
VideoDevice *aVideoDevice) :
mListener(aListener),
mAudioDevice(aAudioDevice),
mVideoDevice(aVideoDevice),
mEchoOn(true),
mAgcOn(false),
mNoiseOn(true),
#ifdef MOZ_WEBRTC
mEcho(webrtc::kEcDefault),
mAgc(webrtc::kAgcDefault),
mNoise(webrtc::kNsDefault),
#else
mEcho(0),
mAgc(0),
mNoise(0),
#endif
mPlayoutDelay(20)
mVideoDevice(aVideoDevice)
{}
virtual ~nsDOMUserMediaStream()
@ -790,21 +777,6 @@ public:
return false;
}
void
AudioConfig(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAgc,
bool aNoiseOn, uint32_t aNoise,
int32_t aPlayoutDelay)
{
mEchoOn = aEchoOn;
mEcho = aEcho;
mAgcOn = aAgcOn;
mAgc = aAgc;
mNoiseOn = aNoiseOn;
mNoise = aNoise;
mPlayoutDelay = aPlayoutDelay;
}
void RemoveDirectListener(MediaStreamDirectListener *aListener) override
{
if (GetSourceStream()) {
@ -842,14 +814,6 @@ public:
RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
RefPtr<AudioDevice> mAudioDevice; // so we can turn on AEC
RefPtr<VideoDevice> mVideoDevice;
bool mEchoOn;
bool mAgcOn;
bool mNoiseOn;
bool mFullDuplex;
uint32_t mEcho;
uint32_t mAgc;
uint32_t mNoise;
uint32_t mPlayoutDelay;
};
@ -954,16 +918,6 @@ public:
NS_IMETHOD
Run()
{
#ifdef MOZ_WEBRTC
int32_t aec = (int32_t) webrtc::kEcUnchanged;
int32_t agc = (int32_t) webrtc::kAgcUnchanged;
int32_t noise = (int32_t) webrtc::kNsUnchanged;
#else
int32_t aec = 0, agc = 0, noise = 0;
#endif
bool aec_on = false, agc_on = false, noise_on = false;
int32_t playout_delay = 0;
MOZ_ASSERT(NS_IsMainThread());
nsPIDOMWindow *window = static_cast<nsPIDOMWindow*>
(nsGlobalWindow::GetInnerWindowWithId(mWindowID));
@ -976,25 +930,6 @@ public:
return NS_OK;
}
#ifdef MOZ_WEBRTC
// Right now these configs are only of use if webrtc is available
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->GetBoolPref("media.getusermedia.aec_enabled", &aec_on);
branch->GetIntPref("media.getusermedia.aec", &aec);
branch->GetBoolPref("media.getusermedia.agc_enabled", &agc_on);
branch->GetIntPref("media.getusermedia.agc", &agc);
branch->GetBoolPref("media.getusermedia.noise_enabled", &noise_on);
branch->GetIntPref("media.getusermedia.noise", &noise);
branch->GetIntPref("media.getusermedia.playout_delay", &playout_delay);
}
}
#endif
MediaStreamGraph::GraphDriverType graphDriverType =
mAudioDevice ? MediaStreamGraph::AUDIO_THREAD_DRIVER
: MediaStreamGraph::SYSTEM_THREAD_DRIVER;
@ -1073,11 +1008,6 @@ public:
TracksAvailableCallback* tracksAvailableCallback =
new TracksAvailableCallback(mManager, mOnSuccess, mWindowID, domStream);
mListener->AudioConfig(aec_on, (uint32_t) aec,
agc_on, (uint32_t) agc,
noise_on, (uint32_t) noise,
playout_delay);
// Dispatch to the media thread to ask it to start the sources,
// because that can take a while.
// Pass ownership of domStream to the MediaOperationTask
@ -1515,11 +1445,24 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
MediaManager::MediaManager()
: mMediaThread(nullptr)
, mBackend(nullptr) {
mPrefs.mFreq = 1000; // 1KHz test tone
mPrefs.mWidth = 0; // adaptive default
mPrefs.mHeight = 0; // adaptive default
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
mPrefs.mFreq = 1000; // 1KHz test tone
mPrefs.mWidth = 0; // adaptive default
mPrefs.mHeight = 0; // adaptive default
mPrefs.mFPS = MediaEngine::DEFAULT_VIDEO_FPS;
mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
mPrefs.mAecOn = false;
mPrefs.mAgcOn = false;
mPrefs.mNoiseOn = false;
#ifdef MOZ_WEBRTC
mPrefs.mAec = webrtc::kEcUnchanged;
mPrefs.mAgc = webrtc::kAgcUnchanged;
mPrefs.mNoise = webrtc::kNsUnchanged;
#else
mPrefs.mAec = 0;
mPrefs.mAgc = 0;
mPrefs.mNoise = 0;
#endif
mPrefs.mPlayoutDelay = 0;
mPrefs.mFullDuplex = false;
nsresult rv;
nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
@ -1529,9 +1472,12 @@ MediaManager::MediaManager()
GetPrefs(branch, nullptr);
}
}
LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones, %sfull-duplex", __FUNCTION__,
mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq,
mPrefs.mFullDuplex ? "" : "not "));
LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones, aec: %s,"
"agc: %s, noise: %s, aec level: %d, agc level: %d, noise level: %d,"
"playout delay: %d, %sfull_duplex", __FUNCTION__, mPrefs.mWidth, mPrefs.mHeight,
mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq, mPrefs.mAecOn ? "on" : "off",
mPrefs.mAgcOn ? "on": "off", mPrefs.mNoiseOn ? "on": "off", mPrefs.mAec,
mPrefs.mAgc, mPrefs.mNoise, mPrefs.mPlayoutDelay, mPrefs.mFullDuplex ? "" : "not "));
}
NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver)
@ -1595,6 +1541,15 @@ MediaManager::Get() {
prefs->AddObserver("media.navigator.video.default_minfps", sSingleton, false);
prefs->AddObserver("media.navigator.audio.fake_frequency", sSingleton, false);
prefs->AddObserver("media.navigator.audio.full_duplex", sSingleton, false);
#ifdef MOZ_WEBRTC
prefs->AddObserver("media.getusermedia.aec_enabled", sSingleton, false);
prefs->AddObserver("media.getusermedia.aec", sSingleton, false);
prefs->AddObserver("media.getusermedia.agc_enabled", sSingleton, false);
prefs->AddObserver("media.getusermedia.agc", sSingleton, false);
prefs->AddObserver("media.getusermedia.noise_enabled", sSingleton, false);
prefs->AddObserver("media.getusermedia.noise", sSingleton, false);
prefs->AddObserver("media.getusermedia.playout_delay", sSingleton, false);
#endif
}
// Prepare async shutdown
@ -2628,6 +2583,15 @@ MediaManager::GetPrefs(nsIPrefBranch *aBranch, const char *aData)
GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
GetPref(aBranch, "media.navigator.video.default_minfps", aData, &mPrefs.mMinFPS);
GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, &mPrefs.mFreq);
#ifdef MOZ_WEBRTC
GetPrefBool(aBranch, "media.getusermedia.aec_enabled", aData, &mPrefs.mAecOn);
GetPrefBool(aBranch, "media.getusermedia.agc_enabled", aData, &mPrefs.mAgcOn);
GetPrefBool(aBranch, "media.getusermedia.noise_enabled", aData, &mPrefs.mNoiseOn);
GetPref(aBranch, "media.getusermedia.aec", aData, &mPrefs.mAec);
GetPref(aBranch, "media.getusermedia.agc", aData, &mPrefs.mAgc);
GetPref(aBranch, "media.getusermedia.noise", aData, &mPrefs.mNoise);
GetPref(aBranch, "media.getusermedia.playout_delay", aData, &mPrefs.mPlayoutDelay);
#endif
GetPrefBool(aBranch, "media.navigator.audio.full_duplex", aData, &mPrefs.mFullDuplex);
}
@ -2655,6 +2619,15 @@ MediaManager::Shutdown()
prefs->RemoveObserver("media.navigator.video.default_fps", this);
prefs->RemoveObserver("media.navigator.video.default_minfps", this);
prefs->RemoveObserver("media.navigator.audio.fake_frequency", this);
#ifdef MOZ_WEBRTC
prefs->RemoveObserver("media.getusermedia.aec_enabled", this);
prefs->RemoveObserver("media.getusermedia.aec", this);
prefs->RemoveObserver("media.getusermedia.agc_enabled", this);
prefs->RemoveObserver("media.getusermedia.agc", this);
prefs->RemoveObserver("media.getusermedia.noise_enabled", this);
prefs->RemoveObserver("media.getusermedia.noise", this);
prefs->RemoveObserver("media.getusermedia.playout_delay", this);
#endif
prefs->RemoveObserver("media.navigator.audio.full_duplex", this);
}
@ -3127,23 +3100,6 @@ MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId)
video == nsIPermissionManager::ALLOW_ACTION;
}
void
GetUserMediaCallbackMediaStreamListener::AudioConfig(bool aEchoOn,
uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
bool aNoiseOn, uint32_t aNoise,
int32_t aPlayoutDelay)
{
if (mAudioDevice) {
#ifdef MOZ_WEBRTC
MediaManager::PostTask(FROM_HERE,
NewRunnableMethod(mAudioDevice->GetSource(), &MediaEngineSource::Config,
aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn,
aNoise, aPlayoutDelay));
#endif
}
}
void
GetUserMediaCallbackMediaStreamListener::Invalidate()
{

View File

@ -23,6 +23,7 @@
#include "AudioNodeStream.h"
#include "AudioNodeExternalInputStream.h"
#include "mozilla/dom/AudioContextBinding.h"
#include "mozilla/media/MediaUtils.h"
#include <algorithm>
#include "DOMMediaStream.h"
#include "GeckoProfiler.h"
@ -1405,17 +1406,20 @@ MediaStreamGraphImpl::ApplyStreamUpdate(StreamUpdate* aUpdate)
}
void
MediaStreamGraphImpl::ForceShutDown()
MediaStreamGraphImpl::ForceShutDown(ShutdownTicket* aShutdownTicket)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
{
MonitorAutoLock lock(mMonitor);
mForceShutDown = true;
mForceShutdownTicket = aShutdownTicket;
EnsureNextIterationLocked();
}
}
/* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker;
namespace {
class MediaStreamGraphShutDownRunnable : public nsRunnable {
@ -1444,6 +1448,13 @@ public:
mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since
// we'll start tearing down the graph after this
// We may be one of several graphs. Drop ticket to eventually unblock shutdown.
mGraph->mForceShutdownTicket = nullptr;
// We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
// stage, since completion of that stage requires all streams to be freed,
// which requires shutdown to proceed.
// mGraph's thread is not running so it's OK to do whatever here
if (mGraph->IsEmpty()) {
// mGraph is no longer needed, so delete it.
@ -1510,14 +1521,6 @@ public:
}
};
class MediaStreamGraphShutdownObserver final : public nsIObserver
{
~MediaStreamGraphShutdownObserver() {}
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
};
} // namespace
void
@ -2800,26 +2803,6 @@ MediaStreamGraphImpl::Destroy()
mSelfRef = nullptr;
}
NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver)
static bool gShutdownObserverRegistered = false;
NS_IMETHODIMP
MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
const char *aTopic,
const char16_t *aData)
{
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
MediaStreamGraphImpl* graph = iter.UserData();
graph->ForceShutDown();
}
nsContentUtils::UnregisterShutdownObserver(this);
gShutdownObserverRegistered = false;
}
return NS_OK;
}
MediaStreamGraph*
MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequested,
dom::AudioChannel aChannel)
@ -2830,9 +2813,38 @@ MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequ
MediaStreamGraphImpl* graph = nullptr;
if (!gGraphs.Get(channel, &graph)) {
if (!gShutdownObserverRegistered) {
gShutdownObserverRegistered = true;
nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
if (!gMediaStreamGraphShutdownBlocker) {
class Blocker : public media::ShutdownBlocker
{
public:
Blocker()
: media::ShutdownBlocker(NS_LITERAL_STRING(
"MediaStreamGraph shutdown: blocking on msg thread")) {}
NS_IMETHOD
BlockShutdown(nsIAsyncShutdownClient* aProfileBeforeChange) override
{
// Distribute the global async shutdown blocker in a ticket. If there
// are zero graphs then shutdown is unblocked when we go out of scope.
RefPtr<MediaStreamGraphImpl::ShutdownTicket> ticket =
new MediaStreamGraphImpl::ShutdownTicket(gMediaStreamGraphShutdownBlocker.get());
gMediaStreamGraphShutdownBlocker = nullptr;
for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
iter.UserData()->ForceShutDown(ticket);
}
return NS_OK;
}
};
gMediaStreamGraphShutdownBlocker = new Blocker();
nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
nsresult rv = barrier->
AddBlocker(gMediaStreamGraphShutdownBlocker,
NS_LITERAL_STRING(__FILE__), __LINE__,
NS_LITERAL_STRING("MediaStreamGraph shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
}
CubebUtils::InitPreferredSampleRate();
@ -2880,7 +2892,7 @@ MediaStreamGraph::DestroyNonRealtimeInstance(MediaStreamGraph* aGraph)
// Start the graph, but don't produce anything
graph->StartNonRealtimeProcessing(0);
}
graph->ForceShutDown();
graph->ForceShutDown(nullptr);
}
NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter)

View File

@ -13,6 +13,7 @@
#include "nsIMemoryReporter.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
#include "nsIAsyncShutdown.h"
#include "Latency.h"
#include "mozilla/WeakPtr.h"
#include "GraphDriver.h"
@ -139,13 +140,48 @@ public:
* during RunInStableState; the messages will run on the graph thread.
*/
void AppendMessage(ControlMessage* aMessage);
// Shutdown helpers.
static already_AddRefed<nsIAsyncShutdownClient>
GetShutdownBarrier()
{
nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
MOZ_RELEASE_ASSERT(svc);
nsCOMPtr<nsIAsyncShutdownClient> barrier;
nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
if (!barrier) {
// We are probably in a content process.
rv = svc->GetContentChildShutdown(getter_AddRefs(barrier));
}
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
MOZ_RELEASE_ASSERT(barrier);
return barrier.forget();
}
class ShutdownTicket final
{
public:
explicit ShutdownTicket(nsIAsyncShutdownBlocker* aBlocker) : mBlocker(aBlocker) {}
NS_INLINE_DECL_REFCOUNTING(ShutdownTicket)
private:
~ShutdownTicket()
{
nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
barrier->RemoveBlocker(mBlocker);
}
nsCOMPtr<nsIAsyncShutdownBlocker> mBlocker;
};
/**
* Make this MediaStreamGraph enter forced-shutdown state. This state
* will be noticed by the media graph thread, which will shut down all streams
* and other state controlled by the media graph thread.
* This is called during application shutdown.
*/
void ForceShutDown();
void ForceShutDown(ShutdownTicket* aShutdownTicket);
/**
* Shutdown() this MediaStreamGraph's threads and return when they've shut down.
*/
@ -692,6 +728,12 @@ public:
* True when we need to do a forced shutdown during application shutdown.
*/
bool mForceShutDown;
/**
* Drop this reference during shutdown to unblock shutdown.
**/
RefPtr<ShutdownTicket> mForceShutdownTicket;
/**
* True when we have posted an event to the main thread to run
* RunInStableState() and the event hasn't run yet.

View File

@ -1108,6 +1108,10 @@ RTCPeerConnection.prototype = {
return this._receivers;
},
mozSelectSsrc: function(receiver, ssrcIndex) {
this._impl.selectSsrc(receiver.track, ssrcIndex);
},
get localDescription() {
this._checkClosed();
let sdp = this._impl.localDescription;

View File

@ -1448,7 +1448,7 @@ bool SkeletonState::DecodeFisbone(ogg_packet* aPacket)
}
msgLength--;
msgProbe++;
};
}
if (!mMsgFieldStore.Contains(serialno)) {
mMsgFieldStore.Put(serialno, field.forget());

View File

@ -91,7 +91,7 @@ public:
int64_t GetMediaTimeUs() override;
// To update progress bar when the element is visible
void SetElementVisibility(bool aIsVisible) override;;
void SetElementVisibility(bool aIsVisible) override;
// Update ready state based on current play state. Not checking data
// availability since offloading is currently done only when whole compressed

View File

@ -58,7 +58,6 @@ bool PDMFactory::sAndroidMCDecoderPreferred = false;
bool PDMFactory::sGMPDecoderEnabled = false;
#ifdef MOZ_FFVPX
bool PDMFactory::sFFVPXDecoderEnabled = false;
using namespace ffvpx;
#endif
#ifdef MOZ_FFMPEG
bool PDMFactory::sFFmpegDecoderEnabled = false;
@ -124,10 +123,10 @@ PDMFactory::Init()
AppleDecoderModule::Init();
#endif
#ifdef MOZ_FFVPX
FFVPXRuntimeLinker::Link();
FFVPXRuntimeLinker::Init();
#endif
#ifdef MOZ_FFMPEG
FFmpegRuntimeLinker::Link();
FFmpegRuntimeLinker::Init();
#endif
GMPDecoderModule::Init();
}

View File

@ -148,6 +148,12 @@ OpusDataDecoder::DoDecode(MediaRawData* aSample)
return -1;
}
if (!mLastFrameTime || mLastFrameTime.ref() != aSample->mTime) {
// We are starting a new block.
mFrames = 0;
mLastFrameTime = Some(aSample->mTime);
}
// Maximum value is 63*2880, so there's no chance of overflow.
int32_t frames_number = opus_packet_get_nb_frames(aSample->Data(),
aSample->Size());
@ -253,8 +259,9 @@ OpusDataDecoder::DoDecode(MediaRawData* aSample)
NS_WARNING("OpusDataDecoder: Int overflow converting WebM audio duration");
return -1;
}
CheckedInt64 time = startTime - FramesToUsecs(mOpusParser->mPreSkip,
mOpusParser->mRate);
CheckedInt64 time =
startTime - FramesToUsecs(mOpusParser->mPreSkip, mOpusParser->mRate) +
FramesToUsecs(mFrames, mOpusParser->mRate);
if (!time.isValid()) {
NS_WARNING("OpusDataDecoder: Int overflow shifting tstamp by codec delay");
return -1;
@ -295,7 +302,7 @@ OpusDataDecoder::Flush()
opus_multistream_decoder_ctl(mOpusDecoder, OPUS_RESET_STATE);
mSkip = mOpusParser->mPreSkip;
mPaddingDiscarded = false;
mFrames = 0;
mLastFrameTime.reset();
}
return NS_OK;
}

View File

@ -9,6 +9,7 @@
#include "OpusParser.h"
#include "PlatformDecoderModule.h"
#include "mozilla/Maybe.h"
#include "nsAutoPtr.h"
namespace mozilla {
@ -53,6 +54,7 @@ private:
// will raise an error so we can indicate that the file is invalid.
bool mPaddingDiscarded;
int64_t mFrames;
Maybe<int64_t> mLastFrameTime;
};
} // namespace mozilla

View File

@ -6,7 +6,6 @@
#include "mozilla/TaskQueue.h"
#include "FFmpegRuntimeLinker.h"
#include "FFmpegAudioDecoder.h"
#include "TimeUnits.h"
@ -15,10 +14,10 @@
namespace mozilla
{
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(FFmpegLibWrapper* aLib,
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
const AudioInfo& aConfig)
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
{
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
// Use a new MediaByteBuffer as the object will be modified during initialization.
@ -44,11 +43,9 @@ FFmpegAudioDecoder<LIBAV_VER>::InitCodecContext()
// isn't implemented.
mCodecContext->thread_count = 1;
// FFmpeg takes this as a suggestion for what format to use for audio samples.
uint32_t major, minor, micro;
FFmpegRuntimeLinker::GetVersion(major, minor, micro);
// LibAV 0.8 produces rubbish float interleaved samples, request 16 bits audio.
mCodecContext->request_sample_fmt =
(major == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
(mLib->mVersion == 53) ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
}
static UniquePtr<AudioDataValue[]>
@ -101,7 +98,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
AVPacket packet;
AV_CALL(av_init_packet(&packet));
mLib->av_init_packet(&packet);
packet.data = const_cast<uint8_t*>(aSample->Data());
packet.size = aSample->Size();
@ -118,7 +115,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
while (packet.size > 0) {
int decoded;
int bytesConsumed =
AV_CALL(avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet));
mLib->avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
if (bytesConsumed < 0) {
NS_WARNING("FFmpeg audio decoder error.");

View File

@ -7,6 +7,7 @@
#ifndef __FFmpegAACDecoder_h__
#define __FFmpegAACDecoder_h__
#include "FFmpegLibWrapper.h"
#include "FFmpegDataDecoder.h"
namespace mozilla
@ -20,7 +21,7 @@ template <>
class FFmpegAudioDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
{
public:
FFmpegAudioDecoder(FlushableTaskQueue* aTaskQueue,
FFmpegAudioDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
const AudioInfo& aConfig);
virtual ~FFmpegAudioDecoder();

View File

@ -18,13 +18,14 @@
namespace mozilla
{
bool FFmpegDataDecoder<LIBAV_VER>::sFFmpegInitDone = false;
StaticMutex FFmpegDataDecoder<LIBAV_VER>::sMonitor;
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
AVCodecID aCodecID)
: mTaskQueue(aTaskQueue)
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FFmpegLibWrapper* aLib,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
AVCodecID aCodecID)
: mLib(aLib)
, mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mCodecContext(nullptr)
, mFrame(NULL)
@ -33,6 +34,7 @@ FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
, mMonitor("FFMpegaDataDecoder")
, mIsFlushing(false)
{
MOZ_ASSERT(aLib);
MOZ_COUNT_CTOR(FFmpegDataDecoder);
}
@ -46,7 +48,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
{
FFMPEG_LOG("Initialising FFmpeg decoder.");
AVCodec* codec = FindAVCodec(mCodecID);
AVCodec* codec = FindAVCodec(mLib, mCodecID);
if (!codec) {
NS_WARNING("Couldn't find ffmpeg decoder");
return NS_ERROR_FAILURE;
@ -54,7 +56,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
StaticMutexAutoLock mon(sMonitor);
if (!(mCodecContext = AV_CALL(avcodec_alloc_context3(codec)))) {
if (!(mCodecContext = mLib->avcodec_alloc_context3(codec))) {
NS_WARNING("Couldn't init ffmpeg context");
return NS_ERROR_FAILURE;
}
@ -77,10 +79,10 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
}
if (AV_CALL(avcodec_open2(mCodecContext, codec, nullptr)) < 0) {
if (mLib->avcodec_open2(mCodecContext, codec, nullptr) < 0) {
NS_WARNING("Couldn't initialise ffmpeg decoder");
AV_CALL(avcodec_close(mCodecContext));
AV_CALL(av_freep(&mCodecContext));
mLib->avcodec_close(mCodecContext);
mLib->av_freep(&mCodecContext);
return NS_ERROR_FAILURE;
}
@ -141,7 +143,7 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
{
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
if (mCodecContext) {
AV_CALL(avcodec_flush_buffers(mCodecContext));
mLib->avcodec_flush_buffers(mCodecContext);
}
MonitorAutoLock mon(mMonitor);
mIsFlushing = false;
@ -153,13 +155,13 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
{
StaticMutexAutoLock mon(sMonitor);
if (sFFmpegInitDone && mCodecContext) {
AV_CALL(avcodec_close(mCodecContext));
AV_CALL(av_freep(&mCodecContext));
if (mCodecContext) {
mLib->avcodec_close(mCodecContext);
mLib->av_freep(&mCodecContext);
#if LIBAVCODEC_VERSION_MAJOR >= 55
AV_CALL(av_frame_free(&mFrame));
mLib->av_frame_free(&mFrame);
#elif LIBAVCODEC_VERSION_MAJOR == 54
AV_CALL(avcodec_free_frame(&mFrame));
mLib->avcodec_free_frame(&mFrame);
#else
delete mFrame;
mFrame = nullptr;
@ -173,36 +175,29 @@ FFmpegDataDecoder<LIBAV_VER>::PrepareFrame()
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
#if LIBAVCODEC_VERSION_MAJOR >= 55
if (mFrame) {
AV_CALL(av_frame_unref(mFrame));
mLib->av_frame_unref(mFrame);
} else {
mFrame = AV_CALL(av_frame_alloc());
mFrame = mLib->av_frame_alloc();
}
#elif LIBAVCODEC_VERSION_MAJOR == 54
if (mFrame) {
AV_CALL(avcodec_get_frame_defaults(mFrame));
mLib->avcodec_get_frame_defaults(mFrame);
} else {
mFrame = AV_CALL(avcodec_alloc_frame());
mFrame = mLib->avcodec_alloc_frame();
}
#else
delete mFrame;
mFrame = new AVFrame;
AV_CALL(avcodec_get_frame_defaults(mFrame));
mLib->avcodec_get_frame_defaults(mFrame);
#endif
return mFrame;
}
/* static */ AVCodec*
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(AVCodecID aCodec)
FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(FFmpegLibWrapper* aLib,
AVCodecID aCodec)
{
StaticMutexAutoLock mon(sMonitor);
if (!sFFmpegInitDone) {
AV_CALL(avcodec_register_all());
#ifdef DEBUG
AV_CALL(av_log_set_level(AV_LOG_DEBUG));
#endif
sFFmpegInitDone = true;
}
return AV_CALL(avcodec_find_decoder(aCodec));
return aLib->avcodec_find_decoder(aCodec);
}
} // namespace mozilla

View File

@ -8,9 +8,9 @@
#define __FFmpegDataDecoder_h__
#include "PlatformDecoderModule.h"
#include "FFmpegLibs.h"
#include "FFmpegRuntimeLinker.h"
#include "FFmpegLibWrapper.h"
#include "mozilla/StaticMutex.h"
#include "FFmpegLibs.h"
namespace mozilla
{
@ -24,7 +24,7 @@ template <>
class FFmpegDataDecoder<LIBAV_VER> : public MediaDataDecoder
{
public:
FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
FFmpegDataDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
AVCodecID aCodecID);
virtual ~FFmpegDataDecoder();
@ -37,7 +37,7 @@ public:
nsresult Drain() override;
nsresult Shutdown() override;
static AVCodec* FindAVCodec(AVCodecID aCodec);
static AVCodec* FindAVCodec(FFmpegLibWrapper* aLib, AVCodecID aCodec);
protected:
// Flush and Drain operation, always run
@ -48,6 +48,7 @@ protected:
AVFrame* PrepareFrame();
nsresult InitDecoder();
FFmpegLibWrapper* mLib;
RefPtr<FlushableTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
@ -65,7 +66,6 @@ protected:
Atomic<bool> mIsFlushing;
private:
static bool sFFmpegInitDone;
static StaticMutex sMonitor;
};

View File

@ -8,6 +8,7 @@
#define __FFmpegDecoderModule_h__
#include "PlatformDecoderModule.h"
#include "FFmpegLibWrapper.h"
#include "FFmpegAudioDecoder.h"
#include "FFmpegVideoDecoder.h"
@ -19,14 +20,14 @@ class FFmpegDecoderModule : public PlatformDecoderModule
{
public:
static already_AddRefed<PlatformDecoderModule>
Create()
Create(FFmpegLibWrapper* aLib)
{
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule();
RefPtr<PlatformDecoderModule> pdm = new FFmpegDecoderModule(aLib);
return pdm.forget();
}
FFmpegDecoderModule() {}
explicit FFmpegDecoderModule(FFmpegLibWrapper* aLib) : mLib(aLib) {}
virtual ~FFmpegDecoderModule() {}
already_AddRefed<MediaDataDecoder>
@ -37,7 +38,7 @@ public:
MediaDataDecoderCallback* aCallback) override
{
RefPtr<MediaDataDecoder> decoder =
new FFmpegVideoDecoder<V>(aVideoTaskQueue, aCallback, aConfig,
new FFmpegVideoDecoder<V>(mLib, aVideoTaskQueue, aCallback, aConfig,
aImageContainer);
return decoder.forget();
}
@ -51,7 +52,7 @@ public:
return nullptr;
#else
RefPtr<MediaDataDecoder> decoder =
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
new FFmpegAudioDecoder<V>(mLib, aAudioTaskQueue, aCallback, aConfig);
return decoder.forget();
#endif
}
@ -68,7 +69,7 @@ public:
return false;
}
AVCodecID codec = audioCodec != AV_CODEC_ID_NONE ? audioCodec : videoCodec;
return !!FFmpegDataDecoder<V>::FindAVCodec(codec);
return !!FFmpegDataDecoder<V>::FindAVCodec(mLib, codec);
}
ConversionRequired
@ -83,6 +84,8 @@ public:
}
}
private:
FFmpegLibWrapper* mLib;
};
} // namespace mozilla

View File

@ -1,39 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* libavcodec */
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
#if LIBAVCODEC_VERSION_MAJOR <= 54 || defined(LIBAVCODEC_ALLVERSION)
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
#endif
/* libavutil */
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
#if defined(LIBAVCODEC_VERSION_MAJOR) || defined(LIBAVCODEC_ALLVERSION)
#if LIBAVCODEC_VERSION_MAJOR == 54 || defined(LIBAVCODEC_ALLVERSION)
/* libavutil v54 only */
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
#endif
#if LIBAVCODEC_VERSION_MAJOR >= 55 || defined(LIBAVCODEC_ALLVERSION)
/* libavutil v55 and later only */
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
#endif
#endif

View File

@ -0,0 +1,149 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FFmpegLibWrapper.h"
#include "FFmpegLog.h"
#include "mozilla/PodOperations.h"
#include "mozilla/Types.h"
#include "prlink.h"
#define AV_LOG_DEBUG 48
namespace mozilla
{
FFmpegLibWrapper::FFmpegLibWrapper()
{
PodZero(this);
}
FFmpegLibWrapper::~FFmpegLibWrapper()
{
Unlink();
}
bool
FFmpegLibWrapper::Link()
{
if (!mAVCodecLib || !mAVUtilLib) {
Unlink();
return false;
}
avcodec_version =
(decltype(avcodec_version))PR_FindSymbol(mAVCodecLib, "avcodec_version");
if (!avcodec_version) {
Unlink();
return false;
}
uint32_t version = avcodec_version();
mVersion = (version >> 16) & 0xff;
uint32_t micro = version & 0xff;
if (mVersion == 57 && micro != 100) {
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV).
// Due to current AVCodecContext binary incompatibility we can only
// support FFmpeg 57 at this stage.
Unlink();
return false;
}
enum {
AV_FUNC_AVUTIL_MASK = 1 << 8,
AV_FUNC_53 = 1 << 0,
AV_FUNC_54 = 1 << 1,
AV_FUNC_55 = 1 << 2,
AV_FUNC_56 = 1 << 3,
AV_FUNC_57 = 1 << 4,
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
};
switch (mVersion) {
case 53:
version = AV_FUNC_53;
break;
case 54:
version = AV_FUNC_54;
break;
case 55:
version = AV_FUNC_55;
break;
case 56:
version = AV_FUNC_56;
break;
case 57:
version = AV_FUNC_57;
break;
default:
FFMPEG_LOG("Unknown avcodec version");
Unlink();
return false;
}
#define AV_FUNC(func, ver) \
if ((ver) & version) { \
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, #func))) { \
FFMPEG_LOG("Couldn't load function " # func); \
Unlink(); \
return false; \
} \
} else { \
func = (decltype(func))nullptr; \
}
AV_FUNC(av_lockmgr_register, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_alloc_context3, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_close, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_decode_audio4, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_decode_video2, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_find_decoder, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_flush_buffers, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_open2, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_register_all, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_init_packet, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_init, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_close, AV_FUNC_AVCODEC_ALL)
AV_FUNC(av_parser_parse2, AV_FUNC_AVCODEC_ALL)
AV_FUNC(avcodec_get_frame_defaults, (AV_FUNC_53 | AV_FUNC_54))
AV_FUNC(av_log_set_level, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_malloc, AV_FUNC_AVUTIL_ALL)
AV_FUNC(av_freep, AV_FUNC_AVUTIL_ALL)
AV_FUNC(avcodec_alloc_frame, AV_FUNC_AVUTIL_54)
AV_FUNC(avcodec_free_frame, AV_FUNC_AVUTIL_54)
AV_FUNC(av_frame_alloc, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_free, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
AV_FUNC(av_frame_unref, (AV_FUNC_AVUTIL_55 | AV_FUNC_AVUTIL_56 | AV_FUNC_AVUTIL_57))
#undef AV_FUNC
avcodec_register_all();
#ifdef DEBUG
av_log_set_level(AV_LOG_DEBUG);
#endif
return true;
}
void
FFmpegLibWrapper::Unlink()
{
if (av_lockmgr_register) {
// Registering a null lockmgr cause the destruction of libav* global mutexes
// as the default lockmgr that allocated them will be deregistered.
// This prevents ASAN and valgrind to report sizeof(pthread_mutex_t) leaks.
av_lockmgr_register(nullptr);
}
if (mAVUtilLib && mAVUtilLib != mAVCodecLib) {
PR_UnloadLibrary(mAVUtilLib);
}
if (mAVCodecLib) {
PR_UnloadLibrary(mAVCodecLib);
}
PodZero(this);
}
} // namespace mozilla

View File

@ -0,0 +1,79 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __FFmpegLibWrapper_h__
#define __FFmpegLibWrapper_h__
#include "mozilla/Types.h"
struct AVCodec;
struct AVCodecContext;
struct AVFrame;
struct AVPacket;
struct AVDictionary;
struct AVCodecParserContext;
struct PRLibrary;
namespace mozilla
{
struct FFmpegLibWrapper
{
FFmpegLibWrapper();
~FFmpegLibWrapper();
// Attempt to resolve all symbols. Return true of successful.
// Upon failure, the entire object will be reset and any attached libraries
// will be unlinked.
bool Link();
// Reset the wrapper and unlink all attached libraries.
void Unlink();
// indicate the version of libavcodec linked to.
// 0 indicates that the function wasn't initialized with Link().
int mVersion;
// libavcodec
unsigned (*avcodec_version)();
int (*av_lockmgr_register)(int (*cb)(void** mutex, int op));
AVCodecContext* (*avcodec_alloc_context3)(const AVCodec* codec);
int (*avcodec_close)(AVCodecContext* avctx);
int (*avcodec_decode_audio4)(AVCodecContext* avctx, AVFrame* frame, int* got_frame_ptr, const AVPacket* avpkt);
int (*avcodec_decode_video2)(AVCodecContext* avctx, AVFrame* picture, int* got_picture_ptr, const AVPacket* avpkt);
AVCodec* (*avcodec_find_decoder)(int id);
void (*avcodec_flush_buffers)(AVCodecContext *avctx);
int (*avcodec_open2)(AVCodecContext *avctx, const AVCodec* codec, AVDictionary** options);
void (*avcodec_register_all)();
void (*av_init_packet)(AVPacket* pkt);
AVCodecParserContext* (*av_parser_init)(int codec_id);
void (*av_parser_close)(AVCodecParserContext* s);
int (*av_parser_parse2)(AVCodecParserContext* s, AVCodecContext* avctx, uint8_t** poutbuf, int* poutbuf_size, const uint8_t* buf, int buf_size, int64_t pts, int64_t dts, int64_t pos);
// only used in libavcodec <= 54
void (*avcodec_get_frame_defaults)(AVFrame* pic);
// libavutil
void (*av_log_set_level)(int level);
void* (*av_malloc)(size_t size);
void (*av_freep)(void *ptr);
// libavutil v54 only
AVFrame* (*avcodec_alloc_frame)();
void (*avcodec_free_frame)(AVFrame** frame);
// libavutil v55 and later only
AVFrame* (*av_frame_alloc)();
void (*av_frame_free)(AVFrame** frame);
void (*av_frame_unref)(AVFrame* frame);
PRLibrary* mAVCodecLib;
PRLibrary* mAVUtilLib;
private:
};
} // namespace mozilla
#endif // FFmpegLibWrapper

View File

@ -7,8 +7,6 @@
#ifndef __FFmpegLibs_h__
#define __FFmpegLibs_h__
#include "mozilla/Types.h"
extern "C" {
#ifdef __GNUC__
#pragma GCC visibility push(default)
@ -37,23 +35,4 @@ enum { LIBAV_VER = FFVPX_VERSION };
enum { LIBAV_VER = LIBAVCODEC_VERSION_MAJOR };
#endif
namespace mozilla {
#ifdef USING_MOZFFVPX
namespace ffvpx {
#endif
#define AV_FUNC(func, ver) extern decltype(func)* func;
#include "FFmpegFunctionList.h"
#undef AV_FUNC
#ifdef USING_MOZFFVPX
} // namespace ffvpx
#define AV_CALL(func) mozilla::ffvpx::func
#else
#define AV_CALL(func) mozilla::func
#endif
}
#endif // __FFmpegLibs_h__

View File

@ -7,6 +7,8 @@
#ifndef __FFmpegLog_h__
#define __FFmpegLog_h__
#include "mozilla/Logging.h"
extern mozilla::LogModule* GetPDMLog();
#define FFMPEG_LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))

View File

@ -5,9 +5,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FFmpegRuntimeLinker.h"
#include "FFmpegLibWrapper.h"
#include "mozilla/ArrayUtils.h"
#include "FFmpegLog.h"
#include "mozilla/Types.h"
#include "prlink.h"
namespace mozilla
@ -19,9 +19,11 @@ FFmpegRuntimeLinker::LinkStatus FFmpegRuntimeLinker::sLinkStatus =
template <int V> class FFmpegDecoderModule
{
public:
static already_AddRefed<PlatformDecoderModule> Create();
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
};
static FFmpegLibWrapper sLibAV;
static const char* sLibs[] = {
#if defined(XP_DARWIN)
"libavcodec.57.dylib",
@ -40,30 +42,8 @@ static const char* sLibs[] = {
#endif
};
PRLibrary* FFmpegRuntimeLinker::sLinkedLib = nullptr;
PRLibrary* FFmpegRuntimeLinker::sLinkedUtilLib = nullptr;
static unsigned (*avcodec_version)() = nullptr;
#ifdef __GNUC__
#define AV_FUNC(func, ver) void (*func)();
#define LIBAVCODEC_ALLVERSION
#else
#define AV_FUNC(func, ver) decltype(func)* func;
#endif
#include "FFmpegFunctionList.h"
#undef AV_FUNC
static PRLibrary*
MozAVLink(const char* aName)
{
PRLibSpec lspec;
lspec.type = PR_LibSpec_Pathname;
lspec.value.pathname = aName;
return PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
}
/* static */ bool
FFmpegRuntimeLinker::Link()
FFmpegRuntimeLinker::Init()
{
if (sLinkStatus) {
return sLinkStatus == LinkStatus_SUCCEEDED;
@ -72,15 +52,16 @@ FFmpegRuntimeLinker::Link()
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
const char* lib = sLibs[i];
sLinkedLib = MozAVLink(lib);
if (sLinkedLib) {
sLinkedUtilLib = sLinkedLib;
if (Bind(lib)) {
PRLibSpec lspec;
lspec.type = PR_LibSpec_Pathname;
lspec.value.pathname = lib;
sLibAV.mAVCodecLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
if (sLibAV.mAVCodecLib) {
sLibAV.mAVUtilLib = sLibAV.mAVCodecLib;
if (sLibAV.Link()) {
sLinkStatus = LinkStatus_SUCCEEDED;
return true;
}
// Shouldn't happen but if it does then we try the next lib..
Unlink();
}
}
@ -90,113 +71,26 @@ FFmpegRuntimeLinker::Link()
}
FFMPEG_LOG(" ]\n");
Unlink();
sLinkStatus = LinkStatus_FAILED;
return false;
}
/* static */ bool
FFmpegRuntimeLinker::Bind(const char* aLibName)
{
avcodec_version = (decltype(avcodec_version))PR_FindSymbol(sLinkedLib,
"avcodec_version");
uint32_t major, minor, micro;
if (!GetVersion(major, minor, micro)) {
return false;
}
int version;
switch (major) {
case 53:
version = AV_FUNC_53;
break;
case 54:
version = AV_FUNC_54;
break;
case 56:
// We use libavcodec 55 code instead. Fallback
case 55:
version = AV_FUNC_55;
break;
case 57:
if (micro != 100) {
// a micro version of 100 indicates that it's FFmpeg (as opposed to LibAV.
// Due to current AVCodecContext binary incompatibility we can only
// support FFmpeg at this stage.
return false;
}
version = AV_FUNC_57;
break;
default:
// Not supported at this stage.
return false;
}
#define AV_FUNC(func, ver) \
if ((ver) & version) { \
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
return false; \
} \
} else { \
func = (decltype(func))nullptr; \
}
#include "FFmpegFunctionList.h"
#undef AV_FUNC
return true;
}
/* static */ already_AddRefed<PlatformDecoderModule>
FFmpegRuntimeLinker::CreateDecoderModule()
{
if (!Link()) {
if (!Init()) {
return nullptr;
}
uint32_t major, minor, micro;
if (!GetVersion(major, minor, micro)) {
return nullptr;
}
RefPtr<PlatformDecoderModule> module;
switch (major) {
case 53: module = FFmpegDecoderModule<53>::Create(); break;
case 54: module = FFmpegDecoderModule<54>::Create(); break;
switch (sLibAV.mVersion) {
case 53: module = FFmpegDecoderModule<53>::Create(&sLibAV); break;
case 54: module = FFmpegDecoderModule<54>::Create(&sLibAV); break;
case 55:
case 56: module = FFmpegDecoderModule<55>::Create(); break;
case 57: module = FFmpegDecoderModule<57>::Create(); break;
case 56: module = FFmpegDecoderModule<55>::Create(&sLibAV); break;
case 57: module = FFmpegDecoderModule<57>::Create(&sLibAV); break;
default: module = nullptr;
}
return module.forget();
}
/* static */ void
FFmpegRuntimeLinker::Unlink()
{
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
PR_UnloadLibrary(sLinkedUtilLib);
}
if (sLinkedLib) {
PR_UnloadLibrary(sLinkedLib);
sLinkedLib = nullptr;
sLinkStatus = LinkStatus_INIT;
avcodec_version = nullptr;
}
sLinkedUtilLib = nullptr;
}
/* static */ bool
FFmpegRuntimeLinker::GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro)
{
if (!avcodec_version) {
return false;
}
uint32_t version = avcodec_version();
aMajor = (version >> 16) & 0xff;
aMinor = (version >> 8) & 0xff;
aMicro = version & 0xff;
return true;
}
#undef LIBAVCODEC_ALLVERSION
} // namespace mozilla

View File

@ -8,43 +8,17 @@
#define __FFmpegRuntimeLinker_h__
#include "PlatformDecoderModule.h"
#include <stdint.h>
struct PRLibrary;
namespace mozilla
{
enum {
AV_FUNC_AVUTIL_MASK = 1 << 8,
AV_FUNC_53 = 1 << 0,
AV_FUNC_54 = 1 << 1,
AV_FUNC_55 = 1 << 2,
AV_FUNC_56 = 1 << 3,
AV_FUNC_57 = 1 << 4,
AV_FUNC_AVUTIL_53 = AV_FUNC_53 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_54 = AV_FUNC_54 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_55 = AV_FUNC_55 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_56 = AV_FUNC_56 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVUTIL_57 = AV_FUNC_57 | AV_FUNC_AVUTIL_MASK,
AV_FUNC_AVCODEC_ALL = AV_FUNC_53 | AV_FUNC_54 | AV_FUNC_55 | AV_FUNC_56 | AV_FUNC_57,
AV_FUNC_AVUTIL_ALL = AV_FUNC_AVCODEC_ALL | AV_FUNC_AVUTIL_MASK
};
class FFmpegRuntimeLinker
{
public:
static bool Link();
static void Unlink();
static bool Init();
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
static bool GetVersion(uint32_t& aMajor, uint32_t& aMinor, uint32_t& aMicro);
private:
static PRLibrary* sLinkedLib;
static PRLibrary* sLinkedUtilLib;
static bool Bind(const char* aLibName);
static enum LinkStatus {
LinkStatus_INIT = 0,
LinkStatus_FAILED,

View File

@ -98,11 +98,11 @@ FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset()
mLastDts = INT64_MIN;
}
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(FFmpegLibWrapper* aLib,
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig,
ImageContainer* aImageContainer)
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
, mImageContainer(aImageContainer)
, mDisplay(aConfig.mDisplay)
, mImage(aConfig.mImage)
@ -151,7 +151,7 @@ FFmpegVideoDecoder<LIBAV_VER>::InitCodecContext()
// FFmpeg will call back to this to negotiate a video pixel format.
mCodecContext->get_format = ChoosePixelFormat;
mCodecParser = AV_CALL(av_parser_init(mCodecID));
mCodecParser = mLib->av_parser_init(mCodecID);
if (mCodecParser) {
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
}
@ -175,10 +175,10 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
while (inputSize) {
uint8_t* data;
int size;
int len = AV_CALL(av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
inputData, inputSize,
aSample->mTime, aSample->mTimecode,
aSample->mOffset));
int len = mLib->av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
inputData, inputSize,
aSample->mTime, aSample->mTimecode,
aSample->mOffset);
if (size_t(len) > inputSize) {
mCallback->Error();
return DecodeResult::DECODE_ERROR;
@ -210,7 +210,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
AVPacket packet;
AV_CALL(av_init_packet(&packet));
mLib->av_init_packet(&packet);
packet.data = aData;
packet.size = aSize;
@ -237,7 +237,7 @@ FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
int decoded;
int bytesConsumed =
AV_CALL(avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet));
mLib->avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet);
FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d "
"(Input: pts(%lld) dts(%lld) Output: pts(%lld) "
@ -361,7 +361,7 @@ FFmpegVideoDecoder<LIBAV_VER>::~FFmpegVideoDecoder()
{
MOZ_COUNT_DTOR(FFmpegVideoDecoder);
if (mCodecParser) {
AV_CALL(av_parser_close(mCodecParser));
mLib->av_parser_close(mCodecParser);
mCodecParser = nullptr;
}
}

View File

@ -7,6 +7,7 @@
#ifndef __FFmpegVideoDecoder_h__
#define __FFmpegVideoDecoder_h__
#include "FFmpegLibWrapper.h"
#include "FFmpegDataDecoder.h"
#include "mozilla/Pair.h"
#include "nsTArray.h"
@ -32,10 +33,10 @@ class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
};
public:
FFmpegVideoDecoder(FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig,
ImageContainer* aImageContainer);
FFmpegVideoDecoder(FFmpegLibWrapper* aLib, FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig,
ImageContainer* aImageContainer);
virtual ~FFmpegVideoDecoder();
RefPtr<InitPromise> Init() override;

View File

@ -5,47 +5,27 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FFVPXRuntimeLinker.h"
#include "FFmpegRuntimeLinker.h"
#include "FFmpegLibWrapper.h"
#include "FFmpegLog.h"
#include "mozilla/Types.h"
#include "nsIFile.h"
#include "nsXPCOMPrivate.h" // for XUL_DLL
#include "prmem.h"
#include "prlink.h"
#if defined(XP_WIN)
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#endif
namespace mozilla
{
template <int V> class FFmpegDecoderModule
{
public:
static already_AddRefed<PlatformDecoderModule> Create();
static already_AddRefed<PlatformDecoderModule> Create(FFmpegLibWrapper*);
};
namespace ffvpx
{
static FFmpegLibWrapper sFFVPXLib;
FFVPXRuntimeLinker::LinkStatus FFVPXRuntimeLinker::sLinkStatus =
LinkStatus_INIT;
PRLibrary* FFVPXRuntimeLinker::sLinkedLib = nullptr;
PRLibrary* FFVPXRuntimeLinker::sLinkedUtilLib = nullptr;
static unsigned (*avcodec_version)() = nullptr;
#ifdef __GNUC__
#define AV_FUNC(func, ver) void (*func)();
#define LIBAVCODEC_ALLVERSION
#else
#define AV_FUNC(func, ver) decltype(func)* func;
#endif
#include "FFmpegFunctionList.h"
#undef AV_FUNC
static PRLibrary*
MozAVLink(const char* aName)
{
@ -56,7 +36,7 @@ MozAVLink(const char* aName)
}
/* static */ bool
FFVPXRuntimeLinker::Link()
FFVPXRuntimeLinker::Init()
{
if (sLinkStatus) {
return sLinkStatus == LinkStatus_SUCCEEDED;
@ -67,7 +47,7 @@ FFVPXRuntimeLinker::Link()
// We retrieve the path of the XUL library as this is where mozavcodec and
// mozavutil libs are located.
char* path =
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Link);
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Init);
if (!path) {
return false;
}
@ -94,69 +74,29 @@ FFVPXRuntimeLinker::Link()
if (!libname) {
return false;
}
sLinkedUtilLib = MozAVLink(libname);
sFFVPXLib.mAVUtilLib = MozAVLink(libname);
PR_FreeLibraryName(libname);
libname = PR_GetLibraryName(rootPath.get(), "mozavcodec");
if (libname) {
sLinkedLib = MozAVLink(libname);
sFFVPXLib.mAVCodecLib = MozAVLink(libname);
PR_FreeLibraryName(libname);
if (sLinkedLib && sLinkedUtilLib) {
if (Bind("mozavcodec")) {
sLinkStatus = LinkStatus_SUCCEEDED;
return true;
}
}
}
Unlink();
if (sFFVPXLib.Link()) {
sLinkStatus = LinkStatus_SUCCEEDED;
return true;
}
sLinkStatus = LinkStatus_FAILED;
return false;
}
/* static */ bool
FFVPXRuntimeLinker::Bind(const char* aLibName)
{
int version = AV_FUNC_57;
#define AV_FUNC(func, ver) \
if ((ver) & version) { \
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
return false; \
} \
} else { \
func = (decltype(func))nullptr; \
}
#include "FFmpegFunctionList.h"
#undef AV_FUNC
return true;
}
/* static */ already_AddRefed<PlatformDecoderModule>
FFVPXRuntimeLinker::CreateDecoderModule()
{
if (!Link()) {
if (!Init()) {
return nullptr;
}
return FFmpegDecoderModule<FFVPX_VERSION>::Create();
return FFmpegDecoderModule<FFVPX_VERSION>::Create(&sFFVPXLib);
}
/* static */ void
FFVPXRuntimeLinker::Unlink()
{
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
PR_UnloadLibrary(sLinkedUtilLib);
}
if (sLinkedLib) {
PR_UnloadLibrary(sLinkedLib);
sLinkedLib = nullptr;
sLinkStatus = LinkStatus_INIT;
avcodec_version = nullptr;
}
sLinkedUtilLib = nullptr;
}
#undef LIBAVCODEC_ALLVERSION
} // namespace ffvpx
} // namespace mozilla

View File

@ -9,35 +9,23 @@
#include "PlatformDecoderModule.h"
struct PRLibrary;
namespace mozilla
{
namespace ffvpx
{
class FFVPXRuntimeLinker
{
public:
static bool Link();
static void Unlink();
static bool Init();
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
private:
static PRLibrary* sLinkedLib;
static PRLibrary* sLinkedUtilLib;
static enum LinkStatus {
LinkStatus_INIT = 0,
LinkStatus_FAILED,
LinkStatus_SUCCEEDED
} sLinkStatus;
static bool Bind(const char* aLibName);
};
}
}
#endif /* __FFVPXRuntimeLinker_h__ */

View File

@ -0,0 +1,22 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXPORTS += [
'FFmpegRuntimeLinker.h',
]
DIRS += [
'libav53',
'libav54',
'libav55',
'ffmpeg57',
]
UNIFIED_SOURCES += [
'FFmpegRuntimeLinker.cpp',
]
FINAL_LIBRARY = 'xul'

View File

@ -38,23 +38,20 @@ if CONFIG['MOZ_WMF']:
if CONFIG['MOZ_EME']:
DIRS += ['agnostic/eme']
if CONFIG['MOZ_FFVPX'] or CONFIG['MOZ_FFMPEG']:
# common code to either FFmpeg or FFVPX
UNIFIED_SOURCES += [
'ffmpeg/FFmpegLibWrapper.cpp',
]
if CONFIG['MOZ_FFVPX']:
DIRS += [
'ffmpeg/ffvpx',
]
if CONFIG['MOZ_FFMPEG']:
EXPORTS += [
'ffmpeg/FFmpegRuntimeLinker.h',
]
UNIFIED_SOURCES += [
'ffmpeg/FFmpegRuntimeLinker.cpp',
]
DIRS += [
'ffmpeg/libav53',
'ffmpeg/libav54',
'ffmpeg/libav55',
'ffmpeg/ffmpeg57',
'ffmpeg',
]
if CONFIG['MOZ_APPLEMEDIA']:

View File

@ -1,7 +0,0 @@
exclude MANIFEST.in
include requirements.txt
include setup.py
recursive-include firefox_media_tests *
recursive-include media_utils *

5
dom/media/test/external/MANIFEST.in vendored Normal file
View File

@ -0,0 +1,5 @@
exclude MANIFEST.in
recursive-include external_media_harness *
recursive-include external_media_tests *

View File

@ -1,4 +1,4 @@
firefox-media-tests
external-media-tests
===================
[Marionette Python tests][marionette-python-tests] for media playback in Mozilla Firefox. MediaTestCase uses [Firefox Puppeteer][ff-puppeteer-docs] library.
@ -6,7 +6,7 @@ firefox-media-tests
Setup
-----
The instructions below assume you have a copy of the project in `some/path/firefox-media-tests` and they refer to this path as `$PROJECT_HOME`.
Normally, you get this source by cloning a firefox repo such as mozilla-central. The path to these tests would be in <mozilla-central>/dom/media/test/external, and these instuctions refer to this path as '$PROJECT_HOME'.
* Create a virtualenv called `foo`.
@ -15,13 +15,13 @@ The instructions below assume you have a copy of the project in `some/path/firef
$ source foo/bin/activate #or `foo\Scripts\activate` on Windows
```
* Install `firefox-media-tests` in development mode. (To get an environment that is closer to what is actually used in Mozilla's automation jobs, run `pip install -r requirements.txt` first.)
* Install `external-media-tests` in development mode. (To get an environment that is closer to what is actually used in Mozilla's automation jobs, run `pip install -r requirements.txt` first.)
```sh
$ python setup.py develop
```
Now `firefox-media-tests` should be a recognized command. Try `firefox-media-tests --help` to see if it works.
Now `external-media-tests` should be a recognized command. Try `external-media-tests --help` to see if it works.
Running the Tests
@ -29,28 +29,28 @@ Running the Tests
In the examples below, `$FF_PATH` is a path to a recent Firefox binary.
This runs all the tests listed in `$PROJECT_HOME/firefox_media_tests/manifest.ini`:
This runs all the tests listed in `$PROJECT_HOME/external_media_tests/manifest.ini`:
```sh
$ firefox-media-tests --binary $FF_PATH
$ external-media-tests --binary $FF_PATH
```
You can also run all the tests at a particular path:
```sh
$ firefox-media-tests --binary $FF_PATH some/path/foo
$ external-media-tests --binary $FF_PATH some/path/foo
```
Or you can run the tests that are listed in a manifest file of your choice.
```sh
$ firefox-media-tests --binary $FF_PATH some/other/path/manifest.ini
$ external-media-tests --binary $FF_PATH some/other/path/manifest.ini
```
By default, the urls listed in `firefox_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
By default, the urls listed in `external_media_tests/urls/default.ini` are used for the tests, but you can also supply your own ini file of urls:
```sh
$ firefox-media-tests --binary $FF_PATH --urls some/other/path/my_urls.ini
$ external-media-tests --binary $FF_PATH --urls some/other/path/my_urls.ini
```
### Running EME tests
@ -58,7 +58,7 @@ By default, the urls listed in `firefox_media_tests/urls/default.ini` are used f
In order to run EME tests, you must use a Firefox profile that has a signed plugin-container.exe and voucher.bin. With Netflix, this will be created when you log in and save the credentials. You must also use a custom .ini file for urls to the provider's content and indicate which test to run, like above. Ex:
```sh
$ firefox-media-tests --binary $FF_PATH some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
$ external-media-tests --binary $FF_PATH some/path/tests.ini --profile custom_profile --urls some/path/provider-urls.ini
```
@ -84,7 +84,7 @@ What if Firefox crashes during a test run? You want to know why! To report usefu
5. Run the tests with a `--symbols-path` flag
```sh
$ firefox-media-tests --binary $FF_PATH --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
$ external-media-tests --binary $FF_PATH --symbols-path path/to/example/firefox-38.0a2.en-US.win32.crashreporter-symbols
```
To check whether the above setup is working for you, trigger a (silly) Firefox crash while the tests are running. One way to do this is with the [crashme add-on](https://github.com/luser/crashme) -- you can add it to Firefox even while the tests are running. Another way on Linux and Mac OS systems:
@ -101,7 +101,7 @@ To check whether the above setup is working for you, trigger a (silly) Firefox c
$ kill -6 1234
```
Somewhere in the output produced by `firefox-media-tests`, you should see something like:
Somewhere in the output produced by `external-media-tests`, you should see something like:
```
0:12.68 CRASH: MainThread pid:1234. Test:test_basic_playback.py TestVideoPlayback.test_playback_starts.
@ -137,11 +137,11 @@ On Windows, use browsermob-proxy.bat.
You can then call browsermob to shape the network. You can find an example in firefox_media_tests/playback/test_playback_limiting_bandwidth.py. Another example can be found at https://dxr.mozilla.org/mozilla-central/source/testing/marionette/client/marionette/tests/unit/test_browsermobproxy.py.
### A warning about video URLs
The ini files in `firefox_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
The ini files in `external_media_tests/urls` may contain URLs pulled from Firefox crash or bug data. Automated tests don't care about video content, but you might: visit these at your own risk and be aware that they may be NSFW. We do not intend to ever moderate or filter these URLs.
Writing a test
--------------
Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/firefox_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
Write your test in a new or existing `test_*.py` file under `$PROJECT_HOME/external_media_tests`. Add it to the appropriate `manifest.ini` file(s) as well. Look in `media_utils` for useful video-playback functions.
* [Marionette docs][marionette-docs]
- [Marionette Command Line Options](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options)

View File

@ -11,9 +11,9 @@ from marionette.runner import BrowserMobProxyArguments
from marionette.runtests import MarionetteHarness, cli as mn_cli
import mozlog
import media_tests
import external_media_tests
from testcase import MediaTestCase
from media_utils.video_puppeteer import debug_script
from external_media_tests.media_utils.video_puppeteer import debug_script
class MediaTestArgumentsBase(object):
@ -21,7 +21,7 @@ class MediaTestArgumentsBase(object):
args = [
[['--urls'], {
'help': 'ini file of urls to make available to all tests',
'default': os.path.join(media_tests.urls, 'default.ini'),
'default': os.path.join(external_media_tests.urls, 'default.ini'),
}],
]
@ -35,7 +35,7 @@ class MediaTestArgumentsBase(object):
def parse_args_handler(self, args):
if not args.tests:
args.tests = [media_tests.manifest]
args.tests = [external_media_tests.manifest]
@staticmethod
@ -55,7 +55,7 @@ class MediaTestRunner(BaseMarionetteTestRunner):
def __init__(self, **kwargs):
BaseMarionetteTestRunner.__init__(self, **kwargs)
if not self.server_root:
self.server_root = media_tests.resources
self.server_root = external_media_tests.resources
# pick up prefs from marionette_driver.geckoinstance.DesktopInstance
self.app = 'fxdesktop'
self.test_handlers = [MediaTestCase]
@ -86,17 +86,6 @@ class MediaTestRunner(BaseMarionetteTestRunner):
class FirefoxMediaHarness(MarionetteHarness):
def __init__(self,
runner_class=MediaTestRunner,
parser_class=MediaTestArguments):
# workaround until next marionette-client release - Bug 1227918
try:
MarionetteHarness.__init__(self, runner_class, parser_class)
except Exception:
logger = mozlog.commandline.setup_logging('Media-test harness', {})
logger.error('Failure setting up harness', exc_info=True)
raise
def parse_args(self, *args, **kwargs):
return MarionetteHarness.parse_args(self, {'mach': sys.stdout})

View File

@ -10,8 +10,8 @@ from marionette_driver.errors import TimeoutException
from marionette.marionette_test import SkipTest
from firefox_puppeteer.testcases import FirefoxTestCase
from media_tests.utils import (timestamp_now, verbose_until)
from media_utils.video_puppeteer import (playback_done, playback_started,
from external_media_tests.utils import (timestamp_now, verbose_until)
from external_media_tests.media_utils.video_puppeteer import (playback_done, playback_started,
VideoException, VideoPuppeteer as VP)

View File

@ -6,7 +6,7 @@ from time import clock, sleep
from marionette_driver import By, expected, Wait
from media_tests.utils import verbose_until
from external_media_tests.utils import verbose_until
# Adapted from

View File

@ -9,7 +9,7 @@ from json import loads
from marionette_driver import By, expected, Wait
from marionette_driver.errors import TimeoutException, NoSuchElementException
from video_puppeteer import VideoPuppeteer, VideoException
from media_tests.utils import verbose_until
from external_media_tests.utils import verbose_until
class YouTubePuppeteer(VideoPuppeteer):

View File

@ -4,7 +4,7 @@
import re
from harness.testcase import MediaTestCase, VideoPlaybackTestsMixin
from external_media_harness.testcase import MediaTestCase, VideoPlaybackTestsMixin
class TestEMEPlayback(MediaTestCase, VideoPlaybackTestsMixin):

View File

@ -3,8 +3,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from harness.testcase import MediaTestCase
from media_utils.video_puppeteer import VideoPuppeteer
from external_media_harness.testcase import MediaTestCase
from external_media_tests.media_utils.video_puppeteer import VideoPuppeteer
class TestFullPlayback(MediaTestCase):

View File

@ -4,7 +4,7 @@
from marionette import BrowserMobProxyTestCaseMixin
from harness.testcase import NetworkBandwidthTestCase
from external_media_harness.testcase import NetworkBandwidthTestCase
class TestPlaybackLimitingBandwidth(NetworkBandwidthTestCase,

View File

@ -4,7 +4,7 @@
from marionette import BrowserMobProxyTestCaseMixin
from harness.testcase import NetworkBandwidthTestCase
from external_media_harness.testcase import NetworkBandwidthTestCase
class TestUltraLowBandwidth(NetworkBandwidthTestCase,

View File

@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from harness.testcase import (
from external_media_harness.testcase import (
MediaTestCase,
VideoPlaybackTestsMixin
)

View File

@ -5,10 +5,10 @@
from marionette_driver import Wait
from marionette_driver.errors import TimeoutException
from media_tests.utils import verbose_until
from harness.testcase import MediaTestCase
from media_utils.video_puppeteer import VideoException
from media_utils.youtube_puppeteer import (YouTubePuppeteer, playback_done,
from external_media_tests.utils import verbose_until
from external_media_harness.testcase import MediaTestCase
from external_media_tests.media_utils.video_puppeteer import VideoException
from external_media_tests.media_utils.youtube_puppeteer import (YouTubePuppeteer, playback_done,
wait_for_almost_done)

View File

@ -2,11 +2,11 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from harness.testcase import MediaTestCase
from external_media_harness.testcase import MediaTestCase
from marionette_driver import Wait
from media_tests.utils import verbose_until
from media_utils.youtube_puppeteer import YouTubePuppeteer
from external_media_tests.utils import verbose_until
from external_media_tests.media_utils.youtube_puppeteer import YouTubePuppeteer
class TestMediaSourcePrefs(MediaTestCase):

View File

@ -1,4 +1,4 @@
from harness.testcase import MediaTestCase
from external_media_harness.testcase import MediaTestCase
class TestSomethingElse(MediaTestCase):

Some files were not shown because too many files have changed in this diff Show More