commit 7eb5827
Author: Edwin Flores <eflores@mozilla.com>
Date: Sat Jul 20 12:03:08 2013 +1200
Bug 889699 - Make gstreamer backend return more accurate results for canPlayType() r=alessandro.d
---
content/media/gstreamer/GStreamerFormatHelper.cpp | 90 +++++++++++++++++------
1 file changed, 66 insertions(+), 24 deletions(-)
diff --git content/media/gstreamer/GStreamerFormatHelper.cpp content/media/gstreamer/GStreamerFormatHelper.cpp
index f05ff8f..39f1fdf 100644
--- mozilla/content/media/gstreamer/GStreamerFormatHelper.cpp
+++ mozilla/content/media/gstreamer/GStreamerFormatHelper.cpp
@@ -6,7 +6,7 @@
#include "GStreamerFormatHelper.h"
#include "nsCharSeparatedTokenizer.h"
-#include "nsXPCOMStrings.h"
+#include "nsString.h"
#include "GStreamerLoader.h"
#define ENTRY_FORMAT(entry) entry[0]
@@ -36,7 +36,7 @@ void GStreamerFormatHelper::Shutdown() {
}
}
-char const *const GStreamerFormatHelper::mContainers[6][2] = {
+static char const *const sContainers[6][2] = {
{"video/mp4", "video/quicktime"},
{"video/quicktime", "video/quicktime"},
{"audio/mp4", "audio/x-m4a"},
@@ -45,7 +45,7 @@ char const *const GStreamerFormatHelper::mContainers[6][2] = {
{"audio/mp3", "audio/mpeg, mpegversion=(int)1"},
};
-char const *const GStreamerFormatHelper::mCodecs[9][2] = {
+static char const *const sCodecs[9][2] = {
{"avc1.42E01E", "video/x-h264"},
{"avc1.42001E", "video/x-h264"},
{"avc1.58A01E", "video/x-h264"},
@@ -57,6 +57,15 @@ char const *const GStreamerFormatHelper::mCodecs[9][2] = {
{"mp3", "audio/mpeg, mpegversion=(int)1"},
};
+static char const * const sDefaultCodecCaps[][2] = {
+ {"video/mp4", "video/x-h264"},
+ {"video/quicktime", "video/x-h264"},
+ {"audio/mp4", "audio/mpeg, mpegversion=(int)4"},
+ {"audio/x-m4a", "audio/mpeg, mpegversion=(int)4"},
+ {"audio/mp3", "audio/mpeg, layer=(int)3"},
+ {"audio/mpeg", "audio/mpeg, layer=(int)3"}
+};
+
GStreamerFormatHelper::GStreamerFormatHelper()
: mFactories(nullptr),
mCookie(static_cast<uint32_t>(-1))
@@ -66,15 +75,15 @@ GStreamerFormatHelper::GStreamerFormatHelper()
}
mSupportedContainerCaps = gst_caps_new_empty();
- for (unsigned int i = 0; i < G_N_ELEMENTS(mContainers); i++) {
- const char* capsString = mContainers[i][1];
+ for (unsigned int i = 0; i < G_N_ELEMENTS(sContainers); i++) {
+ const char* capsString = sContainers[i][1];
GstCaps* caps = gst_caps_from_string(capsString);
gst_caps_append(mSupportedContainerCaps, caps);
}
mSupportedCodecCaps = gst_caps_new_empty();
- for (unsigned int i = 0; i < G_N_ELEMENTS(mCodecs); i++) {
- const char* capsString = mCodecs[i][1];
+ for (unsigned int i = 0; i < G_N_ELEMENTS(sCodecs); i++) {
+ const char* capsString = sCodecs[i][1];
GstCaps* caps = gst_caps_from_string(capsString);
gst_caps_append(mSupportedCodecCaps, caps);
}
@@ -92,6 +101,41 @@ GStreamerFormatHelper::~GStreamerFormatHelper() {
g_list_free(mFactories);
}
+static GstCaps *
+GetContainerCapsFromMIMEType(const char *aType) {
+ /* convert aMIMEType to gst container caps */
+ const char* capsString = nullptr;
+ for (uint32_t i = 0; i < G_N_ELEMENTS(sContainers); i++) {
+ if (!strcmp(ENTRY_FORMAT(sContainers[i]), aType)) {
+ capsString = ENTRY_CAPS(sContainers[i]);
+ break;
+ }
+ }
+
+ if (!capsString) {
+ /* we couldn't find any matching caps */
+ return nullptr;
+ }
+
+ return gst_caps_from_string(capsString);
+}
+
+static GstCaps *
+GetDefaultCapsFromMIMEType(const char *aType) {
+ GstCaps *caps = GetContainerCapsFromMIMEType(aType);
+
+ for (uint32_t i = 0; i < G_N_ELEMENTS(sDefaultCodecCaps); i++) {
+ if (!strcmp(sDefaultCodecCaps[i][0], aType)) {
+ GstCaps *tmp = gst_caps_from_string(sDefaultCodecCaps[i][1]);
+
+ gst_caps_append(caps, tmp);
+ return caps;
+ }
+ }
+
+ return nullptr;
+}
+
bool GStreamerFormatHelper::CanHandleMediaType(const nsACString& aMIMEType,
const nsAString* aCodecs) {
if (!sLoadOK) {
@@ -101,7 +145,15 @@ bool GStreamerFormatHelper::CanHandleMediaType(const nsACString& aMIMEType,
const char *type;
NS_CStringGetData(aMIMEType, &type, NULL);
- GstCaps* caps = ConvertFormatsToCaps(type, aCodecs);
+ GstCaps *caps;
+ if (aCodecs && !aCodecs->IsEmpty()) {
+ caps = ConvertFormatsToCaps(type, aCodecs);
+ } else {
+ // Get a minimal set of codec caps for this MIME type we should support so
+ // that we don't overreport MIME types we are able to play.
+ caps = GetDefaultCapsFromMIMEType(type);
+ }
+
if (!caps) {
return false;
}
@@ -118,21 +170,11 @@ GstCaps* GStreamerFormatHelper::ConvertFormatsToCaps(const char* aMIMEType,
unsigned int i;
- /* convert aMIMEType to gst container caps */
- const char* capsString = nullptr;
- for (i = 0; i < G_N_ELEMENTS(mContainers); i++) {
- if (!strcmp(ENTRY_FORMAT(mContainers[i]), aMIMEType)) {
- capsString = ENTRY_CAPS(mContainers[i]);
- break;
- }
- }
-
- if (!capsString) {
- /* we couldn't find any matching caps */
+ GstCaps *caps = GetContainerCapsFromMIMEType(aMIMEType);
+ if (!caps) {
return nullptr;
}
- GstCaps* caps = gst_caps_from_string(capsString);
/* container only */
if (!aCodecs) {
return caps;
@@ -141,11 +183,11 @@ GstCaps* GStreamerFormatHelper::ConvertFormatsToCaps(const char* aMIMEType,
nsCharSeparatedTokenizer tokenizer(*aCodecs, ',');
while (tokenizer.hasMoreTokens()) {
const nsSubstring& codec = tokenizer.nextToken();
- capsString = nullptr;
+ const char *capsString = nullptr;
- for (i = 0; i < G_N_ELEMENTS(mCodecs); i++) {
- if (codec.EqualsASCII(ENTRY_FORMAT(mCodecs[i]))) {
- capsString = ENTRY_CAPS(mCodecs[i]);
+ for (i = 0; i < G_N_ELEMENTS(sCodecs); i++) {
+ if (codec.EqualsASCII(ENTRY_FORMAT(sCodecs[i]))) {
+ capsString = ENTRY_CAPS(sCodecs[i]);
break;
}
}