Merge m-c to b2g-inbound on a CLOSED TREE. a=merge
@ -4,9 +4,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/accessibility'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.accessibility += [
|
||||
'AccessFu.jsm',
|
||||
'Constants.jsm',
|
||||
'ContentControl.jsm',
|
||||
|
@ -8,8 +8,6 @@ BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
DIRS += ["source/modules/system"]
|
||||
|
||||
JS_MODULES_PATH = 'modules/sdk'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.sdk += [
|
||||
'source/app-extension/bootstrap.js',
|
||||
]
|
||||
|
@ -4,8 +4,6 @@
|
||||
# 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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/sdk/system'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.sdk.system += [
|
||||
'XulApp.js',
|
||||
]
|
||||
|
@ -489,6 +489,7 @@
|
||||
@BINPATH@/components/nsInputListAutoComplete.js
|
||||
@BINPATH@/components/formautofill.manifest
|
||||
@BINPATH@/components/FormAutofillContentService.js
|
||||
@BINPATH@/components/FormAutofillStartup.js
|
||||
@BINPATH@/components/contentSecurityPolicy.manifest
|
||||
@BINPATH@/components/contentSecurityPolicy.js
|
||||
@BINPATH@/components/contentAreaDropListener.manifest
|
||||
|
@ -2536,7 +2536,7 @@ let BrowserOnClick = {
|
||||
try {
|
||||
let reportURL = formatURL("browser.safebrowsing.malware.reportURL", true);
|
||||
reportURL += location;
|
||||
content.location = reportURL;
|
||||
gBrowser.loadURI(reportURL);
|
||||
} catch (e) {
|
||||
Components.utils.reportError("Couldn't get malware report URL: " + e);
|
||||
}
|
||||
@ -2561,7 +2561,7 @@ let BrowserOnClick = {
|
||||
*/
|
||||
onE10sAboutNewTab: function(event, ownerDoc) {
|
||||
let isTopFrame = (ownerDoc.defaultView.parent === ownerDoc.defaultView);
|
||||
if (!isTopFrame || event.button != 0) {
|
||||
if (!isTopFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2570,7 +2570,8 @@ let BrowserOnClick = {
|
||||
if (anchorTarget instanceof HTMLAnchorElement &&
|
||||
anchorTarget.classList.contains("newtab-link")) {
|
||||
event.preventDefault();
|
||||
openUILinkIn(anchorTarget.href, "current");
|
||||
let where = whereToOpenLink(event, false, false);
|
||||
openUILinkIn(anchorTarget.href, where);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2601,11 +2602,11 @@ let BrowserOnClick = {
|
||||
// Allow users to override and continue through to the site,
|
||||
// but add a notify bar as a reminder, so that they don't lose
|
||||
// track after, e.g., tab switching.
|
||||
gBrowser.loadURIWithFlags(content.location.href,
|
||||
gBrowser.loadURIWithFlags(gBrowser.currentURI.spec,
|
||||
nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
|
||||
null, null, null);
|
||||
|
||||
Services.perms.add(makeURI(content.location.href), "safe-browsing",
|
||||
Services.perms.add(gBrowser.currentURI, "safe-browsing",
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION);
|
||||
|
||||
@ -2677,7 +2678,7 @@ function getMeOutOfHere() {
|
||||
} catch(e) {
|
||||
Components.utils.reportError("Couldn't get homepage pref: " + e);
|
||||
}
|
||||
content.location = url;
|
||||
gBrowser.loadURI(url);
|
||||
}
|
||||
|
||||
function BrowserFullScreen()
|
||||
|
@ -917,22 +917,6 @@
|
||||
cui-areatype="toolbar"
|
||||
aboutHomeOverrideTooltip="&abouthome.pageTitle;"/>
|
||||
|
||||
<!-- XXX Bug 1013989 will provide a label for the button -->
|
||||
<!-- This uses badged to be compatible with the social api code it shares.
|
||||
We may also want it to be badged in the future, for notification
|
||||
purposes. -->
|
||||
<toolbarbutton id="loop-call-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
persist="class"
|
||||
type="badged"
|
||||
removable="true"
|
||||
tooltiptext="&loopCallButton.tooltip;"
|
||||
oncommand="LoopUI.openCallPanel(event);"
|
||||
cui-areatype="toolbar"
|
||||
>
|
||||
</toolbarbutton>
|
||||
|
||||
|
||||
<toolbarbutton id="social-share-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
label="&sharePageCmd.label;"
|
||||
|
@ -52,7 +52,7 @@ const kSubviewEvents = [
|
||||
* The current version. We can use this to auto-add new default widgets as necessary.
|
||||
* (would be const but isn't because of testing purposes)
|
||||
*/
|
||||
let kVersion = 0;
|
||||
let kVersion = 1;
|
||||
|
||||
/**
|
||||
* gPalette is a map of every widget that CustomizableUI.jsm knows about, keyed
|
||||
|
@ -898,6 +898,28 @@ const CustomizableWidgets = [{
|
||||
let win = aEvent.view;
|
||||
win.MailIntegration.sendLinkForWindow(win.content);
|
||||
}
|
||||
}, {
|
||||
id: "loop-call-button",
|
||||
type: "custom",
|
||||
// XXX Bug 1013989 will provide a label for the button
|
||||
label: "loop-call-button.label",
|
||||
tooltiptext: "loop-call-button.tooltiptext",
|
||||
defaultArea: CustomizableUI.AREA_NAVBAR,
|
||||
introducedInVersion: 1,
|
||||
onBuild: function(aDocument) {
|
||||
let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
|
||||
node.setAttribute("id", this.id);
|
||||
node.classList.add("toolbarbutton-1");
|
||||
node.classList.add("chromeclass-toolbar-additional");
|
||||
node.setAttribute("type", "badged");
|
||||
node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
|
||||
node.setAttribute("tooltiptext", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
|
||||
node.setAttribute("removable", "true");
|
||||
node.addEventListener("command", function(event) {
|
||||
aDocument.defaultView.LoopUI.openCallPanel(event);
|
||||
});
|
||||
return node;
|
||||
}
|
||||
}];
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
1
browser/components/loop/.gitignore
vendored
@ -1,2 +1 @@
|
||||
.module-cache
|
||||
standalone/content/config.js
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 734 B |
Before Width: | Height: | Size: 861 B After Width: | Height: | Size: 861 B |
Before Width: | Height: | Size: 622 B After Width: | Height: | Size: 622 B |
@ -53,19 +53,19 @@ browser.jar:
|
||||
content/browser/loop/shared/sounds/Firefox-Long.ogg (content/shared/sounds/Firefox-Long.ogg)
|
||||
|
||||
# Partner SDK assets
|
||||
content/browser/loop/libs/sdk.js (content/libs/sdk.js)
|
||||
content/browser/loop/sdk-content/css/ot.css (content/libs/sdk-content/css/ot.css)
|
||||
content/browser/loop/sdk-content/js/dynamic_config.min.js (content/libs/sdk-content/js/dynamic_config.min.js)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-chrome.png (content/libs/sdk-content/images/rtc/access-denied-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-copy-firefox.png (content/libs/sdk-content/images/rtc/access-denied-copy-firefox.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-firefox.png (content/libs/sdk-content/images/rtc/access-denied-firefox.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-predenied-chrome.png (content/libs/sdk-content/images/rtc/access-predenied-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-prompt-chrome.png (content/libs/sdk-content/images/rtc/access-prompt-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/audioonly-publisher.png (content/libs/sdk-content/images/rtc/audioonly-publisher.png)
|
||||
content/browser/loop/sdk-content/images/rtc/audioonly-subscriber.png (content/libs/sdk-content/images/rtc/audioonly-subscriber.png)
|
||||
content/browser/loop/sdk-content/images/rtc/buttons.png (content/libs/sdk-content/images/rtc/buttons.png)
|
||||
content/browser/loop/sdk-content/images/rtc/loader.gif (content/libs/sdk-content/images/rtc/loader.gif)
|
||||
content/browser/loop/sdk-content/images/rtc/mic-off.png (content/libs/sdk-content/images/rtc/mic-off.png)
|
||||
content/browser/loop/sdk-content/images/rtc/mic-on.png (content/libs/sdk-content/images/rtc/mic-on.png)
|
||||
content/browser/loop/sdk-content/images/rtc/speaker-off.png (content/libs/sdk-content/images/rtc/speaker-off.png)
|
||||
content/browser/loop/sdk-content/images/rtc/speaker-on.png (content/libs/sdk-content/images/rtc/speaker-on.png)
|
||||
content/browser/loop/libs/sdk.js (content/shared/libs/sdk.js)
|
||||
content/browser/loop/sdk-content/css/ot.css (content/shared/libs/sdk-content/css/ot.css)
|
||||
content/browser/loop/sdk-content/js/dynamic_config.min.js (content/shared/libs/sdk-content/js/dynamic_config.min.js)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-chrome.png (content/shared/libs/sdk-content/images/rtc/access-denied-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-copy-firefox.png (content/shared/libs/sdk-content/images/rtc/access-denied-copy-firefox.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-denied-firefox.png (content/shared/libs/sdk-content/images/rtc/access-denied-firefox.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-predenied-chrome.png (content/shared/libs/sdk-content/images/rtc/access-predenied-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/access-prompt-chrome.png (content/shared/libs/sdk-content/images/rtc/access-prompt-chrome.png)
|
||||
content/browser/loop/sdk-content/images/rtc/audioonly-publisher.png (content/shared/libs/sdk-content/images/rtc/audioonly-publisher.png)
|
||||
content/browser/loop/sdk-content/images/rtc/audioonly-subscriber.png (content/shared/libs/sdk-content/images/rtc/audioonly-subscriber.png)
|
||||
content/browser/loop/sdk-content/images/rtc/buttons.png (content/shared/libs/sdk-content/images/rtc/buttons.png)
|
||||
content/browser/loop/sdk-content/images/rtc/loader.gif (content/shared/libs/sdk-content/images/rtc/loader.gif)
|
||||
content/browser/loop/sdk-content/images/rtc/mic-off.png (content/shared/libs/sdk-content/images/rtc/mic-off.png)
|
||||
content/browser/loop/sdk-content/images/rtc/mic-on.png (content/shared/libs/sdk-content/images/rtc/mic-on.png)
|
||||
content/browser/loop/sdk-content/images/rtc/speaker-off.png (content/shared/libs/sdk-content/images/rtc/speaker-off.png)
|
||||
content/browser/loop/sdk-content/images/rtc/speaker-on.png (content/shared/libs/sdk-content/images/rtc/speaker-on.png)
|
||||
|
@ -6,15 +6,13 @@
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
JS_MODULES_PATH = 'modules/loop'
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/mochitest/browser.ini',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.loop += [
|
||||
'MozLoopAPI.jsm',
|
||||
'MozLoopPushHandler.jsm',
|
||||
'MozLoopService.jsm',
|
||||
|
@ -1,2 +1,5 @@
|
||||
.module-cache
|
||||
node_modules
|
||||
*.pyc
|
||||
content/config.js
|
||||
content/VERSION.txt
|
||||
|
@ -21,6 +21,21 @@ runserver: config
|
||||
frontend:
|
||||
@echo "Not implemented yet."
|
||||
|
||||
# Try hg first, if not fall back to git.
|
||||
SOURCE_STAMP := $(shell hg parent --template '{node|short}\n' 2> /dev/null)
|
||||
ifndef SOURCE_STAMP
|
||||
SOURCE_STAMP := $(shell git describe --always --tag)
|
||||
endif
|
||||
|
||||
SOURCE_DATE := $(shell hg parent --template '{date|date}\n' 2> /dev/null)
|
||||
ifndef SOURCE_DATE
|
||||
SOURCE_DATE := $(shell git log -1 --format="%H%n%aD")
|
||||
endif
|
||||
|
||||
version:
|
||||
@echo $(SOURCE_STAMP) > content/VERSION.txt
|
||||
@echo $(SOURCE_DATE) >> content/VERSION.txt
|
||||
|
||||
config:
|
||||
@echo "var loop = loop || {};" > content/config.js
|
||||
@echo "loop.config = loop.config || {};" >> content/config.js
|
||||
|
@ -22,7 +22,15 @@
|
||||
<div id="main"></div>
|
||||
|
||||
<!-- libs -->
|
||||
<script src="https://static.opentok.com/webrtc/v2.2/js/opentok.min.js"></script>
|
||||
<script>
|
||||
window.OTProperties = {
|
||||
cdnURL: 'shared/libs/',
|
||||
};
|
||||
window.OTProperties.assetURL = window.OTProperties.cdnURL + 'sdk-content/';
|
||||
window.OTProperties.configURL = window.OTProperties.assetURL + 'js/dynamic_config.min.js';
|
||||
window.OTProperties.cssURL = window.OTProperties.assetURL + 'css/ot.css';
|
||||
</script>
|
||||
<script type="text/javascript" src="shared/libs/sdk.js"></script>
|
||||
<script type="text/javascript" src="libs/webl10n-20130617.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/react-0.10.0.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/jquery-2.1.0.js"></script>
|
||||
|
@ -22,9 +22,7 @@ EXTRA_COMPONENTS += [
|
||||
'nsSessionStore.manifest',
|
||||
]
|
||||
|
||||
JS_MODULES_PATH = 'modules/sessionstore'
|
||||
|
||||
EXTRA_JS_MODULES = [
|
||||
EXTRA_JS_MODULES.sessionstore = [
|
||||
'ContentRestore.jsm',
|
||||
'DocShellCapabilities.jsm',
|
||||
'FrameTree.jsm',
|
||||
@ -46,7 +44,7 @@ EXTRA_JS_MODULES = [
|
||||
'Utils.jsm',
|
||||
]
|
||||
|
||||
EXTRA_PP_JS_MODULES += [
|
||||
EXTRA_PP_JS_MODULES.sessionstore += [
|
||||
'SessionSaver.jsm',
|
||||
'SessionStore.jsm',
|
||||
]
|
||||
|
@ -4,9 +4,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/.
|
||||
|
||||
EXTRA_JS_MODULES = ['modules/utils.jsm']
|
||||
JS_MODULES_PATH = 'modules/tabview'
|
||||
|
||||
EXTRA_JS_MODULES.tabview = ['modules/utils.jsm']
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'test/browser.ini',
|
||||
]
|
||||
|
@ -2,9 +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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/translation'
|
||||
|
||||
EXTRA_JS_MODULES = [
|
||||
EXTRA_JS_MODULES.translation = [
|
||||
'BingTranslator.jsm',
|
||||
'cld2/cld-worker.js',
|
||||
'cld2/cld-worker.js.mem',
|
||||
|
@ -7,9 +7,7 @@
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/app-manager'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools["app-manager"] += [
|
||||
'app-projects.js',
|
||||
'app-validator.js',
|
||||
'builtin-adb-store.js',
|
||||
|
@ -3,9 +3,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/canvasdebugger'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.canvasdebugger += [
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
@ -2,9 +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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/commandline'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.commandline += [
|
||||
'commands-index.js'
|
||||
]
|
||||
|
||||
|
@ -3,9 +3,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/debugger'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.debugger += [
|
||||
'debugger-commands.js',
|
||||
'panel.js'
|
||||
]
|
||||
|
@ -4,9 +4,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/eyedropper'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.eyedropper += [
|
||||
'commands.js',
|
||||
'eyedropper.js'
|
||||
]
|
||||
|
@ -2,9 +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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/inspector'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.inspector += [
|
||||
'breadcrumbs.js',
|
||||
'inspector-commands.js',
|
||||
'inspector-panel.js',
|
||||
|
@ -6,9 +6,7 @@
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/markupview'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.markupview += [
|
||||
'html-editor.js',
|
||||
'markup-view.js',
|
||||
]
|
||||
|
@ -38,8 +38,6 @@ EXTRA_COMPONENTS += [
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools += [
|
||||
'main.js',
|
||||
]
|
||||
|
@ -3,9 +3,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/netmonitor'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.netmonitor += [
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
@ -6,9 +6,7 @@
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/profiler'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.profiler += [
|
||||
'cleopatra.js',
|
||||
'commands.js',
|
||||
'consts.js',
|
||||
|
@ -2,9 +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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools += [
|
||||
'resize-commands.js'
|
||||
]
|
||||
|
||||
|
@ -4,9 +4,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/scratchpad'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.scratchpad += [
|
||||
'scratchpad-commands.js',
|
||||
'scratchpad-panel.js'
|
||||
]
|
||||
|
@ -3,9 +3,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/shadereditor'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.shadereditor += [
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
@ -4,9 +4,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/sourceeditor'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.sourceeditor += [
|
||||
'autocomplete.js',
|
||||
'css-autocompleter.js',
|
||||
'css-tokenizer.js',
|
||||
|
@ -7,9 +7,7 @@
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/styleinspector'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.styleinspector += [
|
||||
'computed-view.js',
|
||||
'css-parsing-utils.js',
|
||||
'rule-view.js',
|
||||
|
@ -2,9 +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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/tilt'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.tilt += [
|
||||
'tilt-commands.js',
|
||||
'tilt-gl.js',
|
||||
'tilt-math.js',
|
||||
|
@ -3,9 +3,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/.
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/webaudioeditor'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.webaudioeditor += [
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
|
@ -6,9 +6,7 @@
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/webconsole'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.webconsole += [
|
||||
'console-commands.js',
|
||||
'console-output.js',
|
||||
'hudservice.js',
|
||||
|
@ -83,19 +83,19 @@ function updateUI() {
|
||||
document.querySelector("#type").classList.remove("hidden");
|
||||
|
||||
if (project.type == "runtimeApp") {
|
||||
let manifest = AppManager.getProjectManifestURL(project);
|
||||
let manifestURL = AppManager.getProjectManifestURL(project);
|
||||
document.querySelector("#type").textContent = manifest.type || "web";
|
||||
document.querySelector("#manifestURLHeader").classList.remove("hidden");
|
||||
document.querySelector("#manifestURL").textContent = manifest;
|
||||
document.querySelector("#manifestURL").textContent = manifestURL;
|
||||
} else {
|
||||
document.querySelector("#type").textContent = project.type + " " + (manifest.type || "web");
|
||||
}
|
||||
|
||||
if (project.type == "packaged") {
|
||||
let manifest = AppManager.getProjectManifestURL(project);
|
||||
if (manifest) {
|
||||
let manifestURL = AppManager.getProjectManifestURL(project);
|
||||
if (manifestURL) {
|
||||
document.querySelector("#manifestURLHeader").classList.remove("hidden");
|
||||
document.querySelector("#manifestURL").textContent = manifest;
|
||||
document.querySelector("#manifestURL").textContent = manifestURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,16 @@
|
||||
<h2>&prefs_editor_title;</h2>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label><span>&prefs_options_keybindings;</span>
|
||||
<select data-pref="devtools.editor.keymap">
|
||||
<option value="default">&prefs_options_keybindings_default;</option>
|
||||
<option value="vim">Vim</option>
|
||||
<option value="emacs">Emacs</option>
|
||||
<option value="sublime">Sublime</option>
|
||||
</select>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><span>&prefs_options_tabsize;</span>
|
||||
<select data-pref="devtools.editor.tabsize">
|
||||
|
@ -632,7 +632,7 @@ let UI = {
|
||||
splitter.removeAttribute("hidden");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
document.querySelector("window").insertBefore(iframe, splitter.nextSibling);
|
||||
document.querySelector("notificationbox").insertBefore(iframe, splitter.nextSibling);
|
||||
let host = devtools.Toolbox.HostType.CUSTOM;
|
||||
let options = { customIframe: iframe };
|
||||
this.toolboxIframe = iframe;
|
||||
|
@ -181,10 +181,9 @@
|
||||
<iframe id="deck-panel-runtimedetails" flex="1" src="runtimedetails.xhtml"/>
|
||||
<iframe id="deck-panel-monitor" flex="1" lazysrc="monitor.xhtml"/>
|
||||
</deck>
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
</notificationbox>
|
||||
|
||||
<splitter hidden="true" class="devtools-horizontal-splitter" orient="vertical"/>
|
||||
|
||||
<!-- toolbox iframe will be inserted here -->
|
||||
|
||||
</window>
|
||||
|
@ -117,6 +117,8 @@
|
||||
<!ENTITY prefs_options_autocomplete_tooltip "Enable code autocompletion">
|
||||
<!ENTITY prefs_options_autoclosebrackets "Autoclose brackets">
|
||||
<!ENTITY prefs_options_autoclosebrackets_tooltip "Automatically insert closing brackets">
|
||||
<!ENTITY prefs_options_keybindings "Keybindings">
|
||||
<!ENTITY prefs_options_keybindings_default "Default">
|
||||
|
||||
<!-- Permissions Table -->
|
||||
<!ENTITY permissionstable_title "Permissions Table">
|
||||
|
@ -12,9 +12,7 @@ DIRS += [
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/webide'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.devtools.webide += [
|
||||
'modules/addons.js',
|
||||
'modules/app-manager.js',
|
||||
'modules/remote-resources.js',
|
||||
|
@ -7,9 +7,7 @@ EXTRA_COMPONENTS += [
|
||||
'ExperimentsService.js',
|
||||
]
|
||||
|
||||
JS_MODULES_PATH = 'modules/experiments'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.experiments += [
|
||||
'Experiments.jsm',
|
||||
]
|
||||
|
||||
|
@ -451,6 +451,7 @@
|
||||
@BINPATH@/components/nsInputListAutoComplete.js
|
||||
@BINPATH@/components/formautofill.manifest
|
||||
@BINPATH@/components/FormAutofillContentService.js
|
||||
@BINPATH@/components/FormAutofillStartup.js
|
||||
@BINPATH@/components/contentSecurityPolicy.manifest
|
||||
@BINPATH@/components/contentSecurityPolicy.js
|
||||
@BINPATH@/components/contentAreaDropListener.manifest
|
||||
|
@ -715,8 +715,6 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
||||
<!ENTITY getUserMedia.selectMicrophone.accesskey "M">
|
||||
<!ENTITY getUserMedia.allWindowsShared.message "All visible windows on your screen will be shared.">
|
||||
|
||||
<!ENTITY loopCallButton.tooltip "Invite someone to talk">
|
||||
|
||||
<!ENTITY mixedContentBlocked.moreinfo "Most websites will still work properly even when this content is blocked.">
|
||||
|
||||
<!ENTITY pointerLock.notification.message "Press ESC at any time to show it again.">
|
||||
|
@ -96,3 +96,6 @@ quit-button.tooltiptext.linux2 = Quit %1$S (%2$S)
|
||||
# LOCALIZATION NOTE(quit-button.tooltiptext.mac): %1$S is the brand name (e.g. Firefox),
|
||||
# %2$S is the keyboard shortcut
|
||||
quit-button.tooltiptext.mac = Quit %1$S (%2$S)
|
||||
|
||||
loop-call-button.label = Invite someone to talk
|
||||
loop-call-button.tooltiptext = Invite someone to talk
|
||||
|
@ -77,6 +77,18 @@ DEBUGGER_INFO = {
|
||||
"requiresEscapedArgs": True
|
||||
},
|
||||
|
||||
# Visual Studio Debugger Support
|
||||
"devenv.exe": {
|
||||
"interactive": True,
|
||||
"args": "-debugexe"
|
||||
},
|
||||
|
||||
# Visual C++ Express Debugger Support
|
||||
"wdexpress.exe": {
|
||||
"interactive": True,
|
||||
"args": "-debugexe"
|
||||
},
|
||||
|
||||
# valgrind doesn't explain much about leaks unless you set the
|
||||
# '--leak-check=full' flag. But there are a lot of objects that are
|
||||
# semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
|
||||
|
@ -55,7 +55,6 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
|
||||
IS_COMPONENT \
|
||||
JAR_MANIFEST \
|
||||
JAVA_JAR_TARGETS \
|
||||
JS_MODULES_PATH \
|
||||
LD_VERSION_SCRIPT \
|
||||
LIBRARY_NAME \
|
||||
LIBS \
|
||||
|
@ -1221,10 +1221,8 @@ endif
|
||||
|
||||
################################################################################
|
||||
# Copy each element of EXTRA_JS_MODULES to
|
||||
# $(FINAL_TARGET)/$(JS_MODULES_PATH). JS_MODULES_PATH defaults to "modules"
|
||||
# if it is undefined.
|
||||
JS_MODULES_PATH ?= modules
|
||||
FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/$(JS_MODULES_PATH)
|
||||
# $(FINAL_TARGET)/modules.
|
||||
FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/modules
|
||||
|
||||
ifdef EXTRA_JS_MODULES
|
||||
ifndef NO_DIST_INSTALL
|
||||
|
59
configure.in
@ -3844,7 +3844,6 @@ MOZ_PAY=
|
||||
MOZ_AUDIO_CHANNEL_MANAGER=
|
||||
NSS_NO_LIBPKIX=
|
||||
MOZ_CONTENT_SANDBOX=
|
||||
MOZ_GMP_SANDBOX=
|
||||
JSGC_USE_EXACT_ROOTING=1
|
||||
JSGC_GENERATIONAL=
|
||||
|
||||
@ -5083,6 +5082,20 @@ if test -n "$MOZ_WEBM"; then
|
||||
MOZ_VPX=1
|
||||
fi;
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Apple platform decoder support
|
||||
dnl ========================================================
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
|
||||
MOZ_APPLEMEDIA=1
|
||||
fi
|
||||
|
||||
if test -n "$MOZ_APPLEMEDIA"; then
|
||||
AC_DEFINE(MOZ_APPLEMEDIA)
|
||||
# hack in frameworks for fmp4 - see bug 1029974
|
||||
# We load VideoToolbox and CoreMedia dynamically, so they don't appear here.
|
||||
LDFLAGS="$LDFLAGS -framework AudioToolbox"
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = DirectShow support
|
||||
dnl ========================================================
|
||||
@ -5143,10 +5156,8 @@ fi;
|
||||
dnl ========================================================
|
||||
dnl = Built-in fragmented MP4 support.
|
||||
dnl ========================================================
|
||||
if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG"; then
|
||||
dnl Enable fragmented MP4 parser on Windows by default.
|
||||
dnl We will also need to enable it on other platforms as we implement
|
||||
dnl platform decoder support there too.
|
||||
if test -n "$MOZ_WMF" -o -n "$MOZ_FFMPEG" -o -n "$MOZ_APPLEMEDIA"; then
|
||||
dnl Enable fragmented MP4 parser on platforms with decoder support.
|
||||
MOZ_FMP4=1
|
||||
fi
|
||||
|
||||
@ -5189,22 +5200,6 @@ if test -n "$MOZ_ANDROID_OMX"; then
|
||||
AC_DEFINE(MOZ_ANDROID_OMX)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Disable platform MP3 decoder on OSX
|
||||
dnl ========================================================
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "cocoa"; then
|
||||
MOZ_APPLEMEDIA=1
|
||||
fi
|
||||
|
||||
MOZ_ARG_DISABLE_BOOL(apple-media,
|
||||
[ --disable-apple-media Disable support for Apple AudioToolbox/VideoToolbox],
|
||||
MOZ_APPLEMEDIA=,
|
||||
MOZ_APPLEMEDIA=1)
|
||||
|
||||
if test -n "$MOZ_APPLEMEDIA"; then
|
||||
AC_DEFINE(MOZ_APPLEMEDIA)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable getUserMedia support
|
||||
dnl ========================================================
|
||||
@ -6406,28 +6401,6 @@ fi
|
||||
|
||||
AC_SUBST(MOZ_CONTENT_SANDBOX)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Gecko Media Plugin sandboxing
|
||||
dnl ========================================================
|
||||
case $OS_TARGET in
|
||||
WINNT)
|
||||
MOZ_GMP_SANDBOX=1
|
||||
;;
|
||||
Linux)
|
||||
case $CPU_ARCH in
|
||||
x86_64|x86)
|
||||
MOZ_GMP_SANDBOX=1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
if test -n "$MOZ_GMP_SANDBOX"; then
|
||||
AC_DEFINE(MOZ_GMP_SANDBOX)
|
||||
fi
|
||||
|
||||
AC_SUBST(MOZ_GMP_SANDBOX)
|
||||
|
||||
dnl ========================================================
|
||||
dnl =
|
||||
dnl = Module specific options
|
||||
|
@ -748,16 +748,6 @@ private:
|
||||
} // dom namespace
|
||||
} // file namespace
|
||||
|
||||
class MOZ_STACK_CLASS nsDOMFileInternalUrlHolder {
|
||||
public:
|
||||
nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile, nsIPrincipal* aPrincipal
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
~nsDOMFileInternalUrlHolder();
|
||||
nsAutoString mUrl;
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class nsDOMFileList MOZ_FINAL : public nsIDOMFileList,
|
||||
public nsWrapperCache
|
||||
{
|
||||
|
@ -1064,21 +1064,3 @@ nsDOMFileList::Item(uint32_t aIndex, nsIDOMFile **aFile)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// nsDOMFileInternalUrlHolder implementation
|
||||
|
||||
nsDOMFileInternalUrlHolder::nsDOMFileInternalUrlHolder(nsIDOMBlob* aFile,
|
||||
nsIPrincipal* aPrincipal
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
aFile->GetInternalUrl(aPrincipal, mUrl);
|
||||
}
|
||||
|
||||
nsDOMFileInternalUrlHolder::~nsDOMFileInternalUrlHolder() {
|
||||
if (!mUrl.IsEmpty()) {
|
||||
nsAutoCString narrowUrl;
|
||||
CopyUTF16toUTF8(mUrl, narrowUrl);
|
||||
nsBlobProtocolHandler::RemoveDataEntry(narrowUrl);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,10 @@
|
||||
#ifdef MOZ_FFMPEG
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
#include "apple/AppleCMLinker.h"
|
||||
#include "apple/AppleVTLinker.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -102,6 +106,31 @@ IsFFmpegAvailable()
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
IsAppleAvailable()
|
||||
{
|
||||
#ifndef MOZ_APPLEMEDIA
|
||||
// Not the right platform.
|
||||
return false;
|
||||
#else
|
||||
if (!Preferences::GetBool("media.apple.mp4.enabled", false)) {
|
||||
// Disabled by preference.
|
||||
return false;
|
||||
}
|
||||
// Attempt to load the required frameworks.
|
||||
bool haveCoreMedia = AppleCMLinker::Link();
|
||||
if (!haveCoreMedia) {
|
||||
return false;
|
||||
}
|
||||
bool haveVideoToolbox = AppleVTLinker::Link();
|
||||
if (!haveVideoToolbox) {
|
||||
return false;
|
||||
}
|
||||
// All hurdles cleared!
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
HavePlatformMPEGDecoders()
|
||||
{
|
||||
@ -111,6 +140,7 @@ HavePlatformMPEGDecoders()
|
||||
IsVistaOrLater() ||
|
||||
#endif
|
||||
IsFFmpegAvailable() ||
|
||||
IsAppleAvailable() ||
|
||||
// TODO: Other platforms...
|
||||
false;
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
#ifdef MOZ_FFMPEG
|
||||
#include "FFmpegRuntimeLinker.h"
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
#include "AppleDecoderModule.h"
|
||||
#endif
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "EMEDecoderModule.h"
|
||||
#include "mozilla/CDMProxy.h"
|
||||
@ -42,6 +45,9 @@ PlatformDecoderModule::Init()
|
||||
#ifdef XP_WIN
|
||||
WMFDecoderModule::Init();
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
AppleDecoderModule::Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
class CreateTaskQueueTask : public nsRunnable {
|
||||
@ -116,6 +122,12 @@ PlatformDecoderModule::Create()
|
||||
if (sFFmpegDecoderEnabled) {
|
||||
return FFmpegRuntimeLinker::CreateDecoderModule();
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
nsAutoPtr<AppleDecoderModule> m(new AppleDecoderModule());
|
||||
if (NS_SUCCEEDED(m->Startup())) {
|
||||
return m.forget();
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
354
content/media/fmp4/apple/AppleATDecoder.cpp
Normal file
@ -0,0 +1,354 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <AudioToolbox/AudioToolbox.h>
|
||||
#include "AppleUtils.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mp4_demuxer/DecoderData.h"
|
||||
#include "nsIThread.h"
|
||||
#include "AppleATDecoder.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||
MediaTaskQueue* anAudioTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback)
|
||||
: mConfig(aConfig)
|
||||
, mTaskQueue(anAudioTaskQueue)
|
||||
, mCallback(aCallback)
|
||||
, mConverter(nullptr)
|
||||
, mStream(nullptr)
|
||||
, mCurrentAudioFrame(0)
|
||||
, mSamplePosition(0)
|
||||
, mHaveOutput(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AppleATDecoder);
|
||||
LOG("Creating Apple AudioToolbox AAC decoder");
|
||||
LOG("Audio Decoder configuration: %s %d Hz %d channels %d bits per channel",
|
||||
mConfig.mime_type,
|
||||
mConfig.samples_per_second,
|
||||
mConfig.channel_count,
|
||||
mConfig.bits_per_sample);
|
||||
// TODO: Verify aConfig.mime_type.
|
||||
}
|
||||
|
||||
AppleATDecoder::~AppleATDecoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(AppleATDecoer);
|
||||
MOZ_ASSERT(!mConverter);
|
||||
MOZ_ASSERT(!mStream);
|
||||
}
|
||||
|
||||
static void
|
||||
_MetadataCallback(void *aDecoder,
|
||||
AudioFileStreamID aStream,
|
||||
AudioFileStreamPropertyID aProperty,
|
||||
UInt32 *aFlags)
|
||||
{
|
||||
LOG("AppleATDecoder metadata callback");
|
||||
AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aDecoder);
|
||||
decoder->MetadataCallback(aStream, aProperty, aFlags);
|
||||
}
|
||||
|
||||
static void
|
||||
_SampleCallback(void *aDecoder,
|
||||
UInt32 aNumBytes, UInt32 aNumPackets,
|
||||
const void *aData,
|
||||
AudioStreamPacketDescription *aPackets)
|
||||
{
|
||||
LOG("AppleATDecoder sample callback %u bytes %u packets",
|
||||
aNumBytes, aNumPackets);
|
||||
AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aDecoder);
|
||||
decoder->SampleCallback(aNumBytes, aNumPackets, aData, aPackets);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleATDecoder::Init()
|
||||
{
|
||||
LOG("Initializing Apple AudioToolbox AAC decoder");
|
||||
AudioFileTypeID fileType = kAudioFileAAC_ADTSType;
|
||||
OSStatus rv = AudioFileStreamOpen(this,
|
||||
_MetadataCallback,
|
||||
_SampleCallback,
|
||||
fileType,
|
||||
&mStream);
|
||||
if (rv) {
|
||||
NS_ERROR("Couldn't open AudioFileStream");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleATDecoder::Input(mp4_demuxer::MP4Sample* aSample)
|
||||
{
|
||||
LOG("mp4 input sample %p %lld us %lld pts%s %llu bytes audio",
|
||||
aSample,
|
||||
aSample->duration,
|
||||
aSample->composition_timestamp,
|
||||
aSample->is_sync_point ? " keyframe" : "",
|
||||
(unsigned long long)aSample->size);
|
||||
|
||||
// Queue a task to perform the actual decoding on a separate thread.
|
||||
mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
|
||||
this,
|
||||
&AppleATDecoder::SubmitSample,
|
||||
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleATDecoder::Flush()
|
||||
{
|
||||
LOG("Flushing AudioToolbox AAC decoder");
|
||||
OSStatus rv = AudioConverterReset(mConverter);
|
||||
if (rv) {
|
||||
LOG("Error %d resetting AudioConverter", rv);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleATDecoder::Drain()
|
||||
{
|
||||
LOG("Draining AudioToolbox AAC decoder");
|
||||
mTaskQueue->AwaitIdle();
|
||||
return Flush();
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleATDecoder::Shutdown()
|
||||
{
|
||||
LOG("Shutdown: Apple AudioToolbox AAC decoder");
|
||||
OSStatus rv1 = AudioConverterDispose(mConverter);
|
||||
if (rv1) {
|
||||
LOG("error %d disposing of AudioConverter", rv1);
|
||||
} else {
|
||||
mConverter = nullptr;
|
||||
}
|
||||
|
||||
OSStatus rv2 = AudioFileStreamClose(mStream);
|
||||
if (rv2) {
|
||||
LOG("error %d closing AudioFileStream", rv2);
|
||||
} else {
|
||||
mStream = nullptr;
|
||||
}
|
||||
|
||||
return (rv1 && rv2) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
AppleATDecoder::MetadataCallback(AudioFileStreamID aFileStream,
|
||||
AudioFileStreamPropertyID aPropertyID,
|
||||
UInt32* aFlags)
|
||||
{
|
||||
if (aPropertyID == kAudioFileStreamProperty_ReadyToProducePackets) {
|
||||
SetupDecoder();
|
||||
}
|
||||
}
|
||||
|
||||
struct PassthroughUserData {
|
||||
AppleATDecoder* mDecoder;
|
||||
UInt32 mNumPackets;
|
||||
UInt32 mDataSize;
|
||||
const void *mData;
|
||||
AudioStreamPacketDescription *mPacketDesc;
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
// Error value we pass through the decoder to signal that nothing
|
||||
// has gone wrong during decoding, but more data is needed.
|
||||
const uint32_t kNeedMoreData = 'MOAR';
|
||||
|
||||
static OSStatus
|
||||
_PassthroughInputDataCallback(AudioConverterRef aAudioConverter,
|
||||
UInt32 *aNumDataPackets /* in/out */,
|
||||
AudioBufferList *aData /* in/out */,
|
||||
AudioStreamPacketDescription **aPacketDesc,
|
||||
void *aUserData)
|
||||
{
|
||||
PassthroughUserData *userData = (PassthroughUserData *)aUserData;
|
||||
if (userData->mDone) {
|
||||
// We make sure this callback is run _once_, with all the data we received
|
||||
// from |AudioFileStreamParseBytes|. When we return an error, the decoder
|
||||
// simply passes the return value on to the calling method,
|
||||
// |SampleCallback|; and flushes all of the audio frames it had
|
||||
// buffered. It does not change the decoder's state.
|
||||
LOG("requested too much data; returning\n");
|
||||
*aNumDataPackets = 0;
|
||||
return kNeedMoreData;
|
||||
}
|
||||
|
||||
userData->mDone = true;
|
||||
|
||||
LOG("AudioConverter wants %u packets of audio data\n", *aNumDataPackets);
|
||||
|
||||
*aNumDataPackets = userData->mNumPackets;
|
||||
*aPacketDesc = userData->mPacketDesc;
|
||||
|
||||
aData->mBuffers[0].mNumberChannels = userData->mDecoder->mConfig.channel_count;
|
||||
aData->mBuffers[0].mDataByteSize = userData->mDataSize;
|
||||
aData->mBuffers[0].mData = const_cast<void *>(userData->mData);
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
void
|
||||
AppleATDecoder::SampleCallback(uint32_t aNumBytes,
|
||||
uint32_t aNumPackets,
|
||||
const void* aData,
|
||||
AudioStreamPacketDescription* aPackets)
|
||||
{
|
||||
// Pick a multiple of the frame size close to a power of two
|
||||
// for efficient allocation.
|
||||
const uint32_t MAX_AUDIO_FRAMES = 128;
|
||||
const uint32_t decodedSize = MAX_AUDIO_FRAMES * mConfig.channel_count *
|
||||
sizeof(AudioDataValue);
|
||||
|
||||
// Descriptions for _decompressed_ audio packets. ignored.
|
||||
nsAutoArrayPtr<AudioStreamPacketDescription>
|
||||
packets(new AudioStreamPacketDescription[MAX_AUDIO_FRAMES]);
|
||||
|
||||
// This API insists on having packets spoon-fed to it from a callback.
|
||||
// This structure exists only to pass our state and the result of the
|
||||
// parser on to the callback above.
|
||||
PassthroughUserData userData =
|
||||
{ this, aNumPackets, aNumBytes, aData, aPackets, false };
|
||||
|
||||
do {
|
||||
// Decompressed audio buffer
|
||||
nsAutoArrayPtr<uint8_t> decoded(new uint8_t[decodedSize]);
|
||||
|
||||
AudioBufferList decBuffer;
|
||||
decBuffer.mNumberBuffers = 1;
|
||||
decBuffer.mBuffers[0].mNumberChannels = mConfig.channel_count;
|
||||
decBuffer.mBuffers[0].mDataByteSize = decodedSize;
|
||||
decBuffer.mBuffers[0].mData = decoded.get();
|
||||
|
||||
// in: the max number of packets we can handle from the decoder.
|
||||
// out: the number of packets the decoder is actually returning.
|
||||
UInt32 numFrames = MAX_AUDIO_FRAMES;
|
||||
|
||||
OSStatus rv = AudioConverterFillComplexBuffer(mConverter,
|
||||
_PassthroughInputDataCallback,
|
||||
&userData,
|
||||
&numFrames /* in/out */,
|
||||
&decBuffer,
|
||||
packets.get());
|
||||
|
||||
if (rv && rv != kNeedMoreData) {
|
||||
LOG("Error decoding audio stream: %#x\n", rv);
|
||||
mCallback->Error();
|
||||
break;
|
||||
}
|
||||
LOG("%d frames decoded", numFrames);
|
||||
|
||||
// If we decoded zero frames then AudioConverterFillComplexBuffer is out
|
||||
// of data to provide. We drained its internal buffer completely on the
|
||||
// last pass.
|
||||
if (numFrames == 0 && rv == kNeedMoreData) {
|
||||
LOG("FillComplexBuffer out of data exactly\n");
|
||||
mCallback->InputExhausted();
|
||||
break;
|
||||
}
|
||||
|
||||
const int rate = mConfig.samples_per_second;
|
||||
int64_t time = FramesToUsecs(mCurrentAudioFrame, rate).value();
|
||||
int64_t duration = FramesToUsecs(numFrames, rate).value();
|
||||
|
||||
LOG("pushed audio at time %lfs; duration %lfs\n",
|
||||
(double)time / USECS_PER_S, (double)duration / USECS_PER_S);
|
||||
|
||||
AudioData *audio = new AudioData(mSamplePosition,
|
||||
time, duration, numFrames,
|
||||
reinterpret_cast<AudioDataValue *>(decoded.forget()),
|
||||
rate);
|
||||
mCallback->Output(audio);
|
||||
mHaveOutput = true;
|
||||
|
||||
mCurrentAudioFrame += numFrames;
|
||||
|
||||
if (rv == kNeedMoreData) {
|
||||
// No error; we just need more data.
|
||||
LOG("FillComplexBuffer out of data\n");
|
||||
mCallback->InputExhausted();
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void
|
||||
AppleATDecoder::SetupDecoder()
|
||||
{
|
||||
AudioStreamBasicDescription inputFormat, outputFormat;
|
||||
// Fill in the input format description from the stream.
|
||||
AppleUtils::GetProperty(mStream,
|
||||
kAudioFileStreamProperty_DataFormat, &inputFormat);
|
||||
|
||||
// Fill in the output format manually.
|
||||
PodZero(&outputFormat);
|
||||
outputFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
outputFormat.mSampleRate = inputFormat.mSampleRate;
|
||||
outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
|
||||
#if defined(MOZ_SAMPLE_TYPE_FLOAT32)
|
||||
outputFormat.mBitsPerChannel = 32;
|
||||
outputFormat.mFormatFlags =
|
||||
kLinearPCMFormatFlagIsFloat |
|
||||
0;
|
||||
#else
|
||||
# error Unknown audio sample type
|
||||
#endif
|
||||
// Set up the decoder so it gives us one sample per frame
|
||||
outputFormat.mFramesPerPacket = 1;
|
||||
outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame
|
||||
= outputFormat.mChannelsPerFrame * outputFormat.mBitsPerChannel / 8;
|
||||
|
||||
OSStatus rv = AudioConverterNew(&inputFormat, &outputFormat, &mConverter);
|
||||
if (rv) {
|
||||
LOG("Error %d constructing AudioConverter", rv);
|
||||
mConverter = nullptr;
|
||||
mCallback->Error();
|
||||
}
|
||||
mHaveOutput = false;
|
||||
}
|
||||
|
||||
void
|
||||
AppleATDecoder::SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample)
|
||||
{
|
||||
mSamplePosition = aSample->byte_offset;
|
||||
OSStatus rv = AudioFileStreamParseBytes(mStream,
|
||||
aSample->size,
|
||||
aSample->data,
|
||||
0);
|
||||
if (rv != noErr) {
|
||||
LOG("Error %d parsing audio data", rv);
|
||||
mCallback->Error();
|
||||
}
|
||||
|
||||
// Sometimes we need multiple input samples before AudioToolbox
|
||||
// starts decoding. If we haven't seen any output yet, ask for
|
||||
// more data here.
|
||||
if (!mHaveOutput) {
|
||||
mCallback->InputExhausted();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
62
content/media/fmp4/apple/AppleATDecoder.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 mozilla_AppleATDecoder_h
|
||||
#define mozilla_AppleATDecoder_h
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsIThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaTaskQueue;
|
||||
class MediaDataDecoderCallback;
|
||||
|
||||
class AppleATDecoder : public MediaDataDecoder {
|
||||
public:
|
||||
AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||
MediaTaskQueue* aVideoTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback);
|
||||
~AppleATDecoder();
|
||||
|
||||
virtual nsresult Init() MOZ_OVERRIDE;
|
||||
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
|
||||
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||
|
||||
|
||||
// Internal callbacks for the platform C api. Don't call externally.
|
||||
void MetadataCallback(AudioFileStreamID aFileStream,
|
||||
AudioFileStreamPropertyID aPropertyID,
|
||||
UInt32* aFlags);
|
||||
void SampleCallback(uint32_t aNumBytes,
|
||||
uint32_t aNumPackets,
|
||||
const void* aData,
|
||||
AudioStreamPacketDescription* aPackets);
|
||||
|
||||
// Callbacks also need access to the config.
|
||||
const mp4_demuxer::AudioDecoderConfig& mConfig;
|
||||
|
||||
private:
|
||||
RefPtr<MediaTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
AudioConverterRef mConverter;
|
||||
AudioFileStreamID mStream;
|
||||
uint64_t mCurrentAudioFrame;
|
||||
int64_t mSamplePosition;
|
||||
bool mHaveOutput;
|
||||
|
||||
void SetupDecoder();
|
||||
void SubmitSample(nsAutoPtr<mp4_demuxer::MP4Sample> aSample);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AppleATDecoder_h
|
12
content/media/fmp4/apple/AppleCMFunctions.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
// Construct references to each of the CoreMedia symbols we use.
|
||||
|
||||
LINK_FUNC(CMVideoFormatDescriptionCreate)
|
||||
LINK_FUNC(CMBlockBufferCreateWithMemoryBlock)
|
||||
LINK_FUNC(CMSampleBufferCreate)
|
||||
LINK_FUNC(CMTimeMake)
|
85
content/media/fmp4/apple/AppleCMLinker.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <dlfcn.h>
|
||||
|
||||
#include "AppleCMLinker.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
AppleCMLinker::LinkStatus
|
||||
AppleCMLinker::sLinkStatus = LinkStatus_INIT;
|
||||
|
||||
void* AppleCMLinker::sLink = nullptr;
|
||||
nsrefcnt AppleCMLinker::sRefCount = 0;
|
||||
|
||||
#define LINK_FUNC(func) typeof(func) func;
|
||||
#include "AppleCMFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
/* static */ bool
|
||||
AppleCMLinker::Link()
|
||||
{
|
||||
// Bump our reference count every time we're called.
|
||||
// Add a lock or change the thread assertion if
|
||||
// you need to call this off the main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
++sRefCount;
|
||||
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
}
|
||||
|
||||
const char* dlname =
|
||||
"/System/Library/Frameworks/CoreMedia.framework/CoreMedia";
|
||||
if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
|
||||
NS_WARNING("Couldn't load CoreMedia framework");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#define LINK_FUNC(func) \
|
||||
func = (typeof(func))dlsym(sLink, #func); \
|
||||
if (!func) { \
|
||||
NS_WARNING("Couldn't load CoreMedia function " #func ); \
|
||||
goto fail; \
|
||||
}
|
||||
#include "AppleCMFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
LOG("Loaded CoreMedia framework.");
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
Unlink();
|
||||
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
AppleCMLinker::Unlink()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(sLink && sRefCount > 0, "Unbalanced Unlink()");
|
||||
--sRefCount;
|
||||
if (sLink && sRefCount < 1) {
|
||||
LOG("Unlinking CoreMedia framework.");
|
||||
dlclose(sLink);
|
||||
sLink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
43
content/media/fmp4/apple/AppleCMLinker.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 AppleCMLinker_h
|
||||
#define AppleCMLinker_h
|
||||
|
||||
extern "C" {
|
||||
#pragma GCC visibility push(default)
|
||||
#include <CoreMedia/CoreMedia.h>
|
||||
#pragma GCC visibility pop
|
||||
}
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AppleCMLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
|
||||
private:
|
||||
static void* sLink;
|
||||
static nsrefcnt sRefCount;
|
||||
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
LinkStatus_SUCCEEDED
|
||||
} sLinkStatus;
|
||||
};
|
||||
|
||||
#define LINK_FUNC(func) extern typeof(func)* func;
|
||||
#include "AppleCMFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // AppleCMLinker_h
|
87
content/media/fmp4/apple/AppleDecoderModule.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "AppleATDecoder.h"
|
||||
#include "AppleCMLinker.h"
|
||||
#include "AppleDecoderModule.h"
|
||||
#include "AppleVTDecoder.h"
|
||||
#include "AppleVTLinker.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool AppleDecoderModule::sIsEnabled = false;
|
||||
|
||||
AppleDecoderModule::AppleDecoderModule()
|
||||
{
|
||||
}
|
||||
|
||||
AppleDecoderModule::~AppleDecoderModule()
|
||||
{
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
AppleDecoderModule::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||
sIsEnabled = Preferences::GetBool("media.apple.mp4.enabled", false);
|
||||
if (!sIsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// dlopen CoreMedia.framework if it's available.
|
||||
sIsEnabled = AppleCMLinker::Link();
|
||||
if (!sIsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// dlopen VideoToolbox.framework if it's available.
|
||||
sIsEnabled = AppleVTLinker::Link();
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleDecoderModule::Startup()
|
||||
{
|
||||
// We don't have any per-instance initialization to do.
|
||||
// Check whether ::Init() above succeeded to know if
|
||||
// we're functional.
|
||||
if (!sIsEnabled) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleDecoderModule::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||
AppleVTLinker::Unlink();
|
||||
AppleCMLinker::Unlink();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaDataDecoder*
|
||||
AppleDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
mozilla::layers::LayersBackend aLayersBackend,
|
||||
mozilla::layers::ImageContainer* aImageContainer,
|
||||
MediaTaskQueue* aVideoTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback)
|
||||
{
|
||||
return new AppleVTDecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer);
|
||||
}
|
||||
|
||||
MediaDataDecoder*
|
||||
AppleDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||
MediaTaskQueue* aAudioTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback)
|
||||
{
|
||||
return new AppleATDecoder(aConfig, aAudioTaskQueue, aCallback);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
48
content/media/fmp4/apple/AppleDecoderModule.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 mozilla_AppleDecoderModule_h
|
||||
#define mozilla_AppleDecoderModule_h
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AppleDecoderModule : public PlatformDecoderModule {
|
||||
public:
|
||||
AppleDecoderModule();
|
||||
virtual ~AppleDecoderModule();
|
||||
|
||||
// Perform any per-instance initialization.
|
||||
// Main thread only.
|
||||
nsresult Startup();
|
||||
|
||||
// Called when the decoders have shutdown. Main thread only.
|
||||
// Does this really need to be main thread only????
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||
|
||||
// Decode thread.
|
||||
virtual MediaDataDecoder*
|
||||
CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
mozilla::layers::LayersBackend aLayersBackend,
|
||||
mozilla::layers::ImageContainer* aImageContainer,
|
||||
MediaTaskQueue* aVideoTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
|
||||
|
||||
// Decode thread.
|
||||
virtual MediaDataDecoder* CreateAACDecoder(
|
||||
const mp4_demuxer::AudioDecoderConfig& aConfig,
|
||||
MediaTaskQueue* aAudioTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
|
||||
|
||||
static void Init();
|
||||
private:
|
||||
static bool sIsEnabled;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AppleDecoderModule_h
|
84
content/media/fmp4/apple/AppleUtils.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/* 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/. */
|
||||
|
||||
// Utility functions to help with Apple API calls.
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include "AppleUtils.h"
|
||||
#include "prlog.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define WARN(...) PR_LOG(GetDemuxerLog(), PR_LOG_WARNING, (__VA_ARGS__))
|
||||
#else
|
||||
#define WARN(...)
|
||||
#endif
|
||||
|
||||
#define PROPERTY_ID_FORMAT "%c%c%c%c"
|
||||
#define PROPERTY_ID_PRINT(x) ((x) >> 24), \
|
||||
((x) >> 16) & 0xff, \
|
||||
((x) >> 8) & 0xff, \
|
||||
(x) & 0xff
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
nsresult
|
||||
AppleUtils::GetProperty(AudioFileStreamID aAudioFileStream,
|
||||
AudioFileStreamPropertyID aPropertyID,
|
||||
void *aData)
|
||||
{
|
||||
UInt32 size;
|
||||
Boolean writeable;
|
||||
OSStatus rv = AudioFileStreamGetPropertyInfo(aAudioFileStream, aPropertyID,
|
||||
&size, &writeable);
|
||||
|
||||
if (rv) {
|
||||
WARN("Couldn't get property " PROPERTY_ID_FORMAT "\n",
|
||||
PROPERTY_ID_PRINT(aPropertyID));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = AudioFileStreamGetProperty(aAudioFileStream, aPropertyID,
|
||||
&size, aData);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
const char* value)
|
||||
{
|
||||
// We avoid using the CFSTR macros because there's no way to release those.
|
||||
AutoCFRelease<CFStringRef> keyRef =
|
||||
CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
|
||||
AutoCFRelease<CFStringRef> valueRef =
|
||||
CFStringCreateWithCString(NULL, value, kCFStringEncodingUTF8);
|
||||
CFDictionarySetValue(dict, keyRef, valueRef);
|
||||
}
|
||||
|
||||
void
|
||||
AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
int32_t value)
|
||||
{
|
||||
AutoCFRelease<CFNumberRef> valueRef =
|
||||
CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
|
||||
AutoCFRelease<CFStringRef> keyRef =
|
||||
CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
|
||||
CFDictionarySetValue(dict, keyRef, valueRef);
|
||||
}
|
||||
|
||||
void
|
||||
AppleUtils::SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
bool value)
|
||||
{
|
||||
AutoCFRelease<CFStringRef> keyRef =
|
||||
CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
|
||||
CFDictionarySetValue(dict, keyRef, value ? kCFBooleanTrue : kCFBooleanFalse);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mozilla
|
66
content/media/fmp4/apple/AppleUtils.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* 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/. */
|
||||
|
||||
// Utility functions to help with Apple API calls.
|
||||
|
||||
#ifndef mozilla_AppleUtils_h
|
||||
#define mozilla_AppleUtils_h
|
||||
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include "nsError.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct AppleUtils {
|
||||
// Helper to retrieve properties from AudioFileStream objects.
|
||||
static nsresult GetProperty(AudioFileStreamID aAudioFileStream,
|
||||
AudioFileStreamPropertyID aPropertyID,
|
||||
void *aData);
|
||||
|
||||
// Helper to set a string, string pair on a CFMutableDictionaryRef.
|
||||
static void SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
const char* value);
|
||||
// Helper to set a string, int32_t pair on a CFMutableDictionaryRef.
|
||||
static void SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
int32_t value);
|
||||
// Helper to set a string, bool pair on a CFMutableDictionaryRef.
|
||||
static void SetCFDict(CFMutableDictionaryRef dict,
|
||||
const char* key,
|
||||
bool value);
|
||||
};
|
||||
|
||||
// Wrapper class to call CFRelease on reference types
|
||||
// when they go out of scope.
|
||||
template <class T>
|
||||
class AutoCFRelease {
|
||||
public:
|
||||
AutoCFRelease(T aRef)
|
||||
: mRef(aRef)
|
||||
{
|
||||
}
|
||||
~AutoCFRelease()
|
||||
{
|
||||
if (mRef) {
|
||||
CFRelease(mRef);
|
||||
}
|
||||
}
|
||||
// Return the wrapped ref so it can be used as an in parameter.
|
||||
operator T()
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
// Return a pointer to the wrapped ref for use as an out parameter.
|
||||
T* receive()
|
||||
{
|
||||
return &mRef;
|
||||
}
|
||||
private:
|
||||
T mRef;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AppleUtils_h
|
427
content/media/fmp4/apple/AppleVTDecoder.cpp
Normal file
@ -0,0 +1,427 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <CoreFoundation/CFString.h>
|
||||
|
||||
#include "AppleUtils.h"
|
||||
#include "mozilla/SHA1.h"
|
||||
#include "mp4_demuxer/DecoderData.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "AppleCMLinker.h"
|
||||
#include "AppleVTDecoder.h"
|
||||
#include "AppleVTLinker.h"
|
||||
#include "prlog.h"
|
||||
#include "MediaData.h"
|
||||
#include "VideoUtils.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
#define LOG_MEDIA_SHA1
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
AppleVTDecoder::AppleVTDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
MediaTaskQueue* aVideoTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
layers::ImageContainer* aImageContainer)
|
||||
: mConfig(aConfig)
|
||||
, mTaskQueue(aVideoTaskQueue)
|
||||
, mCallback(aCallback)
|
||||
, mImageContainer(aImageContainer)
|
||||
, mFormat(nullptr)
|
||||
, mSession(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(AppleVTDecoder);
|
||||
// TODO: Verify aConfig.mime_type.
|
||||
LOG("Creating AppleVTDecoder for %dx%d h.264 video",
|
||||
mConfig.display_width,
|
||||
mConfig.display_height
|
||||
);
|
||||
}
|
||||
|
||||
AppleVTDecoder::~AppleVTDecoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(AppleVTDecoder);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::Init()
|
||||
{
|
||||
nsresult rv = InitializeSession();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::Shutdown()
|
||||
{
|
||||
if (mSession) {
|
||||
LOG("%s: cleaning up session %p", __func__, mSession);
|
||||
VTDecompressionSessionInvalidate(mSession);
|
||||
CFRelease(mSession);
|
||||
mSession = nullptr;
|
||||
}
|
||||
if (mFormat) {
|
||||
LOG("%s: releasing format %p", __func__, mFormat);
|
||||
CFRelease(mFormat);
|
||||
mFormat = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::Input(mp4_demuxer::MP4Sample* aSample)
|
||||
{
|
||||
LOG("mp4 input sample %p pts %lld duration %lld us%s %d bytes",
|
||||
aSample,
|
||||
aSample->composition_timestamp,
|
||||
aSample->duration,
|
||||
aSample->is_sync_point ? " keyframe" : "",
|
||||
aSample->size);
|
||||
|
||||
#ifdef LOG_MEDIA_SHA1
|
||||
SHA1Sum hash;
|
||||
hash.update(aSample->data, aSample->size);
|
||||
uint8_t digest_buf[SHA1Sum::kHashSize];
|
||||
hash.finish(digest_buf);
|
||||
nsAutoCString digest;
|
||||
for (size_t i = 0; i < sizeof(digest_buf); i++) {
|
||||
digest.AppendPrintf("%02x", digest_buf[i]);
|
||||
}
|
||||
LOG(" sha1 %s", digest.get());
|
||||
#endif // LOG_MEDIA_SHA1
|
||||
|
||||
mTaskQueue->Dispatch(
|
||||
NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
|
||||
this,
|
||||
&AppleVTDecoder::SubmitFrame,
|
||||
nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::Flush()
|
||||
{
|
||||
mReorderQueue.Clear();
|
||||
return Drain();
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::Drain()
|
||||
{
|
||||
OSStatus rv = VTDecompressionSessionWaitForAsynchronousFrames(mSession);
|
||||
if (rv != noErr) {
|
||||
LOG("Error %d draining frames", rv);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return DrainReorderedFrames();
|
||||
}
|
||||
|
||||
//
|
||||
// Implementation details.
|
||||
//
|
||||
|
||||
// Context object to hold a copy of sample metadata.
|
||||
class FrameRef {
|
||||
public:
|
||||
Microseconds timestamp;
|
||||
Microseconds duration;
|
||||
int64_t byte_offset;
|
||||
bool is_sync_point;
|
||||
|
||||
explicit FrameRef(mp4_demuxer::MP4Sample* aSample)
|
||||
{
|
||||
MOZ_ASSERT(aSample);
|
||||
timestamp = aSample->composition_timestamp;
|
||||
duration = aSample->duration;
|
||||
byte_offset = aSample->byte_offset;
|
||||
is_sync_point = aSample->is_sync_point;
|
||||
}
|
||||
};
|
||||
|
||||
// Callback passed to the VideoToolbox decoder for returning data.
|
||||
// This needs to be static because the API takes a C-style pair of
|
||||
// function and userdata pointers. This validates parameters and
|
||||
// forwards the decoded image back to an object method.
|
||||
static void
|
||||
PlatformCallback(void* decompressionOutputRefCon,
|
||||
void* sourceFrameRefCon,
|
||||
OSStatus status,
|
||||
VTDecodeInfoFlags flags,
|
||||
CVImageBufferRef image,
|
||||
CMTime presentationTimeStamp,
|
||||
CMTime presentationDuration)
|
||||
{
|
||||
LOG("AppleVideoDecoder %s status %d flags %d", __func__, status, flags);
|
||||
|
||||
AppleVTDecoder* decoder =
|
||||
static_cast<AppleVTDecoder*>(decompressionOutputRefCon);
|
||||
nsAutoPtr<FrameRef> frameRef =
|
||||
nsAutoPtr<FrameRef>(static_cast<FrameRef*>(sourceFrameRefCon));
|
||||
|
||||
LOG("mp4 output frame %lld pts %lld duration %lld us%s",
|
||||
frameRef->byte_offset,
|
||||
frameRef->timestamp,
|
||||
frameRef->duration,
|
||||
frameRef->is_sync_point ? " keyframe" : ""
|
||||
);
|
||||
|
||||
// Validate our arguments.
|
||||
if (status != noErr || !image) {
|
||||
NS_WARNING("VideoToolbox decoder returned no data");
|
||||
return;
|
||||
}
|
||||
if (flags & kVTDecodeInfo_FrameDropped) {
|
||||
NS_WARNING(" ...frame dropped...");
|
||||
}
|
||||
MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(),
|
||||
"VideoToolbox returned an unexpected image type");
|
||||
|
||||
// Forward the data back to an object method which can access
|
||||
// the correct MP4Reader callback.
|
||||
decoder->OutputFrame(image, frameRef);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::DrainReorderedFrames()
|
||||
{
|
||||
while (!mReorderQueue.IsEmpty()) {
|
||||
mCallback->Output(mReorderQueue.Pop());
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Copy and return a decoded frame.
|
||||
nsresult
|
||||
AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
|
||||
nsAutoPtr<FrameRef> aFrameRef)
|
||||
{
|
||||
size_t width = CVPixelBufferGetWidth(aImage);
|
||||
size_t height = CVPixelBufferGetHeight(aImage);
|
||||
LOG(" got decoded frame data... %ux%u %s", width, height,
|
||||
CVPixelBufferIsPlanar(aImage) ? "planar" : "chunked");
|
||||
#ifdef DEBUG
|
||||
size_t planes = CVPixelBufferGetPlaneCount(aImage);
|
||||
for (size_t i = 0; i < planes; ++i) {
|
||||
size_t stride = CVPixelBufferGetBytesPerRowOfPlane(aImage, i);
|
||||
LOG(" plane %u %ux%u rowbytes %u",
|
||||
(unsigned)i,
|
||||
CVPixelBufferGetWidthOfPlane(aImage, i),
|
||||
CVPixelBufferGetHeightOfPlane(aImage, i),
|
||||
(unsigned)stride);
|
||||
}
|
||||
MOZ_ASSERT(planes == 2);
|
||||
#endif // DEBUG
|
||||
|
||||
VideoData::YCbCrBuffer buffer;
|
||||
|
||||
// Lock the returned image data.
|
||||
CVReturn rv = CVPixelBufferLockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
|
||||
if (rv != kCVReturnSuccess) {
|
||||
NS_ERROR("error locking pixel data");
|
||||
mCallback->Error();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Y plane.
|
||||
buffer.mPlanes[0].mData =
|
||||
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 0));
|
||||
buffer.mPlanes[0].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 0);
|
||||
buffer.mPlanes[0].mWidth = width;
|
||||
buffer.mPlanes[0].mHeight = height;
|
||||
buffer.mPlanes[0].mOffset = 0;
|
||||
buffer.mPlanes[0].mSkip = 0;
|
||||
// Cb plane.
|
||||
buffer.mPlanes[1].mData =
|
||||
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
|
||||
buffer.mPlanes[1].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
|
||||
buffer.mPlanes[1].mWidth = (width+1) / 2;
|
||||
buffer.mPlanes[1].mHeight = (height+1) / 2;
|
||||
buffer.mPlanes[1].mOffset = 0;
|
||||
buffer.mPlanes[1].mSkip = 1;
|
||||
// Cr plane.
|
||||
buffer.mPlanes[2].mData =
|
||||
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
|
||||
buffer.mPlanes[2].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
|
||||
buffer.mPlanes[2].mWidth = (width+1) / 2;
|
||||
buffer.mPlanes[2].mHeight = (height+1) / 2;
|
||||
buffer.mPlanes[2].mOffset = 1;
|
||||
buffer.mPlanes[2].mSkip = 1;
|
||||
|
||||
// Bounds.
|
||||
VideoInfo info;
|
||||
info.mDisplay = nsIntSize(width, height);
|
||||
info.mHasVideo = true;
|
||||
gfx::IntRect visible = gfx::IntRect(0,
|
||||
0,
|
||||
mConfig.display_width,
|
||||
mConfig.display_height);
|
||||
|
||||
// Copy the image data into our own format.
|
||||
nsAutoPtr<VideoData> data;
|
||||
data =
|
||||
VideoData::Create(info,
|
||||
mImageContainer,
|
||||
nullptr,
|
||||
aFrameRef->byte_offset,
|
||||
aFrameRef->timestamp,
|
||||
aFrameRef->duration,
|
||||
buffer,
|
||||
aFrameRef->is_sync_point,
|
||||
aFrameRef->timestamp,
|
||||
visible);
|
||||
// Unlock the returned image data.
|
||||
CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
|
||||
|
||||
// Frames come out in DTS order but we need to output them
|
||||
// in composition order.
|
||||
mReorderQueue.Push(data.forget());
|
||||
if (mReorderQueue.Length() > 2) {
|
||||
VideoData* readyData = mReorderQueue.Pop();
|
||||
mCallback->Output(readyData);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Helper to fill in a timestamp structure.
|
||||
static CMSampleTimingInfo
|
||||
TimingInfoFromSample(mp4_demuxer::MP4Sample* aSample)
|
||||
{
|
||||
CMSampleTimingInfo timestamp;
|
||||
|
||||
timestamp.duration = CMTimeMake(aSample->duration, USECS_PER_S);
|
||||
timestamp.presentationTimeStamp =
|
||||
CMTimeMake(aSample->composition_timestamp, USECS_PER_S);
|
||||
// No DTS value available from libstagefright.
|
||||
timestamp.decodeTimeStamp = CMTimeMake(0, USECS_PER_S);
|
||||
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::SubmitFrame(mp4_demuxer::MP4Sample* aSample)
|
||||
{
|
||||
// For some reason this gives me a double-free error with stagefright.
|
||||
AutoCFRelease<CMBlockBufferRef> block = nullptr;
|
||||
AutoCFRelease<CMSampleBufferRef> sample = nullptr;
|
||||
VTDecodeInfoFlags flags;
|
||||
OSStatus rv;
|
||||
|
||||
// FIXME: This copies the sample data. I think we can provide
|
||||
// a custom block source which reuses the aSample buffer.
|
||||
// But note that there may be a problem keeping the samples
|
||||
// alive over multiple frames.
|
||||
rv = CMBlockBufferCreateWithMemoryBlock(NULL // Struct allocator.
|
||||
,aSample->data
|
||||
,aSample->size
|
||||
,kCFAllocatorNull // Block allocator.
|
||||
,NULL // Block source.
|
||||
,0 // Data offset.
|
||||
,aSample->size
|
||||
,false
|
||||
,block.receive());
|
||||
NS_ASSERTION(rv == noErr, "Couldn't create CMBlockBuffer");
|
||||
CMSampleTimingInfo timestamp = TimingInfoFromSample(aSample);
|
||||
rv = CMSampleBufferCreate(NULL, block, true, 0, 0, mFormat, 1, 1, ×tamp, 0, NULL, sample.receive());
|
||||
NS_ASSERTION(rv == noErr, "Couldn't create CMSampleBuffer");
|
||||
rv = VTDecompressionSessionDecodeFrame(mSession,
|
||||
sample,
|
||||
0,
|
||||
new FrameRef(aSample),
|
||||
&flags);
|
||||
NS_ASSERTION(rv == noErr, "Couldn't pass frame to decoder");
|
||||
|
||||
// Ask for more data.
|
||||
if (mTaskQueue->IsEmpty()) {
|
||||
LOG("AppleVTDecoder task queue empty; requesting more data");
|
||||
mCallback->InputExhausted();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppleVTDecoder::InitializeSession()
|
||||
{
|
||||
OSStatus rv;
|
||||
AutoCFRelease<CFMutableDictionaryRef> extensions =
|
||||
CFDictionaryCreateMutable(NULL, 0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
AppleUtils::SetCFDict(extensions, "CVImageBufferChromaLocationBottomField", "left");
|
||||
AppleUtils::SetCFDict(extensions, "CVImageBufferChromaLocationTopField", "left");
|
||||
AppleUtils::SetCFDict(extensions, "FullRangeVideo", true);
|
||||
|
||||
AutoCFRelease<CFMutableDictionaryRef> atoms =
|
||||
CFDictionaryCreateMutable(NULL, 0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
AutoCFRelease<CFDataRef> avc_data = CFDataCreate(NULL,
|
||||
mConfig.extra_data.begin(), mConfig.extra_data.length());
|
||||
|
||||
#ifdef LOG_MEDIA_SHA1
|
||||
SHA1Sum avc_hash;
|
||||
avc_hash.update(mConfig.extra_data.begin(), mConfig.extra_data.length());
|
||||
uint8_t digest_buf[SHA1Sum::kHashSize];
|
||||
avc_hash.finish(digest_buf);
|
||||
nsAutoCString avc_digest;
|
||||
for (size_t i = 0; i < sizeof(digest_buf); i++) {
|
||||
avc_digest.AppendPrintf("%02x", digest_buf[i]);
|
||||
}
|
||||
LOG("AVCDecoderConfig %ld bytes sha1 %s",
|
||||
mConfig.extra_data.length(), avc_digest.get());
|
||||
#endif // LOG_MEDIA_SHA1
|
||||
|
||||
CFDictionarySetValue(atoms, CFSTR("avcC"), avc_data);
|
||||
CFDictionarySetValue(extensions, CFSTR("SampleDescriptionExtensionAtoms"), atoms);
|
||||
rv = CMVideoFormatDescriptionCreate(NULL, // Use default allocator.
|
||||
kCMVideoCodecType_H264,
|
||||
mConfig.display_width,
|
||||
mConfig.display_height,
|
||||
extensions,
|
||||
&mFormat);
|
||||
if (rv != noErr) {
|
||||
NS_ERROR("Couldn't create format description!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Contruct video decoder selection spec.
|
||||
AutoCFRelease<CFMutableDictionaryRef> spec =
|
||||
CFDictionaryCreateMutable(NULL, 0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
// This key is supported (or ignored) but not declared prior to OSX 10.9.
|
||||
AutoCFRelease<CFStringRef>
|
||||
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder =
|
||||
CFStringCreateWithCString(NULL, "EnableHardwareAcceleratedVideoDecoder",
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
CFDictionarySetValue(spec,
|
||||
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
|
||||
kCFBooleanTrue);
|
||||
|
||||
VTDecompressionOutputCallbackRecord cb = { PlatformCallback, this };
|
||||
rv = VTDecompressionSessionCreate(NULL, // Allocator.
|
||||
mFormat,
|
||||
spec, // Video decoder selection.
|
||||
NULL, // Output video format.
|
||||
&cb,
|
||||
&mSession);
|
||||
if (rv != noErr) {
|
||||
NS_ERROR("Couldn't create decompression session!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
60
content/media/fmp4/apple/AppleVTDecoder.h
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 mozilla_AppleVTDecoder_h
|
||||
#define mozilla_AppleVTDecoder_h
|
||||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "nsIThread.h"
|
||||
#include "ReorderQueue.h"
|
||||
|
||||
#include "VideoToolbox/VideoToolbox.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaTaskQueue;
|
||||
class MediaDataDecoderCallback;
|
||||
namespace layers {
|
||||
class ImageContainer;
|
||||
}
|
||||
class FrameRef;
|
||||
|
||||
class AppleVTDecoder : public MediaDataDecoder {
|
||||
public:
|
||||
AppleVTDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||
MediaTaskQueue* aVideoTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
layers::ImageContainer* aImageContainer);
|
||||
~AppleVTDecoder();
|
||||
virtual nsresult Init() MOZ_OVERRIDE;
|
||||
virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
|
||||
virtual nsresult Flush() MOZ_OVERRIDE;
|
||||
virtual nsresult Drain() MOZ_OVERRIDE;
|
||||
virtual nsresult Shutdown() MOZ_OVERRIDE;
|
||||
// Return hook for VideoToolbox callback.
|
||||
nsresult OutputFrame(CVPixelBufferRef aImage,
|
||||
nsAutoPtr<FrameRef> frameRef);
|
||||
private:
|
||||
const mp4_demuxer::VideoDecoderConfig& mConfig;
|
||||
RefPtr<MediaTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
layers::ImageContainer* mImageContainer;
|
||||
CMVideoFormatDescriptionRef mFormat;
|
||||
VTDecompressionSessionRef mSession;
|
||||
ReorderQueue mReorderQueue;
|
||||
|
||||
// Method to pass a frame to VideoToolbox for decoding.
|
||||
nsresult SubmitFrame(mp4_demuxer::MP4Sample* aSample);
|
||||
// Method to set up the decompression session.
|
||||
nsresult InitializeSession();
|
||||
nsresult DrainReorderedFrames();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_AppleVTDecoder_h
|
12
content/media/fmp4/apple/AppleVTFunctions.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
// Construct references to each of the VideoToolbox symbols we use.
|
||||
|
||||
LINK_FUNC(VTDecompressionSessionCreate)
|
||||
LINK_FUNC(VTDecompressionSessionDecodeFrame)
|
||||
LINK_FUNC(VTDecompressionSessionInvalidate)
|
||||
LINK_FUNC(VTDecompressionSessionWaitForAsynchronousFrames)
|
89
content/media/fmp4/apple/AppleVTLinker.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 <dlfcn.h>
|
||||
|
||||
#include "AppleVTLinker.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
AppleVTLinker::LinkStatus
|
||||
AppleVTLinker::sLinkStatus = LinkStatus_INIT;
|
||||
|
||||
void* AppleVTLinker::sLink = nullptr;
|
||||
nsrefcnt AppleVTLinker::sRefCount = 0;
|
||||
|
||||
#define LINK_FUNC(func) typeof(func) func;
|
||||
#include "AppleVTFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
/* static */ bool
|
||||
AppleVTLinker::Link()
|
||||
{
|
||||
// Bump our reference count every time we're called.
|
||||
// Add a lock or change the thread assertion if
|
||||
// you need to call this off the main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
++sRefCount;
|
||||
|
||||
if (sLinkStatus) {
|
||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||
}
|
||||
|
||||
const char* dlname =
|
||||
"/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox";
|
||||
if (!(sLink = dlopen(dlname, RTLD_NOW | RTLD_LOCAL))) {
|
||||
NS_WARNING("Couldn't load VideoToolbox framework");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#define LINK_FUNC(func) \
|
||||
func = (typeof(func))dlsym(sLink, #func); \
|
||||
if (!func) { \
|
||||
NS_WARNING("Couldn't load VideoToolbox function " #func ); \
|
||||
goto fail; \
|
||||
}
|
||||
#include "AppleVTFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
LOG("Loaded VideoToolbox framework.");
|
||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
Unlink();
|
||||
|
||||
sLinkStatus = LinkStatus_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
AppleVTLinker::Unlink()
|
||||
{
|
||||
// We'll be called by multiple Decoders, one intantiated for
|
||||
// each media element. Therefore we receive must maintain a
|
||||
// reference count to avoidunloading our symbols when other
|
||||
// instances still need them.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(sLink && sRefCount > 0, "Unbalanced Unlink()");
|
||||
--sRefCount;
|
||||
if (sLink && sRefCount < 1) {
|
||||
LOG("Unlinking VideoToolbox framework.");
|
||||
dlclose(sLink);
|
||||
sLink = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
43
content/media/fmp4/apple/AppleVTLinker.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 AppleVTLinker_h
|
||||
#define AppleVTLinker_h
|
||||
|
||||
extern "C" {
|
||||
#pragma GCC visibility push(default)
|
||||
#include "VideoToolbox/VideoToolbox.h"
|
||||
#pragma GCC visibility pop
|
||||
}
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AppleVTLinker
|
||||
{
|
||||
public:
|
||||
static bool Link();
|
||||
static void Unlink();
|
||||
|
||||
private:
|
||||
static void* sLink;
|
||||
static nsrefcnt sRefCount;
|
||||
|
||||
static enum LinkStatus {
|
||||
LinkStatus_INIT = 0,
|
||||
LinkStatus_FAILED,
|
||||
LinkStatus_SUCCEEDED
|
||||
} sLinkStatus;
|
||||
};
|
||||
|
||||
#define LINK_FUNC(func) extern typeof(func)* func;
|
||||
#include "AppleVTFunctions.h"
|
||||
#undef LINK_FUNC
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // AppleVTLinker_h
|
29
content/media/fmp4/apple/ReorderQueue.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* 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/. */
|
||||
|
||||
// Queue for ordering decoded video frames by presentation time.
|
||||
// Decoders often return frames out of order, which we need to
|
||||
// buffer so we can forward them in correct presentation order.
|
||||
|
||||
#ifndef mozilla_ReorderQueue_h
|
||||
#define mozilla_ReorderQueue_h
|
||||
|
||||
#include <MediaData.h>
|
||||
#include <nsTPriorityQueue.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct ReorderQueueComparator
|
||||
{
|
||||
bool LessThan(VideoData* const& a, VideoData* const& b) const
|
||||
{
|
||||
return a->mTime < b->mTime;
|
||||
}
|
||||
};
|
||||
|
||||
typedef nsTPriorityQueue<VideoData*, ReorderQueueComparator> ReorderQueue;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ReorderQueue_h
|
76
content/media/fmp4/apple/VideoToolbox/VideoToolbox.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
// Stub header for VideoToolbox framework API.
|
||||
// We include our own copy so we can build on MacOS versions
|
||||
// where it's not available.
|
||||
|
||||
#ifndef mozilla_VideoToolbox_VideoToolbox_h
|
||||
#define mozilla_VideoToolbox_VideoToolbox_h
|
||||
|
||||
// CoreMedia is available starting in OS X 10.7,
|
||||
// so we need to dlopen it as well to run on 10.6,
|
||||
// but we can depend on the real framework headers at build time.
|
||||
|
||||
#include <CoreMedia/CMBase.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreVideo/CVPixelBuffer.h>
|
||||
#include <CoreMedia/CMSampleBuffer.h>
|
||||
#include <CoreMedia/CMFormatDescription.h>
|
||||
#include <CoreMedia/CMTime.h>
|
||||
|
||||
typedef uint32_t VTDecodeFrameFlags;
|
||||
typedef uint32_t VTDecodeInfoFlags;
|
||||
enum {
|
||||
kVTDecodeInfo_Asynchronous = 1UL << 0,
|
||||
kVTDecodeInfo_FrameDropped = 1UL << 1,
|
||||
};
|
||||
|
||||
typedef struct OpaqueVTDecompressionSession* VTDecompressionSessionRef;
|
||||
typedef void (*VTDecompressionOutputCallback)(
|
||||
void*,
|
||||
void*,
|
||||
OSStatus,
|
||||
VTDecodeInfoFlags,
|
||||
CVImageBufferRef,
|
||||
CMTime,
|
||||
CMTime
|
||||
);
|
||||
typedef struct VTDecompressionOutputCallbackRecord {
|
||||
VTDecompressionOutputCallback decompressionOutputCallback;
|
||||
void* decompressionOutputRefCon;
|
||||
} VTDecompressionOutputCallbackRecord;
|
||||
|
||||
OSStatus
|
||||
VTDecompressionSessionCreate(
|
||||
CFAllocatorRef,
|
||||
CMVideoFormatDescriptionRef,
|
||||
CFDictionaryRef,
|
||||
CFDictionaryRef,
|
||||
const VTDecompressionOutputCallbackRecord*,
|
||||
VTDecompressionSessionRef*
|
||||
);
|
||||
|
||||
OSStatus
|
||||
VTDecompressionSessionDecodeFrame(
|
||||
VTDecompressionSessionRef,
|
||||
CMSampleBufferRef,
|
||||
VTDecodeFrameFlags,
|
||||
void*,
|
||||
VTDecodeInfoFlags*
|
||||
);
|
||||
|
||||
OSStatus
|
||||
VTDecompressionSessionWaitForAsynchronousFrames(
|
||||
VTDecompressionSessionRef
|
||||
);
|
||||
|
||||
void
|
||||
VTDecompressionSessionInvalidate(
|
||||
VTDecompressionSessionRef
|
||||
);
|
||||
|
||||
#endif // mozilla_VideoToolbox_VideoToolbox_h
|
@ -42,6 +42,22 @@ if CONFIG['MOZ_FFMPEG']:
|
||||
'ffmpeg',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_APPLEMEDIA']:
|
||||
EXPORTS += [
|
||||
'apple/AppleDecoderModule.h',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'apple/AppleATDecoder.cpp',
|
||||
'apple/AppleCMLinker.cpp',
|
||||
'apple/AppleDecoderModule.cpp',
|
||||
'apple/AppleUtils.cpp',
|
||||
'apple/AppleVTDecoder.cpp',
|
||||
'apple/AppleVTLinker.cpp',
|
||||
]
|
||||
LDFLAGS += [
|
||||
'-framework AudioToolbox',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -26,8 +26,6 @@ using mozilla::dom::CrashReporterChild;
|
||||
#if defined(XP_WIN)
|
||||
#define TARGET_SANDBOX_EXPORTS
|
||||
#include "mozilla/sandboxTarget.h"
|
||||
#elif defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||
#include "mozilla/Sandbox.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
@ -100,13 +98,6 @@ GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
|
||||
|
||||
nsAutoCString nativePath;
|
||||
libFile->GetNativePath(nativePath);
|
||||
|
||||
#if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
|
||||
// Enable sandboxing here -- we know the plugin file's path, but
|
||||
// this process's execution hasn't been affected by its content yet.
|
||||
mozilla::SetMediaPluginSandbox(nativePath.get());
|
||||
#endif
|
||||
|
||||
mLib = PR_LoadLibrary(nativePath.get());
|
||||
if (!mLib) {
|
||||
return false;
|
||||
|
@ -329,7 +329,6 @@ AudioDestinationNode::AudioDestinationNode(AudioContext* aContext,
|
||||
static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
|
||||
|
||||
mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
|
||||
mStream->SetAudioChannelType(aChannel);
|
||||
mStream->AddMainThreadListener(this);
|
||||
mStream->AddAudioOutput(&gWebAudioOutputKey);
|
||||
|
||||
@ -539,6 +538,10 @@ AudioDestinationNode::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& a
|
||||
CheckAudioChannelPermissions(aValue)) {
|
||||
mAudioChannel = aValue;
|
||||
|
||||
if (mStream) {
|
||||
mStream->SetAudioChannelType(mAudioChannel);
|
||||
}
|
||||
|
||||
if (mAudioChannelAgent) {
|
||||
CreateAudioChannelAgent();
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/Likely.h"
|
||||
|
||||
@ -518,11 +518,14 @@ SVGSVGElement::SetCurrentScaleTranslate(float s, float x, float y)
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
|
||||
if (presShell && IsRoot()) {
|
||||
bool scaling = (mPreviousScale != mCurrentScale);
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetGUIEvent event(true, scaling ? NS_SVG_ZOOM : NS_SVG_SCROLL, 0);
|
||||
event.eventStructType = scaling ? NS_SVGZOOM_EVENT : NS_EVENT;
|
||||
presShell->HandleDOMEventWithTarget(this, &event, &status);
|
||||
if (mPreviousScale != mCurrentScale) {
|
||||
InternalSVGZoomEvent svgZoomEvent(true, NS_SVG_ZOOM);
|
||||
presShell->HandleDOMEventWithTarget(this, &svgZoomEvent, &status);
|
||||
} else {
|
||||
WidgetEvent svgScrollEvent(true, NS_SVG_SCROLL);
|
||||
presShell->HandleDOMEventWithTarget(this, &svgScrollEvent, &status);
|
||||
}
|
||||
InvalidateTransformNotifyFrame();
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
* 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 "mozilla/dom/SVGZoomEvent.h"
|
||||
#include "DOMSVGPoint.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "mozilla/dom/SVGZoomEvent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "prtime.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -27,9 +28,9 @@ NS_INTERFACE_MAP_END_INHERITING(UIEvent)
|
||||
|
||||
SVGZoomEvent::SVGZoomEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetGUIEvent* aEvent)
|
||||
InternalSVGZoomEvent* aEvent)
|
||||
: UIEvent(aOwner, aPresContext,
|
||||
aEvent ? aEvent : new WidgetGUIEvent(false, NS_SVG_ZOOM, 0))
|
||||
aEvent ? aEvent : new InternalSVGZoomEvent(false, NS_SVG_ZOOM))
|
||||
, mPreviousScale(0)
|
||||
, mNewScale(0)
|
||||
{
|
||||
@ -38,12 +39,9 @@ SVGZoomEvent::SVGZoomEvent(EventTarget* aOwner,
|
||||
}
|
||||
else {
|
||||
mEventIsInternal = true;
|
||||
mEvent->eventStructType = NS_SVGZOOM_EVENT;
|
||||
mEvent->time = PR_Now();
|
||||
}
|
||||
|
||||
mEvent->mFlags.mCancelable = false;
|
||||
|
||||
// We must store the "Previous" and "New" values before this event is
|
||||
// dispatched. Reading the values from the root 'svg' element after we've
|
||||
// been dispatched is not an option since event handler code may change
|
||||
@ -95,7 +93,7 @@ nsresult
|
||||
NS_NewDOMSVGZoomEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::WidgetGUIEvent* aEvent)
|
||||
mozilla::InternalSVGZoomEvent* aEvent)
|
||||
{
|
||||
mozilla::dom::SVGZoomEvent* it =
|
||||
new mozilla::dom::SVGZoomEvent(aOwner, aPresContext, aEvent);
|
||||
|
@ -28,7 +28,7 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
SVGZoomEvent(EventTarget* aOwner, nsPresContext* aPresContext,
|
||||
WidgetGUIEvent* aEvent);
|
||||
InternalSVGZoomEvent* aEvent);
|
||||
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_UIEVENT
|
||||
|
@ -729,10 +729,10 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
|
||||
aEvent->AsClipboardEvent());
|
||||
case NS_SVGZOOM_EVENT:
|
||||
return NS_NewDOMSVGZoomEvent(aDOMEvent, aOwner, aPresContext,
|
||||
aEvent->AsGUIEvent());
|
||||
aEvent->AsSVGZoomEvent());
|
||||
case NS_SMIL_TIME_EVENT:
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext, aEvent);
|
||||
|
||||
return NS_NewDOMTimeEvent(aDOMEvent, aOwner, aPresContext,
|
||||
aEvent->AsSMILTimeEvent());
|
||||
case NS_COMMAND_EVENT:
|
||||
return NS_NewDOMCommandEvent(aDOMEvent, aOwner, aPresContext,
|
||||
aEvent->AsCommandEvent());
|
||||
|
@ -306,12 +306,12 @@ nsresult
|
||||
NS_NewDOMSVGZoomEvent(nsIDOMEvent** aResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::WidgetGUIEvent* aEvent);
|
||||
mozilla::InternalSVGZoomEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMTimeEvent(nsIDOMEvent** aResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::WidgetEvent* aEvent);
|
||||
mozilla::InternalSMILTimeEvent* aEvent);
|
||||
nsresult
|
||||
NS_NewDOMXULCommandEvent(nsIDOMEvent** aResult,
|
||||
mozilla::dom::EventTarget* aOwner,
|
||||
|
@ -918,7 +918,7 @@ ContentChild::RecvSetProcessSandbox()
|
||||
// at some point; see bug 880808.
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
#if defined(XP_LINUX)
|
||||
SetContentProcessSandbox();
|
||||
SetCurrentProcessSandbox();
|
||||
#elif defined(XP_WIN)
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
#endif
|
||||
|
@ -46,9 +46,7 @@ EXTRA_COMPONENTS += [
|
||||
'PeerConnection.manifest',
|
||||
]
|
||||
|
||||
JS_MODULES_PATH = 'modules/media'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
EXTRA_JS_MODULES.media += [
|
||||
'IdpProxy.jsm',
|
||||
'PeerConnectionIdp.jsm',
|
||||
'RTCStatsReport.jsm',
|
||||
|
@ -19,7 +19,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
'android/SmsService.cpp',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
EXTRA_JS_MODULES = [
|
||||
EXTRA_JS_MODULES += [
|
||||
'gonk/mms_consts.js',
|
||||
'gonk/MmsPduHelper.jsm',
|
||||
'gonk/MobileMessageDB.jsm',
|
||||
|
@ -27,7 +27,7 @@ UNIFIED_SOURCES += [
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
EXTRA_JS_MODULES = [
|
||||
EXTRA_JS_MODULES += [
|
||||
'NetworkStatsDB.jsm',
|
||||
'NetworkStatsService.jsm',
|
||||
]
|
||||
|
@ -3,8 +3,8 @@
|
||||
* 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 "mozilla/ContentEvents.h"
|
||||
#include "mozilla/dom/TimeEvent.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
@ -14,26 +14,18 @@ namespace dom {
|
||||
|
||||
TimeEvent::TimeEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent)
|
||||
InternalSMILTimeEvent* aEvent)
|
||||
: Event(aOwner, aPresContext,
|
||||
aEvent ? aEvent : new InternalUIEvent(false, 0))
|
||||
, mDetail(0)
|
||||
aEvent ? aEvent : new InternalSMILTimeEvent(false, 0))
|
||||
, mDetail(mEvent->AsSMILTimeEvent()->detail)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
if (aEvent) {
|
||||
mEventIsInternal = false;
|
||||
} else {
|
||||
mEventIsInternal = true;
|
||||
mEvent->eventStructType = NS_SMIL_TIME_EVENT;
|
||||
}
|
||||
|
||||
if (mEvent->eventStructType == NS_SMIL_TIME_EVENT) {
|
||||
mDetail = mEvent->AsUIEvent()->detail;
|
||||
}
|
||||
|
||||
mEvent->mFlags.mBubbles = false;
|
||||
mEvent->mFlags.mCancelable = false;
|
||||
|
||||
if (mPresContext) {
|
||||
nsCOMPtr<nsIDocShell> docShell = mPresContext->GetDocShell();
|
||||
if (docShell) {
|
||||
@ -92,7 +84,7 @@ nsresult
|
||||
NS_NewDOMTimeEvent(nsIDOMEvent** aInstancePtrResult,
|
||||
EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent)
|
||||
InternalSMILTimeEvent* aEvent)
|
||||
{
|
||||
TimeEvent* it = new TimeEvent(aOwner, aPresContext, aEvent);
|
||||
NS_ADDREF(it);
|
||||
|
@ -19,7 +19,7 @@ class TimeEvent MOZ_FINAL : public Event,
|
||||
public:
|
||||
TimeEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
WidgetEvent* aEvent);
|
||||
InternalSMILTimeEvent* aEvent);
|
||||
|
||||
// nsISupports interface:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/SVGAnimationElement.h"
|
||||
#include "nsSMILTimedElement.h"
|
||||
@ -92,8 +92,7 @@ namespace
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
InternalUIEvent event(true, mMsg);
|
||||
event.eventStructType = NS_SMIL_TIME_EVENT;
|
||||
InternalSMILTimeEvent event(true, mMsg);
|
||||
event.detail = mDetail;
|
||||
|
||||
nsPresContext* context = nullptr;
|
||||
|