Bug 1037754: Query GMPService to determine if H.264 is available r=cpearce

This commit is contained in:
Randell Jesup 2014-07-16 22:59:17 -04:00
parent 3bade8183d
commit f9990e063e
6 changed files with 127 additions and 29 deletions

View File

@ -14,6 +14,7 @@
#include "mozilla/Services.h"
#include "nsNativeCharsetUtils.h"
#include "nsIConsoleService.h"
#include "mozilla/unused.h"
namespace mozilla {
namespace gmp {
@ -113,6 +114,10 @@ GeckoMediaPluginService::Init()
MOZ_ASSERT(obsService);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)));
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false)));
// Kick off scanning for plugins
nsCOMPtr<nsIThread> thread;
unused << GetThread(getter_AddRefs(thread));
}
NS_IMETHODIMP
@ -255,6 +260,7 @@ GeckoMediaPluginService::UnloadPlugins()
MOZ_ASSERT(!mShuttingDownOnGMPThread);
mShuttingDownOnGMPThread = true;
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
mPlugins[i]->UnloadProcess();
}
@ -330,13 +336,28 @@ GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
return NS_OK;
}
NS_IMETHODIMP
GeckoMediaPluginService::HasPluginForAPI(const nsAString& aOrigin,
const nsACString& aAPI,
nsTArray<nsCString>* aTags,
bool* aResult)
{
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aResult);
nsCString temp(aAPI);
GMPParent *parent = SelectPluginForAPI(aOrigin, temp, *aTags);
*aResult = !!parent;
return NS_OK;
}
GMPParent*
GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin,
const nsCString& aAPI,
const nsTArray<nsCString>& aTags)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); i++) {
GMPParent* gmp = mPlugins[i];
bool supportsAllTags = true;
@ -402,6 +423,7 @@ GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory)
return;
}
MutexAutoLock lock(mMutex);
mPlugins.AppendElement(gmp);
}
@ -416,6 +438,7 @@ GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
return;
}
MutexAutoLock lock(mMutex);
for (uint32_t i = 0; i < mPlugins.Length(); ++i) {
nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
bool equals;

View File

@ -69,8 +69,8 @@ private:
bool mAdd;
};
Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
nsTArray<nsRefPtr<GMPParent>> mPlugins;
Mutex mMutex; // Protects mGMPThread and mShuttingDown
nsCOMPtr<nsIThread> mGMPThread;
bool mShuttingDown;
bool mShuttingDownOnGMPThread;

View File

@ -21,7 +21,7 @@ class GMPVideoHost;
[ptr] native MessageLoop(MessageLoop);
[ptr] native TagArray(nsTArray<nsCString>);
[scriptable, uuid(7cef50ca-7a0f-41f2-9560-47abf709f0d7)]
[scriptable, uuid(a9b826da-725a-4b81-814f-b715445188f2)]
interface mozIGeckoMediaPluginService : nsISupports
{
/**
@ -29,6 +29,15 @@ interface mozIGeckoMediaPluginService : nsISupports
*/
readonly attribute nsIThread thread;
/**
* Get a plugin that supports the specified tags.
* Callable on any thread
*/
[noscript]
boolean hasPluginForAPI([optional] in AString origin,
in ACString api,
in TagArray tags);
/**
* Get a video decoder that supports the specified tags.
* The array of tags should at least contain a codec tag, and optionally

View File

@ -146,7 +146,7 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
GMPVideoEncoderProxy* gmp = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("vp8"));
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
nsresult rv = mMPS->GetGMPVideoEncoder(&tags,
NS_LITERAL_STRING(""),
&host,
@ -178,7 +178,7 @@ WebrtcGmpVideoEncoder::InitEncode_g(const webrtc::VideoCodec* aCodecSettings,
nsTArray<uint8_t> codecSpecific;
// H.264 mode 1 only supported so far
GMPErr err = mGMP->InitEncode(codec, codecSpecific, this, 1, 256000 /*aMaxPayloadSize*/);
GMPErr err = mGMP->InitEncode(codec, codecSpecific, this, 1, 1024*1024 /*aMaxPayloadSize*/);
if (err != GMPNoErr) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
@ -418,7 +418,7 @@ WebrtcGmpVideoDecoder::InitDecode_g(const webrtc::VideoCodec* aCodecSettings,
GMPVideoDecoderProxy* gmp = nullptr;
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("vp8"));
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
if (NS_WARN_IF(NS_FAILED(mMPS->GetGMPVideoDecoder(&tags,
NS_LITERAL_STRING(""),
&host,

View File

@ -89,6 +89,7 @@ using namespace mozilla;
using namespace CSF;
VcmSIPCCBinding * VcmSIPCCBinding::gSelf = nullptr;
bool VcmSIPCCBinding::gInitGmpCodecs = false;
int VcmSIPCCBinding::gAudioCodecMask = 0;
int VcmSIPCCBinding::gVideoCodecMask = 0;
int VcmSIPCCBinding::gVideoCodecGmpMask = 0;
@ -228,12 +229,6 @@ void VcmSIPCCBinding::setVideoCodecs(int codecMask)
VcmSIPCCBinding::gVideoCodecMask = codecMask;
}
void VcmSIPCCBinding::addVideoCodecsGmp(int codecMask)
{
CSFLogDebug(logTag, "ADDING VIDEO: %d", codecMask);
VcmSIPCCBinding::gVideoCodecGmpMask |= codecMask;
}
int VcmSIPCCBinding::getAudioCodecs()
{
return VcmSIPCCBinding::gAudioCodecMask;
@ -244,9 +239,76 @@ int VcmSIPCCBinding::getVideoCodecs()
return VcmSIPCCBinding::gVideoCodecMask;
}
static void GMPDummy() {};
bool VcmSIPCCBinding::scanForGmpCodecs()
{
if (!gSelf) {
return false;
}
if (!gSelf->mGMPService) {
gSelf->mGMPService = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
if (!gSelf->mGMPService) {
return false;
}
}
// XXX find a way to a) do this earlier, b) not block mainthread
// Perhaps fire on first RTCPeerconnection creation, and block
// processing (async) CreateOffer or CreateAnswer's until it has returned.
// Since they're already async, it's easy to avoid starting them there.
// However, we might like to do it even earlier, perhaps.
// XXX We shouldn't be blocking MainThread on the GMP thread!
// This initiates the scan for codecs
nsIThread *thread;
nsresult rv = gSelf->mGMPService->GetThread(&thread);
if (NS_FAILED(rv)) {
return false;
}
// presumes that all GMP dir scans have been queued for the GMPThread
RUN_ON_THREAD(thread,
WrapRunnableNM(&GMPDummy),
NS_DISPATCH_SYNC);
return true;
}
int VcmSIPCCBinding::getVideoCodecsGmp()
{
return VcmSIPCCBinding::gVideoCodecGmpMask;
if (!gInitGmpCodecs) {
if (scanForGmpCodecs()) {
gInitGmpCodecs = true;
}
}
if (gInitGmpCodecs) {
if (!gSelf->mGMPService) {
gSelf->mGMPService = do_GetService("@mozilla.org/gecko-media-plugin-service;1");
}
if (gSelf->mGMPService) {
// XXX I'd prefer if this was all known ahead of time...
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
// H.264 only for now
bool has_gmp;
nsresult rv;
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_STRING(""),
NS_LITERAL_CSTRING("encode-video"),
&tags,
&has_gmp);
if (NS_SUCCEEDED(rv) && has_gmp) {
rv = gSelf->mGMPService->HasPluginForAPI(NS_LITERAL_STRING(""),
NS_LITERAL_CSTRING("decode-video"),
&tags,
&has_gmp);
if (NS_SUCCEEDED(rv) && has_gmp) {
return VCM_CODEC_RESOURCE_H264;
}
}
}
}
return 0;
}
int VcmSIPCCBinding::getVideoCodecsHw()

View File

@ -11,6 +11,7 @@ extern "C"
}
#include "sigslot.h"
#include "mozIGeckoMediaPluginService.h"
class nsIThread;
class nsIEventTarget;
@ -32,11 +33,12 @@ namespace CSF
class StreamObserver
{
public:
virtual void registerStream(cc_call_handle_t call, int streamId, bool isVideo) = 0;
virtual void deregisterStream(cc_call_handle_t call, int streamId) = 0;
virtual void dtmfBurst(int digit, int direction, int duration) = 0;
virtual void sendIFrame(cc_call_handle_t call) = 0;
virtual void registerStream(cc_call_handle_t call, int streamId, bool isVideo) = 0;
virtual void deregisterStream(cc_call_handle_t call, int streamId) = 0;
virtual void dtmfBurst(int digit, int direction, int duration) = 0;
virtual void sendIFrame(cc_call_handle_t call) = 0;
};
class VcmSIPCCBinding : public sigslot::has_slots<>
{
public:
@ -58,35 +60,37 @@ namespace CSF
static void setAudioCodecs(int codecMask);
static void setVideoCodecs(int codecMask);
static void addVideoCodecsGmp(int codecMask);
static int getAudioCodecs();
static int getVideoCodecs();
static int getVideoCodecsGmp();
static int getVideoCodecsHw();
static void setMainThread(nsIThread *thread);
static nsIThread *getMainThread();
static nsIEventTarget *getSTSThread();
static void setMainThread(nsIThread *thread);
static nsIThread *getMainThread();
static nsIEventTarget *getSTSThread();
static void setSTSThread(nsIEventTarget *thread);
static void setSTSThread(nsIEventTarget *thread);
static void connectCandidateSignal(mozilla::NrIceMediaStream* stream);
static void connectCandidateSignal(mozilla::NrIceMediaStream* stream);
static nsCOMPtr<nsIPrefBranch> getPrefBranch();
static int gVideoCodecGmpMask;
private:
void CandidateReady(mozilla::NrIceMediaStream* stream,
const std::string& candidate);
static bool scanForGmpCodecs();
void CandidateReady(mozilla::NrIceMediaStream* stream,
const std::string& candidate);
nsCOMPtr<mozIGeckoMediaPluginService> mGMPService;
static VcmSIPCCBinding * gSelf;
StreamObserver* streamObserver;
MediaProviderObserver *mediaProviderObserver;
static bool gInitGmpCodecs;
static int gAudioCodecMask;
static int gVideoCodecMask;
static int gVideoCodecGmpMask;
static nsIThread *gMainThread;
static nsIEventTarget *gSTSThread;
static nsIThread *gMainThread;
static nsIEventTarget *gSTSThread;
static nsCOMPtr<nsIPrefBranch> gBranch;
};
}