Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WMF.h"
8 #include "WMFDecoder.h"
9 #include "WMFReader.h"
10 #include "WMFUtils.h"
11 #include "MediaDecoderStateMachine.h"
12 #include "mozilla/Preferences.h"
13 #include "mozilla/WindowsVersion.h"
14 #include "nsCharSeparatedTokenizer.h"
16 #ifdef MOZ_DIRECTSHOW
17 #include "DirectShowDecoder.h"
18 #endif
20 namespace mozilla {
22 MediaDecoderStateMachine* WMFDecoder::CreateStateMachine()
23 {
24 return new MediaDecoderStateMachine(this, new WMFReader(this));
25 }
27 /* static */
28 bool
29 WMFDecoder::IsMP3Supported()
30 {
31 MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
32 if (!MediaDecoder::IsWMFEnabled()) {
33 return false;
34 }
35 // MP3 works fine in WMF on Windows Vista and Windows 8.
36 if (!IsWin7OrLater()) {
37 return true;
38 }
39 // MP3 support is disabled if we're on Windows 7 and no service packs are
40 // installed, since it's crashy. Win7 with service packs is not so crashy,
41 // so we enable it there. Note we prefer DirectShow for MP3 playback, but
42 // we still support MP3 in MP4 via WMF, or MP3 in WMF if DirectShow is
43 // disabled.
44 return IsWin7SP1OrLater();
45 }
47 static bool
48 IsSupportedH264Codec(const nsAString& aCodec)
49 {
50 // According to the WMF documentation:
51 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815%28v=vs.85%29.aspx
52 // "The Media Foundation H.264 video decoder is a Media Foundation Transform
53 // that supports decoding of Baseline, Main, and High profiles, up to level
54 // 5.1.". We also report that we can play Extended profile, as there are
55 // bitstreams that are Extended compliant that are also Baseline compliant.
57 // H.264 codecs parameters have a type defined as avc1.PPCCLL, where
58 // PP = profile_idc, CC = constraint_set flags, LL = level_idc.
59 // We ignore the constraint_set flags, as it's not clear from the WMF
60 // documentation what constraints the WMF H.264 decoder supports.
61 // See http://blog.pearce.org.nz/2013/11/what-does-h264avc1-codecs-parameters.html
62 // for more details.
63 if (aCodec.Length() != strlen("avc1.PPCCLL")) {
64 return false;
65 }
67 // Verify the codec starts with "avc1.".
68 const nsAString& sample = Substring(aCodec, 0, 5);
69 if (!sample.EqualsASCII("avc1.")) {
70 return false;
71 }
73 // Extract the profile_idc and level_idc. Note: the constraint_set flags
74 // are ignored, it's not clear from the WMF documentation if they make a
75 // difference.
76 nsresult rv = NS_OK;
77 const int32_t profile = PromiseFlatString(Substring(aCodec, 5, 2)).ToInteger(&rv, 16);
78 NS_ENSURE_SUCCESS(rv, false);
80 const int32_t level = PromiseFlatString(Substring(aCodec, 9, 2)).ToInteger(&rv, 16);
81 NS_ENSURE_SUCCESS(rv, false);
83 return level >= eAVEncH264VLevel1 &&
84 level <= eAVEncH264VLevel5_1 &&
85 (profile == eAVEncH264VProfile_Base ||
86 profile == eAVEncH264VProfile_Main ||
87 profile == eAVEncH264VProfile_Extended ||
88 profile == eAVEncH264VProfile_High);
89 }
91 bool
92 WMFDecoder::CanPlayType(const nsACString& aType,
93 const nsAString& aCodecs)
94 {
95 if (!MediaDecoder::IsWMFEnabled() ||
96 NS_FAILED(LoadDLLs())) {
97 return false;
98 }
100 // Assume that if LoadDLLs() didn't fail, we can playback the types that
101 // we know should be supported by Windows Media Foundation.
102 if ((aType.EqualsASCII("audio/mpeg") || aType.EqualsASCII("audio/mp3")) &&
103 IsMP3Supported()) {
104 // Note: We block MP3 playback on Window 7 SP0 since it seems to crash
105 // in some circumstances.
106 return !aCodecs.Length() || aCodecs.EqualsASCII("mp3");
107 }
109 // AAC-LC or MP3 in M4A.
110 if (aType.EqualsASCII("audio/mp4") || aType.EqualsASCII("audio/x-m4a")) {
111 return !aCodecs.Length() ||
112 aCodecs.EqualsASCII("mp4a.40.2") ||
113 aCodecs.EqualsASCII("mp3");
114 }
116 if (!aType.EqualsASCII("video/mp4")) {
117 return false;
118 }
120 // H.264 + AAC in MP4. Verify that all the codecs specifed are ones that
121 // we expect that we can play.
122 nsCharSeparatedTokenizer tokenizer(aCodecs, ',');
123 bool expectMoreTokens = false;
124 while (tokenizer.hasMoreTokens()) {
125 const nsSubstring& token = tokenizer.nextToken();
126 expectMoreTokens = tokenizer.separatorAfterCurrentToken();
127 if (token.EqualsASCII("mp4a.40.2") || // AAC-LC
128 token.EqualsASCII("mp3") ||
129 IsSupportedH264Codec(token)) {
130 continue;
131 }
132 return false;
133 }
134 if (expectMoreTokens) {
135 // Last codec name was empty
136 return false;
137 }
138 return true;
139 }
141 nsresult
142 WMFDecoder::LoadDLLs()
143 {
144 return SUCCEEDED(wmf::LoadDLLs()) ? NS_OK : NS_ERROR_FAILURE;
145 }
147 void
148 WMFDecoder::UnloadDLLs()
149 {
150 wmf::UnloadDLLs();
151 }
153 /* static */
154 bool
155 WMFDecoder::IsEnabled()
156 {
157 // We only use WMF on Windows Vista and up
158 return IsVistaOrLater() &&
159 Preferences::GetBool("media.windows-media-foundation.enabled");
160 }
162 } // namespace mozilla