22 #include "nsIObjectLoadingContent.h" |
22 #include "nsIObjectLoadingContent.h" |
23 #include "nsCCUncollectableMarker.h" |
23 #include "nsCCUncollectableMarker.h" |
24 #include "mozilla/Base64.h" |
24 #include "mozilla/Base64.h" |
25 #include "mozilla/Preferences.h" |
25 #include "mozilla/Preferences.h" |
26 #include "nsDOMMutationObserver.h" |
26 #include "nsDOMMutationObserver.h" |
27 @@ -6706,26 +6709,23 @@ nsContentUtils::FindInternalContentViewe |
|
28 } |
|
29 return docFactory.forget(); |
|
30 } |
|
31 } |
|
32 } |
|
33 #endif |
|
34 |
|
35 #ifdef MOZ_GSTREAMER |
|
36 - if (nsHTMLMediaElement::IsH264Enabled()) { |
|
37 - for (unsigned int i = 0; i < ArrayLength(nsHTMLMediaElement::gH264Types); ++i) { |
|
38 - const char* type = nsHTMLMediaElement::gH264Types[i]; |
|
39 - if (!strcmp(aType, type)) { |
|
40 - docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1"); |
|
41 - if (docFactory && aLoaderType) { |
|
42 - *aLoaderType = TYPE_CONTENT; |
|
43 - } |
|
44 - return docFactory.forget(); |
|
45 + if (nsHTMLMediaElement::IsGStreamerEnabled()) { |
|
46 + if (nsGStreamerDecoder::CanHandleMediaType(aType, nullptr)) { |
|
47 + docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1"); |
|
48 + if (docFactory && aLoaderType) { |
|
49 + *aLoaderType = TYPE_CONTENT; |
|
50 } |
|
51 + return docFactory.forget(); |
|
52 } |
|
53 } |
|
54 #endif |
|
55 |
|
56 #ifdef MOZ_MEDIA_PLUGINS |
|
57 if (nsHTMLMediaElement::IsMediaPluginsEnabled() && |
|
58 nsHTMLMediaElement::IsMediaPluginsType(nsDependentCString(aType))) { |
|
59 docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1"); |
|
60 diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h |
27 diff --git a/content/html/content/public/nsHTMLMediaElement.h b/content/html/content/public/nsHTMLMediaElement.h |
61 --- a/content/html/content/public/nsHTMLMediaElement.h |
28 --- a/content/html/content/public/nsHTMLMediaElement.h |
62 +++ b/content/html/content/public/nsHTMLMediaElement.h |
29 +++ b/content/html/content/public/nsHTMLMediaElement.h |
63 @@ -263,17 +263,19 @@ public: |
30 @@ -263,17 +263,19 @@ public: |
64 void UpdateMediaSize(nsIntSize size); |
31 void UpdateMediaSize(nsIntSize size); |
79 static CanPlayStatus GetCanPlay(const nsAString& aType); |
46 static CanPlayStatus GetCanPlay(const nsAString& aType); |
80 |
47 |
81 // Returns true if we should handle this MIME type when it appears |
48 // Returns true if we should handle this MIME type when it appears |
82 // as an <object> or as a toplevel page. If, in practice, our support |
49 // as an <object> or as a toplevel page. If, in practice, our support |
83 // for the type is more limited than appears in the wild, we should return |
50 // for the type is more limited than appears in the wild, we should return |
84 @@ -303,20 +305,17 @@ public: |
51 @@ -305,19 +307,16 @@ public: |
85 #ifdef MOZ_WEBM |
|
86 static bool IsWebMEnabled(); |
|
87 static bool IsWebMType(const nsACString& aType); |
52 static bool IsWebMType(const nsACString& aType); |
88 static const char gWebMTypes[2][11]; |
53 static const char gWebMTypes[2][11]; |
89 static char const *const gWebMCodecs[4]; |
54 static char const *const gWebMCodecs[4]; |
90 #endif |
55 #endif |
91 |
56 |
92 #ifdef MOZ_GSTREAMER |
57 #ifdef MOZ_GSTREAMER |
93 - static bool IsH264Enabled(); |
58 static bool IsGStreamerEnabled(); |
|
59 static bool IsGStreamerSupportedType(const nsACString& aType); |
94 - static bool IsH264Type(const nsACString& aType); |
60 - static bool IsH264Type(const nsACString& aType); |
95 - static const char gH264Types[3][16]; |
61 - static const char gH264Types[3][16]; |
96 - static char const *const gH264Codecs[7]; |
62 - static char const *const gH264Codecs[7]; |
97 + static bool IsGStreamerEnabled(); |
|
98 #endif |
63 #endif |
99 |
64 |
100 #ifdef MOZ_WIDGET_GONK |
65 #ifdef MOZ_WIDGET_GONK |
101 static bool IsOmxEnabled(); |
66 static bool IsOmxEnabled(); |
102 static bool IsOmxSupportedType(const nsACString& aType); |
67 static bool IsOmxSupportedType(const nsACString& aType); |
133 - "video/mp4", |
98 - "video/mp4", |
134 - "video/3gpp", |
99 - "video/3gpp", |
135 - "video/quicktime", |
100 - "video/quicktime", |
136 -}; |
101 -}; |
137 - |
102 - |
138 -bool |
103 bool |
139 -nsHTMLMediaElement::IsH264Enabled() |
104 nsHTMLMediaElement::IsGStreamerEnabled() |
140 +bool nsHTMLMediaElement::IsGStreamerEnabled() |
105 { |
141 { |
106 return Preferences::GetBool("media.gstreamer.enabled"); |
142 - return Preferences::GetBool("media.h264.enabled"); |
107 } |
143 -} |
|
144 - |
108 - |
145 -bool |
109 -bool |
146 -nsHTMLMediaElement::IsH264Type(const nsACString& aType) |
110 -nsHTMLMediaElement::IsH264Type(const nsACString& aType) |
147 -{ |
111 -{ |
148 - if (!IsH264Enabled()) { |
|
149 - return false; |
|
150 - } |
|
151 - |
|
152 - for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) { |
112 - for (uint32_t i = 0; i < ArrayLength(gH264Types); ++i) { |
153 - if (aType.EqualsASCII(gH264Types[i])) { |
113 - if (aType.EqualsASCII(gH264Types[i])) { |
154 - return true; |
114 - return true; |
155 - } |
115 - } |
156 - } |
116 - } |
157 - |
|
158 - return false; |
117 - return false; |
159 + return Preferences::GetBool("media.gstreamer.enabled"); |
118 -} |
160 } |
|
161 #endif |
119 #endif |
162 |
120 |
163 #ifdef MOZ_WIDGET_GONK |
121 #ifdef MOZ_WIDGET_GONK |
164 const char nsHTMLMediaElement::gOmxTypes[5][16] = { |
122 const char nsHTMLMediaElement::gOmxTypes[5][16] = { |
165 "audio/mpeg", |
123 "audio/mpeg", |
166 "audio/mp4", |
124 "audio/mp4", |
167 "video/mp4", |
125 "video/mp4", |
168 @@ -2262,18 +2239,22 @@ nsHTMLMediaElement::IsDASHMPDType(const |
126 "video/3gpp", |
|
127 @@ -2257,18 +2240,22 @@ nsHTMLMediaElement::IsDASHMPDType(const |
169 |
128 |
170 return false; |
129 return false; |
171 } |
130 } |
172 #endif |
131 #endif |
173 |
132 |
270 CanPlayStatus result = CANPLAY_YES; |
229 CanPlayStatus result = CANPLAY_YES; |
271 // See http://www.rfc-editor.org/rfc/rfc4281.txt for the description |
230 // See http://www.rfc-editor.org/rfc/rfc4281.txt for the description |
272 // of the 'codecs' parameter |
231 // of the 'codecs' parameter |
273 nsCharSeparatedTokenizer tokenizer(codecs, ','); |
232 nsCharSeparatedTokenizer tokenizer(codecs, ','); |
274 bool expectMoreTokens = false; |
233 bool expectMoreTokens = false; |
275 @@ -2486,17 +2474,19 @@ nsHTMLMediaElement::CreateDecoder(const |
234 @@ -2425,46 +2419,41 @@ nsHTMLMediaElement::CanPlayType(const ns |
|
235 } |
|
236 |
|
237 #ifdef MOZ_GSTREAMER |
|
238 bool |
|
239 nsHTMLMediaElement::IsGStreamerSupportedType(const nsACString& aMimeType) |
|
240 { |
|
241 if (!IsGStreamerEnabled()) |
|
242 return false; |
|
243 - if (IsH264Type(aMimeType)) |
|
244 + |
|
245 + const char *type; |
|
246 + NS_CStringGetData(aMimeType, &type, nullptr); |
|
247 + if (nsGStreamerDecoder::CanHandleMediaType(type, nullptr)) |
|
248 return true; |
|
249 - if (!Preferences::GetBool("media.prefer-gstreamer", false)) |
|
250 - return false; |
|
251 -#ifdef MOZ_WEBM |
|
252 - if (IsWebMType(aMimeType)) |
|
253 - return true; |
|
254 -#endif |
|
255 -#ifdef MOZ_OGG |
|
256 - if (IsOggType(aMimeType)) |
|
257 - return true; |
|
258 -#endif |
|
259 + |
|
260 return false; |
|
261 } |
|
262 #endif |
|
263 |
|
264 already_AddRefed<nsMediaDecoder> |
|
265 nsHTMLMediaElement::CreateDecoder(const nsACString& aType) |
|
266 { |
|
267 #ifdef MOZ_GSTREAMER |
|
268 // When enabled, use GStreamer for H.264, but not for codecs handled by our |
|
269 // bundled decoders, unless the "media.prefer-gstreamer" pref is set. |
|
270 - if (IsGStreamerSupportedType(aType)) { |
|
271 - nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder(); |
|
272 - if (decoder->Init(this)) { |
|
273 - return decoder.forget(); |
|
274 + if (!Preferences::GetBool("media.prefer-gstreamer", false)) { |
|
275 + if (IsGStreamerSupportedType(aType)) { |
|
276 + nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder(); |
|
277 + if (decoder->Init(this)) { |
|
278 + return decoder.forget(); |
|
279 + } |
|
280 } |
|
281 } |
|
282 #endif |
|
283 - |
|
284 #ifdef MOZ_RAW |
|
285 if (IsRawType(aType)) { |
|
286 nsRefPtr<nsRawDecoder> decoder = new nsRawDecoder(); |
|
287 if (decoder->Init(this)) { |
|
288 return decoder.forget(); |
|
289 } |
|
290 } |
|
291 #endif |
|
292 @@ -2503,25 +2492,33 @@ nsHTMLMediaElement::CreateDecoder(const |
|
293 #ifdef MOZ_WEBM |
|
294 if (IsWebMType(aType)) { |
|
295 nsRefPtr<nsWebMDecoder> decoder = new nsWebMDecoder(); |
|
296 if (decoder->Init(this)) { |
|
297 return decoder.forget(); |
|
298 } |
|
299 } |
|
300 #endif |
|
301 - |
|
302 #ifdef MOZ_DASH |
|
303 if (IsDASHMPDType(aType)) { |
276 nsRefPtr<nsDASHDecoder> decoder = new nsDASHDecoder(); |
304 nsRefPtr<nsDASHDecoder> decoder = new nsDASHDecoder(); |
277 if (decoder->Init(this)) { |
305 if (decoder->Init(this)) { |
278 return decoder.forget(); |
306 return decoder.forget(); |
279 } |
307 } |
280 } |
308 } |
281 #endif |
309 #endif |
282 |
310 +#ifdef MOZ_GSTREAMER |
283 #ifdef MOZ_GSTREAMER |
311 + // use GStreamer as fallback if not preferred |
284 - if (IsH264Type(aType)) { |
312 + if (IsGStreamerSupportedType(aType)) { |
285 + const char *type; |
313 + nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder(); |
286 + NS_CStringGetData(aType, &type, NULL); |
314 + if (decoder->Init(this)) { |
287 + if (nsGStreamerDecoder::CanHandleMediaType(type, NULL)) { |
315 + return decoder.forget(); |
288 nsRefPtr<nsGStreamerDecoder> decoder = new nsGStreamerDecoder(); |
316 + } |
289 if (decoder->Init(this)) { |
317 + } |
290 return decoder.forget(); |
318 +#endif |
291 } |
319 |
292 } |
|
293 #endif |
|
294 return nullptr; |
320 return nullptr; |
295 } |
321 } |
|
322 |
|
323 nsresult nsHTMLMediaElement::InitializeDecoderAsClone(nsMediaDecoder* aOriginal) |
|
324 { |
|
325 NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set"); |
|
326 NS_ASSERTION(mDecoder == nullptr, "Shouldn't have a decoder"); |
296 diff --git a/content/media/gstreamer/Makefile.in b/content/media/gstreamer/Makefile.in |
327 diff --git a/content/media/gstreamer/Makefile.in b/content/media/gstreamer/Makefile.in |
297 --- a/content/media/gstreamer/Makefile.in |
328 --- a/content/media/gstreamer/Makefile.in |
298 +++ b/content/media/gstreamer/Makefile.in |
329 +++ b/content/media/gstreamer/Makefile.in |
299 @@ -17,16 +17,17 @@ LIBXUL_LIBRARY = 1 |
330 @@ -17,16 +17,17 @@ LIBXUL_LIBRARY = 1 |
300 |
331 |
369 +#include "nsXPCOMStrings.h" |
400 +#include "nsXPCOMStrings.h" |
370 + |
401 + |
371 +#define ENTRY_FORMAT(entry) entry[0] |
402 +#define ENTRY_FORMAT(entry) entry[0] |
372 +#define ENTRY_CAPS(entry) entry[1] |
403 +#define ENTRY_CAPS(entry) entry[1] |
373 + |
404 + |
374 +nsGStreamerFormatHelper* nsGStreamerFormatHelper::gInstance = NULL; |
405 +nsGStreamerFormatHelper* nsGStreamerFormatHelper::gInstance = nullptr; |
375 + |
406 + |
376 +nsGStreamerFormatHelper *nsGStreamerFormatHelper::Instance() { |
407 +nsGStreamerFormatHelper *nsGStreamerFormatHelper::Instance() { |
377 + if (!gInstance) { |
408 + if (!gInstance) { |
378 + gst_init(NULL, NULL); |
409 + gst_init(nullptr, nullptr); |
379 + gInstance = new nsGStreamerFormatHelper(); |
410 + gInstance = new nsGStreamerFormatHelper(); |
380 + } |
411 + } |
381 + |
412 + |
382 + return gInstance; |
413 + return gInstance; |
383 +} |
414 +} |
384 + |
415 + |
385 +nsGStreamerFormatHelper::nsGStreamerFormatHelper() |
416 +nsGStreamerFormatHelper::nsGStreamerFormatHelper() |
386 + : mFactories(NULL), |
417 + : mFactories(nullptr), |
387 + mCookie(0) |
418 + mCookie(0) |
388 +{ |
419 +{ |
389 + const char *containers[3][2] = { |
420 + const char *containers[3][2] = { |
390 + {"video/mp4", "video/quicktime"}, |
421 + {"video/mp4", "video/quicktime"}, |
391 + {"audio/mp4", "audio/mpeg, mpegversion=(int)4"}, |
422 + {"audio/mp4", "audio/mpeg, mpegversion=(int)4"}, |
426 +GstCaps *nsGStreamerFormatHelper::ConvertFormatsToCaps(const char *aMIMEType, |
457 +GstCaps *nsGStreamerFormatHelper::ConvertFormatsToCaps(const char *aMIMEType, |
427 + const char *aCodecs) { |
458 + const char *aCodecs) { |
428 + unsigned int i; |
459 + unsigned int i; |
429 + |
460 + |
430 + /* convert aMIMEType to gst container caps */ |
461 + /* convert aMIMEType to gst container caps */ |
431 + const char *capsString = NULL; |
462 + const char *capsString = nullptr; |
432 + for (i = 0; i < G_N_ELEMENTS(mContainers); i++) { |
463 + for (i = 0; i < G_N_ELEMENTS(mContainers); i++) { |
433 + if (!strcmp(ENTRY_FORMAT(mContainers[i]), aMIMEType)) { |
464 + if (!strcmp(ENTRY_FORMAT(mContainers[i]), aMIMEType)) { |
434 + capsString = ENTRY_CAPS(mContainers[i]); |
465 + capsString = ENTRY_CAPS(mContainers[i]); |
435 + break; |
466 + break; |
436 + } |
467 + } |
437 + } |
468 + } |
438 + |
469 + |
439 + if (!capsString) { |
470 + if (!capsString) { |
440 + /* we couldn't find any matching caps */ |
471 + /* we couldn't find any matching caps */ |
441 + return NULL; |
472 + return nullptr; |
442 + } |
473 + } |
443 + |
474 + |
444 + GstCaps *caps = gst_caps_from_string(capsString); |
475 + GstCaps *caps = gst_caps_from_string(capsString); |
445 + /* container only */ |
476 + /* container only */ |
446 + if (!aCodecs) { |
477 + if (!aCodecs) { |
449 + |
480 + |
450 + nsDependentCSubstring codecs(aCodecs, strlen(aCodecs)); |
481 + nsDependentCSubstring codecs(aCodecs, strlen(aCodecs)); |
451 + nsCCharSeparatedTokenizer tokenizer(codecs, ','); |
482 + nsCCharSeparatedTokenizer tokenizer(codecs, ','); |
452 + while (tokenizer.hasMoreTokens()) { |
483 + while (tokenizer.hasMoreTokens()) { |
453 + const nsCSubstring& codec = tokenizer.nextToken(); |
484 + const nsCSubstring& codec = tokenizer.nextToken(); |
454 + capsString = NULL; |
485 + capsString = nullptr; |
455 + |
486 + |
456 + for (i = 0; i < G_N_ELEMENTS(mCodecs); i++) { |
487 + for (i = 0; i < G_N_ELEMENTS(mCodecs); i++) { |
457 + if (codec.Equals(ENTRY_FORMAT(mCodecs[i]))) { |
488 + if (codec.Equals(ENTRY_FORMAT(mCodecs[i]))) { |
458 + capsString = ENTRY_CAPS(mCodecs[i]); |
489 + capsString = ENTRY_CAPS(mCodecs[i]); |
459 + break; |
490 + break; |
460 + } |
491 + } |
461 + } |
492 + } |
462 + |
493 + |
463 + if (!capsString) { |
494 + if (!capsString) { |
464 + gst_caps_unref(caps); |
495 + gst_caps_unref(caps); |
465 + return NULL; |
496 + return nullptr; |
466 + } |
497 + } |
467 + |
498 + |
468 + GstCaps *tmp = gst_caps_from_string(capsString); |
499 + GstCaps *tmp = gst_caps_from_string(capsString); |
469 + /* appends and frees tmp */ |
500 + /* appends and frees tmp */ |
470 + gst_caps_append(caps, tmp); |
501 + gst_caps_append(caps, tmp); |
481 + /* here aCaps contains [containerCaps, [codecCaps1, [codecCaps2, ...]]] so process |
512 + /* here aCaps contains [containerCaps, [codecCaps1, [codecCaps2, ...]]] so process |
482 + * caps structures individually as we want one element for _each_ |
513 + * caps structures individually as we want one element for _each_ |
483 + * structure */ |
514 + * structure */ |
484 + for (unsigned int i = 0; i < gst_caps_get_size(aCaps); i++) { |
515 + for (unsigned int i = 0; i < gst_caps_get_size(aCaps); i++) { |
485 + GstStructure *s = gst_caps_get_structure(aCaps, i); |
516 + GstStructure *s = gst_caps_get_structure(aCaps, i); |
486 + GstCaps *caps = gst_caps_new_full(gst_structure_copy(s), NULL); |
517 + GstCaps *caps = gst_caps_new_full(gst_structure_copy(s), nullptr); |
487 + list = gst_element_factory_list_filter (factories, caps, GST_PAD_SINK, FALSE); |
518 + list = gst_element_factory_list_filter (factories, caps, GST_PAD_SINK, FALSE); |
488 + gst_caps_unref(caps); |
519 + gst_caps_unref(caps); |
489 + if (!list) { |
520 + if (!list) { |
490 + return false; |
521 + return false; |
491 + } |
522 + } |