commit 7eb5827 Author: Edwin Flores 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 --- content/media/gstreamer/GStreamerFormatHelper.cpp +++ 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(-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; } }