[WebRTC] updated to upstream branch 49 and related.

this patch is based on 38d7a7883...226f2f0bd
This commit is contained in:
roytam1 2021-10-01 10:48:39 +08:00
commit a3239eaa4d
2838 changed files with 151221 additions and 159688 deletions

View file

@ -5,7 +5,6 @@
#include "CamerasChild.h"
#include "webrtc/video_engine/include/vie_capture.h"
#undef FF
#include "mozilla/Assertions.h"
@ -336,7 +335,7 @@ int
CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
const char* unique_idUTF8,
const unsigned int capability_number,
webrtc::CaptureCapability& capability)
webrtc::VideoCaptureCapability& capability)
{
LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
RefPtr<CamerasChild> deathGrip = this;
@ -352,7 +351,7 @@ CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
}
bool
CamerasChild::RecvReplyGetCaptureCapability(const CaptureCapability& ipcCapability)
CamerasChild::RecvReplyGetCaptureCapability(const VideoCaptureCapability& ipcCapability)
{
LOG((__PRETTY_FUNCTION__));
MonitorAutoLock monitor(mReplyMonitor);
@ -414,7 +413,7 @@ int
CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
const char* unique_idUTF8,
const unsigned int unique_idUTF8Length,
int& capture_id,
int& aStreamId,
const nsACString& aOrigin)
{
LOG((__PRETTY_FUNCTION__));
@ -427,7 +426,7 @@ CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
LockAndDispatch<> dispatcher(this, __func__, runnable);
if (dispatcher.Success()) {
LOG(("Capture Device allocated: %d", mReplyInteger));
capture_id = mReplyInteger;
aStreamId = mReplyInteger;
}
return dispatcher.ReturnValue();
}
@ -460,7 +459,7 @@ CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
void
CamerasChild::AddCallback(const CaptureEngine aCapEngine, const int capture_id,
webrtc::ExternalRenderer* render)
FrameRelay* render)
{
MutexAutoLock lock(mCallbackMutex);
CapturerElement ce;
@ -486,12 +485,12 @@ CamerasChild::RemoveCallback(const CaptureEngine aCapEngine, const int capture_i
int
CamerasChild::StartCapture(CaptureEngine aCapEngine,
const int capture_id,
webrtc::CaptureCapability& webrtcCaps,
webrtc::ExternalRenderer* cb)
webrtc::VideoCaptureCapability& webrtcCaps,
FrameRelay* cb)
{
LOG((__PRETTY_FUNCTION__));
AddCallback(aCapEngine, capture_id, cb);
CaptureCapability capCap(webrtcCaps.width,
VideoCaptureCapability capCap(webrtcCaps.width,
webrtcCaps.height,
webrtcCaps.maxFPS,
webrtcCaps.expectedCaptureDelay,
@ -500,7 +499,7 @@ CamerasChild::StartCapture(CaptureEngine aCapEngine,
webrtcCaps.interlaced);
RefPtr<CamerasChild> deathGrip = this;
nsCOMPtr<nsIRunnable> runnable =
mozilla::NewNonOwningRunnableMethod<CaptureEngine, int, CaptureCapability>
mozilla::NewNonOwningRunnableMethod<CaptureEngine, int, VideoCaptureCapability>
(this, &CamerasChild::SendStartCapture, aCapEngine, capture_id, capCap);
LockAndDispatch<> dispatcher(this, __func__, runnable);
return dispatcher.ReturnValue();
@ -617,18 +616,12 @@ bool
CamerasChild::RecvDeliverFrame(const CaptureEngine& capEngine,
const int& capId,
mozilla::ipc::Shmem&& shmem,
const size_t& size,
const uint32_t& time_stamp,
const int64_t& ntp_time,
const int64_t& render_time)
const VideoFrameProperties & prop)
{
MutexAutoLock lock(mCallbackMutex);
if (Callback(capEngine, capId)) {
unsigned char* image = shmem.get<unsigned char>();
Callback(capEngine, capId)->DeliverFrame(image, size,
time_stamp,
ntp_time, render_time,
nullptr);
Callback(capEngine, capId)->DeliverFrame(image, prop);
} else {
LOG(("DeliverFrame called with dead callback"));
}
@ -673,7 +666,7 @@ CamerasChild::RecvFrameSizeChange(const CaptureEngine& capEngine,
LOG((__PRETTY_FUNCTION__));
MutexAutoLock lock(mCallbackMutex);
if (Callback(capEngine, capId)) {
Callback(capEngine, capId)->FrameSizeChange(w, h, 0);
Callback(capEngine, capId)->FrameSizeChange(w, h);
} else {
LOG(("Frame size change with dead callback"));
}
@ -717,7 +710,7 @@ CamerasChild::~CamerasChild()
MOZ_COUNT_DTOR(CamerasChild);
}
webrtc::ExternalRenderer* CamerasChild::Callback(CaptureEngine aCapEngine,
FrameRelay* CamerasChild::Callback(CaptureEngine aCapEngine,
int capture_id)
{
for (unsigned int i = 0; i < mCallbacks.Length(); i++) {

View file

@ -19,10 +19,10 @@
// conflicts with #include of scoped_ptr.h
#undef FF
#include "webrtc/common.h"
// Video Engine
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_render.h"
#include "webrtc/video_renderer.h"
#include "webrtc/modules/video_capture/video_capture_defines.h"
namespace mozilla {
@ -32,10 +32,17 @@ class BackgroundChildImpl;
namespace camera {
class FrameRelay {
public:
virtual int DeliverFrame(uint8_t* buffer,
const mozilla::camera::VideoFrameProperties& props) = 0;
virtual void FrameSizeChange(unsigned int w, unsigned int h) = 0;
};
struct CapturerElement {
CaptureEngine engine;
int id;
webrtc::ExternalRenderer* callback;
FrameRelay* callback;
};
// Forward declaration so we can work with pointers to it.
@ -157,9 +164,9 @@ public:
// IPC messages recevied, received on the PBackground thread
// these are the actual callbacks with data
virtual bool RecvDeliverFrame(const CaptureEngine&, const int&, mozilla::ipc::Shmem&&,
const size_t&, const uint32_t&, const int64_t&,
const int64_t&) override;
virtual bool RecvDeliverFrame(const CaptureEngine&, const int&,
mozilla::ipc::Shmem&&,
const VideoFrameProperties & prop) override;
virtual bool RecvFrameSizeChange(const CaptureEngine&, const int&,
const int& w, const int& h) override;
@ -171,7 +178,7 @@ public:
virtual bool RecvReplyNumberOfCaptureDevices(const int&) override;
virtual bool RecvReplyNumberOfCapabilities(const int&) override;
virtual bool RecvReplyAllocateCaptureDevice(const int&) override;
virtual bool RecvReplyGetCaptureCapability(const CaptureCapability& capability) override;
virtual bool RecvReplyGetCaptureCapability(const VideoCaptureCapability& capability) override;
virtual bool RecvReplyGetCaptureDevice(const nsCString& device_name,
const nsCString& device_id,
const bool& scary) override;
@ -188,8 +195,8 @@ public:
int ReleaseCaptureDevice(CaptureEngine aCapEngine,
const int capture_id);
int StartCapture(CaptureEngine aCapEngine,
const int capture_id, webrtc::CaptureCapability& capability,
webrtc::ExternalRenderer* func);
const int capture_id, webrtc::VideoCaptureCapability& capability,
FrameRelay* func);
int StopCapture(CaptureEngine aCapEngine, const int capture_id);
int AllocateCaptureDevice(CaptureEngine aCapEngine,
const char* unique_idUTF8,
@ -199,7 +206,7 @@ public:
int GetCaptureCapability(CaptureEngine aCapEngine,
const char* unique_idUTF8,
const unsigned int capability_number,
webrtc::CaptureCapability& capability);
webrtc::VideoCaptureCapability& capability);
int GetCaptureDevice(CaptureEngine aCapEngine,
unsigned int list_number, char* device_nameUTF8,
const unsigned int device_nameUTF8Length,
@ -209,7 +216,7 @@ public:
void ShutdownAll();
int EnsureInitialized(CaptureEngine aCapEngine);
webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
FrameRelay* Callback(CaptureEngine aCapEngine, int capture_id);
private:
CamerasChild();
@ -219,7 +226,7 @@ private:
bool DispatchToParent(nsIRunnable* aRunnable,
MonitorAutoLock& aMonitor);
void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
webrtc::ExternalRenderer* render);
FrameRelay* render);
void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
void ShutdownParent();
void ShutdownChild();
@ -246,7 +253,7 @@ private:
// Async responses data contents;
bool mReplySuccess;
int mReplyInteger;
webrtc::CaptureCapability mReplyCapability;
webrtc::VideoCaptureCapability mReplyCapability;
nsCString mReplyDeviceName;
nsCString mReplyDeviceID;
bool mReplyScary;

View file

@ -6,6 +6,7 @@
#include "CamerasParent.h"
#include "MediaEngine.h"
#include "MediaUtils.h"
#include "VideoFrameUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Unused.h"
@ -26,9 +27,11 @@
#endif
#undef LOG
#undef LOG_VERBOSE
#undef LOG_ENABLED
mozilla::LazyLogModule gCamerasParentLog("CamerasParent");
#define LOG(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Debug, args)
#define LOG_VERBOSE(args) MOZ_LOG(gCamerasParentLog, mozilla::LogLevel::Verbose, args)
#define LOG_ENABLED() MOZ_LOG_TEST(gCamerasParentLog, mozilla::LogLevel::Debug)
namespace mozilla {
@ -44,7 +47,7 @@ namespace camera {
// suitable for UI access.
// InputObserver is owned by CamerasParent, and it has a ref to CamerasParent
void InputObserver::DeviceChange() {
void InputObserver::OnDeviceChange() {
LOG((__PRETTY_FUNCTION__));
MOZ_ASSERT(mParent);
@ -63,80 +66,30 @@ void InputObserver::DeviceChange() {
thread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
};
class FrameSizeChangeRunnable : public Runnable {
class DeliverFrameRunnable : public ::mozilla::Runnable {
public:
FrameSizeChangeRunnable(CamerasParent *aParent, CaptureEngine capEngine,
int cap_id, unsigned int aWidth, unsigned int aHeight)
: mParent(aParent), mCapEngine(capEngine), mCapId(cap_id),
mWidth(aWidth), mHeight(aHeight) {}
NS_IMETHOD Run() override {
if (mParent->IsShuttingDown()) {
// Communication channel is being torn down
LOG(("FrameSizeChangeRunnable is active without active Child"));
mResult = 0;
return NS_OK;
}
if (!mParent->SendFrameSizeChange(mCapEngine, mCapId, mWidth, mHeight)) {
mResult = -1;
} else {
mResult = 0;
}
return NS_OK;
}
int GetResult() {
return mResult;
}
private:
RefPtr<CamerasParent> mParent;
CaptureEngine mCapEngine;
int mCapId;
unsigned int mWidth;
unsigned int mHeight;
int mResult;
};
int
CallbackHelper::FrameSizeChange(unsigned int w, unsigned int h,
unsigned int streams)
{
LOG(("CallbackHelper Video FrameSizeChange: %ux%u", w, h));
RefPtr<FrameSizeChangeRunnable> runnable =
new FrameSizeChangeRunnable(mParent, mCapEngine, mCapturerId, w, h);
MOZ_ASSERT(mParent);
nsIThread * thread = mParent->GetBackgroundThread();
MOZ_ASSERT(thread != nullptr);
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
return 0;
}
class DeliverFrameRunnable : public Runnable {
public:
DeliverFrameRunnable(CamerasParent *aParent,
CaptureEngine engine,
int cap_id,
ShmemBuffer buffer,
unsigned char* altbuffer,
size_t size,
uint32_t time_stamp,
int64_t ntp_time,
int64_t render_time)
: mParent(aParent), mCapEngine(engine), mCapId(cap_id), mBuffer(Move(buffer)),
mSize(size), mTimeStamp(time_stamp), mNtpTime(ntp_time),
mRenderTime(render_time) {
DeliverFrameRunnable(CamerasParent *aParent, CaptureEngine aEngine,
uint32_t aStreamId, const webrtc::VideoFrame& aFrame,
const VideoFrameProperties& aProperties)
: mParent(aParent), mCapEngine(aEngine), mStreamId(aStreamId),
mProperties(aProperties)
{
// No ShmemBuffer (of the right size) was available, so make an
// extra buffer here. We have no idea when we are going to run and
// it will be potentially long after the webrtc frame callback has
// returned, so the copy needs to be no later than here.
// We will need to copy this back into a Shmem later on so we prefer
// using ShmemBuffers to avoid the extra copy.
if (altbuffer != nullptr) {
mAlternateBuffer.reset(new unsigned char[size]);
memcpy(mAlternateBuffer.get(), altbuffer, size);
}
};
mAlternateBuffer.reset(new unsigned char[aProperties.bufferSize()]);
VideoFrameUtils::CopyVideoFrameBuffers(mAlternateBuffer.get(),
aProperties.bufferSize(), aFrame);
}
DeliverFrameRunnable(CamerasParent* aParent, CaptureEngine aEngine,
uint32_t aStreamId, ShmemBuffer aBuffer, VideoFrameProperties& aProperties)
: mParent(aParent), mCapEngine(aEngine), mStreamId(aStreamId),
mBuffer(Move(aBuffer)), mProperties(aProperties)
{};
NS_IMETHOD Run() override {
if (mParent->IsShuttingDown()) {
@ -144,10 +97,8 @@ public:
mResult = 0;
return NS_OK;
}
if (!mParent->DeliverFrameOverIPC(mCapEngine, mCapId,
Move(mBuffer), mAlternateBuffer.get(),
mSize, mTimeStamp,
mNtpTime, mRenderTime)) {
if (!mParent->DeliverFrameOverIPC(mCapEngine, mStreamId, Move(mBuffer),
mAlternateBuffer.get(), mProperties)) {
mResult = -1;
} else {
mResult = 0;
@ -162,13 +113,10 @@ public:
private:
RefPtr<CamerasParent> mParent;
CaptureEngine mCapEngine;
int mCapId;
uint32_t mStreamId;
ShmemBuffer mBuffer;
mozilla::UniquePtr<unsigned char[]> mAlternateBuffer;
size_t mSize;
uint32_t mTimeStamp;
int64_t mNtpTime;
int64_t mRenderTime;
VideoFrameProperties mProperties;
int mResult;
};
@ -258,14 +206,11 @@ CamerasParent::StopVideoCapture()
}
int
CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine,
int cap_id,
ShmemBuffer buffer,
unsigned char* altbuffer,
size_t size,
uint32_t time_stamp,
int64_t ntp_time,
int64_t render_time)
CamerasParent::DeliverFrameOverIPC(CaptureEngine capEng,
uint32_t aStreamId,
ShmemBuffer buffer,
unsigned char* altbuffer,
VideoFrameProperties& aProps)
{
// No ShmemBuffers were available, so construct one now of the right size
// and copy into it. That is an extra copy, but we expect this to be
@ -273,7 +218,7 @@ CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine,
// buffer of the right size.
if (altbuffer != nullptr) {
// Get a shared memory buffer from the pool, at least size big
ShmemBuffer shMemBuff = mShmemPool.Get(this, size);
ShmemBuffer shMemBuff = mShmemPool.Get(this, aProps.bufferSize());
if (!shMemBuff.Valid()) {
LOG(("No usable Video shmem in DeliverFrame (out of buffers?)"));
@ -282,20 +227,18 @@ CamerasParent::DeliverFrameOverIPC(CaptureEngine cap_engine,
}
// get() and Size() check for proper alignment of the segment
memcpy(shMemBuff.GetBytes(), altbuffer, size);
memcpy(shMemBuff.GetBytes(), altbuffer, aProps.bufferSize());
if (!SendDeliverFrame(cap_engine, cap_id,
shMemBuff.Get(), size,
time_stamp, ntp_time, render_time)) {
if (!SendDeliverFrame(capEng, aStreamId,
shMemBuff.Get(), aProps)) {
return -1;
}
} else {
MOZ_ASSERT(buffer.Valid());
// ShmemBuffer was available, we're all good. A single copy happened
// in the original webrtc callback.
if (!SendDeliverFrame(cap_engine, cap_id,
buffer.Get(), size,
time_stamp, ntp_time, render_time)) {
if (!SendDeliverFrame(capEng, aStreamId,
buffer.Get(), aProps)) {
return -1;
}
}
@ -309,16 +252,16 @@ CamerasParent::GetBuffer(size_t aSize)
return mShmemPool.GetIfAvailable(aSize);
}
int
CallbackHelper::DeliverFrame(unsigned char* buffer,
size_t size,
uint32_t time_stamp,
int64_t ntp_time,
int64_t render_time,
void *handle)
int32_t
CallbackHelper::RenderFrame(uint32_t aStreamId, const webrtc::VideoFrame& aVideoFrame)
{
LOG_VERBOSE((__PRETTY_FUNCTION__));
RefPtr<DeliverFrameRunnable> runnable = nullptr;
// Get frame properties
camera::VideoFrameProperties properties;
VideoFrameUtils::InitFrameBufferProperties(aVideoFrame, properties);
// Get a shared memory buffer to copy the frame data into
ShmemBuffer shMemBuffer = mParent->GetBuffer(size);
ShmemBuffer shMemBuffer = mParent->GetBuffer(properties.bufferSize());
if (!shMemBuffer.Valid()) {
// Either we ran out of buffers or they're not the right size yet
LOG(("Correctly sized Video shmem not available in DeliverFrame"));
@ -326,30 +269,33 @@ CallbackHelper::DeliverFrame(unsigned char* buffer,
// the DeliverFrameRunnable constructor.
} else {
// Shared memory buffers of the right size are available, do the copy here.
memcpy(shMemBuffer.GetBytes(), buffer, size);
// Mark the original buffer as cleared.
buffer = nullptr;
VideoFrameUtils::CopyVideoFrameBuffers(shMemBuffer.GetBytes(),
properties.bufferSize(), aVideoFrame);
runnable = new DeliverFrameRunnable(mParent, mCapEngine, mStreamId,
Move(shMemBuffer), properties);
}
if (!runnable.get()) {
runnable = new DeliverFrameRunnable(mParent, mCapEngine, mStreamId,
aVideoFrame, properties);
}
RefPtr<DeliverFrameRunnable> runnable =
new DeliverFrameRunnable(mParent, mCapEngine, mCapturerId,
Move(shMemBuffer), buffer, size, time_stamp,
ntp_time, render_time);
MOZ_ASSERT(mParent);
nsIThread* thread = mParent->GetBackgroundThread();
MOZ_ASSERT(thread != nullptr);
thread->Dispatch(runnable, NS_DISPATCH_NORMAL);
return 0;
}
// XXX!!! FIX THIS -- we should move to pure DeliverI420Frame
int
CallbackHelper::DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame)
void
CallbackHelper::OnIncomingCapturedFrame(const int32_t id, const webrtc::VideoFrame& aVideoFrame)
{
return DeliverFrame(const_cast<uint8_t*>(webrtc_frame.buffer(webrtc::kYPlane)),
CalcBufferSize(webrtc::kI420, webrtc_frame.width(), webrtc_frame.height()),
webrtc_frame.timestamp(),
webrtc_frame.ntp_time_ms(),
webrtc_frame.render_time_ms(),
(void*) webrtc_frame.native_handle());
LOG_VERBOSE((__PRETTY_FUNCTION__));
RenderFrame(id,aVideoFrame);
}
void
CallbackHelper::OnCaptureDelayChanged(const int32_t id, const int32_t delay)
{
LOG((__PRETTY_FUNCTION__));
}
bool
@ -361,15 +307,17 @@ CamerasParent::RecvReleaseFrame(mozilla::ipc::Shmem&& s) {
bool
CamerasParent::SetupEngine(CaptureEngine aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
MOZ_ASSERT(mVideoCaptureThread->thread_id() == PlatformThread::CurrentId());
EngineHelper *helper = &mEngines[aCapEngine];
RefPtr<mozilla::camera::VideoEngine>* engine = &mEngines[aCapEngine];
// Already initialized
if (helper->mEngine) {
if (engine->get()) {
return true;
}
webrtc::CaptureDeviceInfo *captureDeviceInfo = nullptr;
UniquePtr<webrtc::Config> config(new webrtc::Config);
switch (aCapEngine) {
case ScreenEngine:
@ -398,43 +346,19 @@ CamerasParent::SetupEngine(CaptureEngine aCapEngine)
break;
}
helper->mConfig.Set<webrtc::CaptureDeviceInfo>(captureDeviceInfo);
helper->mEngine = webrtc::VideoEngine::Create(helper->mConfig);
config->Set<webrtc::CaptureDeviceInfo>(captureDeviceInfo);
*engine = mozilla::camera::VideoEngine::Create(UniquePtr<const webrtc::Config>(config.release()));
if (!helper->mEngine) {
if (!engine->get()) {
LOG(("VideoEngine::Create failed"));
return false;
}
helper->mPtrViEBase = webrtc::ViEBase::GetInterface(helper->mEngine);
if (!helper->mPtrViEBase) {
LOG(("ViEBase::GetInterface failed"));
return false;
}
if (helper->mPtrViEBase->Init() < 0) {
LOG(("ViEBase::Init failed"));
return false;
}
helper->mPtrViECapture = webrtc::ViECapture::GetInterface(helper->mEngine);
if (!helper->mPtrViECapture) {
LOG(("ViECapture::GetInterface failed"));
return false;
}
RefPtr<InputObserver>* observer = mObservers.AppendElement(new InputObserver(this));
#ifdef DEBUG
MOZ_ASSERT(0 == helper->mPtrViECapture->RegisterInputObserver(observer->get()));
#else
helper->mPtrViECapture->RegisterInputObserver(observer->get());
#endif
helper->mPtrViERender = webrtc::ViERender::GetInterface(helper->mEngine);
if (!helper->mPtrViERender) {
LOG(("ViERender::GetInterface failed"));
return false;
auto device_info = engine->get()->GetOrCreateVideoCaptureDeviceInfo();
MOZ_ASSERT(device_info);
if (device_info) {
device_info->RegisterVideoInputFeedBack(**observer);
}
return true;
@ -452,38 +376,25 @@ CamerasParent::CloseEngines()
// Stop the callers
while (mCallbacks.Length()) {
auto capEngine = mCallbacks[0]->mCapEngine;
auto capNum = mCallbacks[0]->mCapturerId;
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, capNum));
StopCapture(capEngine, capNum);
Unused << ReleaseCaptureDevice(capEngine, capNum);
auto streamNum = mCallbacks[0]->mStreamId;
LOG(("Forcing shutdown of engine %d, capturer %d", capEngine, streamNum));
StopCapture(capEngine, streamNum);
Unused << ReleaseCaptureDevice(capEngine, streamNum);
}
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
if (mEngines[i].mEngineIsRunning) {
LOG(("Being closed down while engine %d is running!", i));
}
if (mEngines[i].mPtrViERender) {
mEngines[i].mPtrViERender->Release();
mEngines[i].mPtrViERender = nullptr;
}
if (mEngines[i].mPtrViECapture) {
#ifdef DEBUG
MOZ_ASSERT(0 == mEngines[i].mPtrViECapture->DeregisterInputObserver());
#else
mEngines[i].mPtrViECapture->DeregisterInputObserver();
#endif
if (auto engine = mEngines[i].get() ){
if (engine->IsRunning()) {
LOG(("Being closed down while engine %d is running!", i));
}
mEngines[i].mPtrViECapture->Release();
mEngines[i].mPtrViECapture = nullptr;
}
if(mEngines[i].mPtrViEBase) {
mEngines[i].mPtrViEBase->Release();
mEngines[i].mPtrViEBase = nullptr;
}
if (mEngines[i].mEngine) {
mEngines[i].mEngine->SetTraceCallback(nullptr);
webrtc::VideoEngine::Delete(mEngines[i].mEngine);
mEngines[i].mEngine = nullptr;
auto device_info = engine->GetOrCreateVideoCaptureDeviceInfo();
MOZ_ASSERT(device_info);
if (device_info) {
device_info->DeRegisterVideoInputFeedBack();
}
mozilla::camera::VideoEngine::Delete(engine);
mEngines[i] = nullptr;
}
}
@ -492,21 +403,21 @@ CamerasParent::CloseEngines()
mWebRTCAlive = false;
}
bool
VideoEngine *
CamerasParent::EnsureInitialized(int aEngine)
{
LOG((__PRETTY_FUNCTION__));
LOG_VERBOSE((__PRETTY_FUNCTION__));
// We're shutting down, don't try to do new WebRTC ops.
if (!mWebRTCAlive) {
return false;
return nullptr;
}
CaptureEngine capEngine = static_cast<CaptureEngine>(aEngine);
if (!SetupEngine(capEngine)) {
LOG(("CamerasParent failed to initialize engine"));
return false;
return nullptr;
}
return true;
return mEngines[aEngine];
}
// Dispatch the runnable to do the camera operation on the
@ -518,13 +429,15 @@ bool
CamerasParent::RecvNumberOfCaptureDevices(const CaptureEngine& aCapEngine)
{
LOG((__PRETTY_FUNCTION__));
LOG(("CaptureEngine=%d", aCapEngine));
RefPtr<CamerasParent> self(this);
RefPtr<Runnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine]() -> nsresult {
int num = -1;
if (self->EnsureInitialized(aCapEngine)) {
num = self->mEngines[aCapEngine].mPtrViECapture->NumberOfCaptureDevices();
if (auto engine = self->EnsureInitialized(aCapEngine)) {
if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()) {
num = devInfo->NumberOfDevices();
}
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, num]() -> nsresult {
@ -591,11 +504,10 @@ CamerasParent::RecvNumberOfCapabilities(const CaptureEngine& aCapEngine,
RefPtr<Runnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine]() -> nsresult {
int num = -1;
if (self->EnsureInitialized(aCapEngine)) {
num =
self->mEngines[aCapEngine].mPtrViECapture->NumberOfCapabilities(
unique_id.get(),
MediaEngineSource::kMaxUniqueIdLength);
if (auto engine = self->EnsureInitialized(aCapEngine)) {
if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()) {
num = devInfo->NumberOfCapabilities(unique_id.get());
}
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, num]() -> nsresult {
@ -630,18 +542,19 @@ CamerasParent::RecvGetCaptureCapability(const CaptureEngine& aCapEngine,
RefPtr<CamerasParent> self(this);
RefPtr<Runnable> webrtc_runnable =
media::NewRunnableFrom([self, unique_id, aCapEngine, num]() -> nsresult {
webrtc::CaptureCapability webrtcCaps;
webrtc::VideoCaptureCapability webrtcCaps;
int error = -1;
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureCapability(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, num, webrtcCaps);
if (auto engine = self->EnsureInitialized(aCapEngine)) {
if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()){
error = devInfo->GetCapability(unique_id.get(), num, webrtcCaps);
}
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, webrtcCaps, error]() -> nsresult {
if (self->IsShuttingDown()) {
return NS_ERROR_FAILURE;
}
CaptureCapability capCap(webrtcCaps.width,
VideoCaptureCapability capCap(webrtcCaps.width,
webrtcCaps.height,
webrtcCaps.maxFPS,
webrtcCaps.expectedCaptureDelay,
@ -682,15 +595,15 @@ CamerasParent::RecvGetCaptureDevice(const CaptureEngine& aCapEngine,
char deviceUniqueId[MediaEngineSource::kMaxUniqueIdLength];
nsCString name;
nsCString uniqueId;
int devicePid = 0;
pid_t devicePid = 0;
int error = -1;
if (self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->GetCaptureDevice(aListNumber,
deviceName,
sizeof(deviceName),
deviceUniqueId,
sizeof(deviceUniqueId),
&devicePid);
if (auto engine = self->EnsureInitialized(aCapEngine)) {
if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()) {
error = devInfo->GetDeviceName(aListNumber, deviceName, sizeof(deviceName),
deviceUniqueId, sizeof(deviceUniqueId),
nullptr, 0,
&devicePid);
}
}
if (!error) {
name.Assign(deviceName);
@ -806,8 +719,17 @@ CamerasParent::RecvAllocateCaptureDevice(const CaptureEngine& aCapEngine,
int numdev = -1;
int error = -1;
if (allowed && self->EnsureInitialized(aCapEngine)) {
error = self->mEngines[aCapEngine].mPtrViECapture->AllocateCaptureDevice(
unique_id.get(), MediaEngineSource::kMaxUniqueIdLength, numdev);
auto engine = self->mEngines[aCapEngine].get();
engine->CreateVideoCapture(numdev, unique_id.get());
engine->WithEntry(numdev, [&error](VideoEngine::CaptureEntry& cap) {
if (cap.VideoCapture()) {
if (!cap.VideoRenderer()) {
LOG(("VideoEngine::VideoRenderer() failed"));
} else {
error = 0;
}
}
});
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, numdev, error]() -> nsresult {
@ -838,8 +760,8 @@ CamerasParent::ReleaseCaptureDevice(const CaptureEngine& aCapEngine,
const int& capnum)
{
int error = -1;
if (EnsureInitialized(aCapEngine)) {
error = mEngines[aCapEngine].mPtrViECapture->ReleaseCaptureDevice(capnum);
if (auto engine = EnsureInitialized(aCapEngine)) {
error = engine->ReleaseVideoCapture(capnum);
}
return error;
}
@ -881,44 +803,48 @@ CamerasParent::RecvReleaseCaptureDevice(const CaptureEngine& aCapEngine,
bool
CamerasParent::RecvStartCapture(const CaptureEngine& aCapEngine,
const int& capnum,
const CaptureCapability& ipcCaps)
const VideoCaptureCapability& ipcCaps)
{
LOG((__PRETTY_FUNCTION__));
RefPtr<CamerasParent> self(this);
RefPtr<Runnable> webrtc_runnable =
media::NewRunnableFrom([self, aCapEngine, capnum, ipcCaps]() -> nsresult {
LOG((__PRETTY_FUNCTION__));
CallbackHelper** cbh;
webrtc::ExternalRenderer* render;
EngineHelper* helper = nullptr;
webrtc::VideoRenderCallback* render;
VideoEngine* engine = nullptr;
int error = -1;
if (self->EnsureInitialized(aCapEngine)) {
cbh = self->mCallbacks.AppendElement(
new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
render = static_cast<webrtc::ExternalRenderer*>(*cbh);
render = static_cast<webrtc::VideoRenderCallback*>(*cbh);
helper = &self->mEngines[aCapEngine];
error =
helper->mPtrViERender->AddRenderer(capnum, webrtc::kVideoI420, render);
if (!error) {
error = helper->mPtrViERender->StartRender(capnum);
}
engine = self->mEngines[aCapEngine];
engine->WithEntry(capnum, [capnum, &render, &engine, &error, &ipcCaps, &cbh](VideoEngine::CaptureEntry& cap) {
cap.VideoRenderer()->AddIncomingRenderStream(capnum,0, 0., 0., 1., 1.);
error = cap.VideoRenderer()->AddExternalRenderCallback(capnum, render);
if (!error) {
error = cap.VideoRenderer()->StartRender(capnum);
}
webrtc::CaptureCapability capability;
capability.width = ipcCaps.width();
capability.height = ipcCaps.height();
capability.maxFPS = ipcCaps.maxFPS();
capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
capability.interlaced = ipcCaps.interlaced();
webrtc::VideoCaptureCapability capability;
capability.width = ipcCaps.width();
capability.height = ipcCaps.height();
capability.maxFPS = ipcCaps.maxFPS();
capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
capability.interlaced = ipcCaps.interlaced();
if (!error) {
error = helper->mPtrViECapture->StartCapture(capnum, capability);
}
if (!error) {
helper->mEngineIsRunning = true;
}
if (!error) {
error = cap.VideoCapture()->StartCapture(capability);
}
if (!error) {
engine->Startup();
cap.VideoCapture()->RegisterCaptureDataCallback(*static_cast<webrtc::VideoCaptureDataCallback*>(*cbh));
}
});
}
RefPtr<nsIRunnable> ipc_runnable =
media::NewRunnableFrom([self, error]() -> nsresult {
@ -944,20 +870,27 @@ void
CamerasParent::StopCapture(const CaptureEngine& aCapEngine,
const int& capnum)
{
if (EnsureInitialized(aCapEngine)) {
mEngines[aCapEngine].mPtrViECapture->StopCapture(capnum);
mEngines[aCapEngine].mPtrViERender->StopRender(capnum);
mEngines[aCapEngine].mPtrViERender->RemoveRenderer(capnum);
mEngines[aCapEngine].mEngineIsRunning = false;
for (size_t i = 0; i < mCallbacks.Length(); i++) {
if (mCallbacks[i]->mCapEngine == aCapEngine
&& mCallbacks[i]->mCapturerId == capnum) {
delete mCallbacks[i];
mCallbacks.RemoveElementAt(i);
if (auto engine = EnsureInitialized(aCapEngine)) {
engine->WithEntry(capnum,[capnum](VideoEngine::CaptureEntry& cap){
if (cap.VideoCapture()) {
cap.VideoCapture()->StopCapture();
cap.VideoCapture()->DeRegisterCaptureDataCallback();
}
if (cap.VideoRenderer()) {
cap.VideoRenderer()->StopRender(capnum);
}
});
// we're removing elements, iterate backwards
for (size_t i = mCallbacks.Length(); i > 0; i--) {
if (mCallbacks[i-1]->mCapEngine == aCapEngine
&& mCallbacks[i-1]->mStreamId == (uint32_t) capnum) {
delete mCallbacks[i-1];
mCallbacks.RemoveElementAt(i-1);
break;
}
}
engine->RemoveRenderer(capnum);
engine->Shutdown();
}
}
@ -1077,7 +1010,7 @@ CamerasParent::~CamerasParent()
// That runnable takes a ref to us, so it must have finished
// by the time we get here.
for (int i = 0; i < CaptureEngine::MaxEngine; i++) {
MOZ_ASSERT(!mEngines[i].mEngine);
MOZ_ASSERT(!mEngines[i]);
}
#endif
}

View file

@ -7,19 +7,21 @@
#define mozilla_CamerasParent_h
#include "nsIObserver.h"
#include "VideoEngine.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/camera/PCamerasParent.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ShmemPool.h"
#include "mozilla/Atomics.h"
#include "webrtc/modules/video_capture/video_capture.h"
#include "webrtc/modules/video_render/video_render_impl.h"
#include "webrtc/modules/video_capture/video_capture_defines.h"
#include "webrtc/common_video/include/incoming_video_stream.h"
// conflicts with #include of scoped_ptr.h
#undef FF
#include "webrtc/common.h"
// Video Engine
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_render.h"
#include "CamerasChild.h"
#include "base/thread.h"
@ -29,60 +31,43 @@ namespace camera {
class CamerasParent;
class CallbackHelper : public webrtc::ExternalRenderer
class CallbackHelper :
public webrtc::VideoRenderCallback,
public webrtc::VideoCaptureDataCallback
{
public:
CallbackHelper(CaptureEngine aCapEng, int aCapId, CamerasParent *aParent)
: mCapEngine(aCapEng), mCapturerId(aCapId), mParent(aParent) {};
CallbackHelper(CaptureEngine aCapEng, uint32_t aStreamId, CamerasParent *aParent)
: mCapEngine(aCapEng), mStreamId(aStreamId), mParent(aParent) {};
// ViEExternalRenderer implementation. These callbacks end up
// running on the VideoCapture thread.
virtual int FrameSizeChange(unsigned int w, unsigned int h,
unsigned int streams) override;
virtual int DeliverFrame(unsigned char* buffer,
size_t size,
uint32_t time_stamp,
int64_t ntp_time,
int64_t render_time,
void *handle) override;
virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override;
virtual bool IsTextureSupported() override { return false; };
virtual int32_t RenderFrame(const uint32_t aStreamId, const webrtc::VideoFrame& video_frame) override;
// From VideoCaptureCallback
virtual void OnIncomingCapturedFrame(const int32_t id, const webrtc::VideoFrame& videoFrame) override;
virtual void OnCaptureDelayChanged(const int32_t id, const int32_t delay) override;
// TODO(@@NG) This is now part of webrtc::VideoRenderer, not in the webrtc::VideoRenderCallback
// virtual bool IsTextureSupported() const override { return false; };
//
// virtual bool SmoothsRenderedFrames() const override { return false; }
friend CamerasParent;
private:
CaptureEngine mCapEngine;
int mCapturerId;
uint32_t mStreamId;
CamerasParent *mParent;
};
class EngineHelper
{
public:
EngineHelper() :
mEngine(nullptr), mPtrViEBase(nullptr), mPtrViECapture(nullptr),
mPtrViERender(nullptr), mEngineIsRunning(false) {};
webrtc::VideoEngine *mEngine;
webrtc::ViEBase *mPtrViEBase;
webrtc::ViECapture *mPtrViECapture;
webrtc::ViERender *mPtrViERender;
// The webrtc code keeps a reference to this one.
webrtc::Config mConfig;
// Engine alive
bool mEngineIsRunning;
};
class InputObserver : public webrtc::ViEInputObserver
class InputObserver : public webrtc::VideoInputFeedBack
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InputObserver)
explicit InputObserver(CamerasParent* aParent)
: mParent(aParent) {};
virtual void DeviceChange();
virtual void OnDeviceChange();
friend CamerasParent;
@ -113,7 +98,7 @@ public:
const int&) override;
virtual bool RecvGetCaptureDevice(const CaptureEngine&, const int&) override;
virtual bool RecvStartCapture(const CaptureEngine&, const int&,
const CaptureCapability&) override;
const VideoCaptureCapability&) override;
virtual bool RecvStopCapture(const CaptureEngine&, const int&) override;
virtual bool RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
virtual bool RecvAllDone() override;
@ -128,13 +113,10 @@ public:
// helper to forward to the PBackground thread
int DeliverFrameOverIPC(CaptureEngine capEng,
int cap_id,
uint32_t aStreamId,
ShmemBuffer buffer,
unsigned char* altbuffer,
size_t size,
uint32_t time_stamp,
int64_t ntp_time,
int64_t render_time);
VideoFrameProperties& aProps);
CamerasParent();
@ -147,14 +129,14 @@ protected:
int ReleaseCaptureDevice(const CaptureEngine& aCapEngine, const int& capnum);
bool SetupEngine(CaptureEngine aCapEngine);
bool EnsureInitialized(int aEngine);
VideoEngine* EnsureInitialized(int aEngine);
void CloseEngines();
void StopIPC();
void StopVideoCapture();
// Can't take already_AddRefed because it can fail in stupid ways.
nsresult DispatchToVideoCaptureThread(Runnable* event);
EngineHelper mEngines[CaptureEngine::MaxEngine];
RefPtr<VideoEngine> mEngines[CaptureEngine::MaxEngine];
nsTArray<CallbackHelper*> mCallbacks;
// image buffers

View file

@ -14,8 +14,8 @@
#include "nsIObserver.h"
#include "webrtc/common_types.h"
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/call.h"
#include "webrtc/video/overuse_frame_detector.h"
extern mozilla::LazyLogModule gLoadManagerLog;
namespace mozilla {
@ -77,7 +77,7 @@ private:
};
class LoadManager final : public webrtc::CPULoadStateCallbackInvoker,
public webrtc::CpuOveruseObserver
public webrtc::LoadObserver
{
public:
explicit LoadManager(LoadManagerSingleton* aManager)
@ -93,13 +93,14 @@ public:
{
mManager->RemoveObserver(aObserver);
}
void OveruseDetected() override
void OnLoadUpdate(webrtc::LoadObserver::Load load_state) override
{
mManager->OveruseDetected();
}
void NormalUsage() override
{
mManager->NormalUsage();
if (load_state == webrtc::LoadObserver::kOveruse) {
mManager->OveruseDetected();
} else if (load_state == webrtc::LoadObserver::kUnderuse) {
mManager->NormalUsage();
}
}
private:

View file

@ -10,7 +10,8 @@ using mozilla::camera::CaptureEngine from "mozilla/media/CamerasTypes.h";
namespace mozilla {
namespace camera {
struct CaptureCapability
// IPC analog for webrtc::VideoCaptureCapability
struct VideoCaptureCapability
{
int width;
int height;
@ -21,6 +22,32 @@ struct CaptureCapability
bool interlaced;
};
// IPC analog for webrtc::VideoFrame
// the described buffer is transported seperately in a Shmem
// See VideoFrameUtils.h
struct VideoFrameProperties
{
// Size of image data within the ShMem,
// the ShMem is at least this large
uint32_t bufferSize;
// From webrtc::VideoFrame
uint32_t timeStamp;
int64_t ntpTimeMs;
int64_t renderTimeMs;
// See webrtc/**/rotation.h
int rotation;
int yAllocatedSize;
int uAllocatedSize;
int vAllocatedSize;
// From webrtc::VideoFrameBuffer
int width;
int height;
int yStride;
int uStride;
int vStride;
};
async protocol PCameras
{
manager PBackground;
@ -28,14 +55,13 @@ async protocol PCameras
child:
async FrameSizeChange(CaptureEngine capEngine, int cap_id, int w, int h);
// transfers ownership of |buffer| from parent to child
async DeliverFrame(CaptureEngine capEngine, int cap_id,
Shmem buffer, size_t size, uint32_t time_stamp,
int64_t ntp_time, int64_t render_time);
async DeliverFrame(CaptureEngine capEngine, int streamId,
Shmem buffer, VideoFrameProperties props);
async DeviceChange();
async ReplyNumberOfCaptureDevices(int numdev);
async ReplyNumberOfCapabilities(int numdev);
async ReplyAllocateCaptureDevice(int numdev);
async ReplyGetCaptureCapability(CaptureCapability cap);
async ReplyGetCaptureCapability(VideoCaptureCapability cap);
async ReplyGetCaptureDevice(nsCString device_name, nsCString device_id, bool scary);
async ReplyFailure();
async ReplySuccess();
@ -45,12 +71,13 @@ parent:
async NumberOfCaptureDevices(CaptureEngine engine);
async NumberOfCapabilities(CaptureEngine engine, nsCString deviceUniqueIdUTF8);
async GetCaptureCapability(CaptureEngine engine, nsCString unique_idUTF8, int capability_number);
async GetCaptureCapability(CaptureEngine engine, nsCString unique_idUTF8,
int capability_number);
async GetCaptureDevice(CaptureEngine engine, int num);
async AllocateCaptureDevice(CaptureEngine engine, nsCString unique_idUTF8, nsCString origin);
async ReleaseCaptureDevice(CaptureEngine engine, int numdev);
async StartCapture(CaptureEngine engine, int numdev, CaptureCapability capability);
async StartCapture(CaptureEngine engine, int numdev, VideoCaptureCapability capability);
async StopCapture(CaptureEngine engine, int numdev);
// transfers frame back
async ReleaseFrame(Shmem s);

View file

@ -39,7 +39,7 @@ mozilla::ShmemBuffer ShmemPool::GetIfAvailable(size_t aSize)
MOZ_ASSERT(res.mShmem.IsWritable(), "Pool in Shmem is not writable?");
if (res.mShmem.Size<char>() < aSize) {
if (res.mShmem.Size<uint8_t>() < aSize) {
LOG(("Free Shmem but not of the right size"));
return ShmemBuffer();
}
@ -64,7 +64,7 @@ void ShmemPool::Put(ShmemBuffer&& aShmem)
#ifdef DEBUG
size_t poolUse = mShmemPool.Length() - mPoolFree;
if (poolUse > 0) {
LOG(("ShmemPool usage reduced to %d buffers", poolUse));
LOG_VERBOSE(("ShmemPool usage reduced to %d buffers", poolUse));
}
#endif
}

View file

@ -47,8 +47,8 @@ public:
return mInitialized;
}
char* GetBytes() {
return mShmem.get<char>();
uint8_t * GetBytes() {
return mShmem.get<uint8_t>();
}
mozilla::ipc::Shmem& Get() {

View file

@ -0,0 +1,185 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoEngine.h"
#include "webrtc/video_engine/browser_capture_impl.h"
#ifdef WEBRTC_ANDROID
#include "webrtc/modules/video_capture/video_capture.h"
#ifdef WEBRTC_INCLUDE_INTERNAL_VIDEO_RENDER
#include "webrtc/modules/video_render/video_render.h"
#endif
#endif
namespace mozilla {
namespace camera {
#undef LOG
#undef LOG_ENABLED
mozilla::LazyLogModule gVideoEngineLog("VideoEngine");
#define LOG(args) MOZ_LOG(gVideoEngineLog, mozilla::LogLevel::Debug, args)
#define LOG_ENABLED() MOZ_LOG_TEST(gVideoEngineLog, mozilla::LogLevel::Debug)
int VideoEngine::sId = 0;
#if defined(ANDROID)
int VideoEngine::SetAndroidObjects(JavaVM* javaVM) {
LOG((__PRETTY_FUNCTION__));
if (webrtc::SetCaptureAndroidVM(javaVM) != 0) {
LOG(("Could not set capture Android VM"));
return -1;
}
#ifdef WEBRTC_INCLUDE_INTERNAL_VIDEO_RENDER
if (webrtc::SetRenderAndroidVM(javaVM) != 0) {
LOG(("Could not set render Android VM"));
return -1;
}
#endif
return 0;
}
#endif
void
VideoEngine::CreateVideoCapture(int32_t& id, const char* deviceUniqueIdUTF8) {
LOG((__PRETTY_FUNCTION__));
id = GenerateId();
LOG(("CaptureDeviceInfo.type=%s id=%d",mCaptureDevInfo.TypeName(),id));
CaptureEntry entry = {-1,nullptr,nullptr};
if (mCaptureDevInfo.type == webrtc::CaptureDeviceType::Camera) {
entry = CaptureEntry(id,
webrtc::VideoCaptureFactory::Create(id, deviceUniqueIdUTF8),
nullptr);
} else {
#ifndef WEBRTC_ANDROID
entry = CaptureEntry(
id,
webrtc::DesktopCaptureImpl::Create(id, deviceUniqueIdUTF8, mCaptureDevInfo.type),
nullptr);
#else
MOZ_ASSERT("CreateVideoCapture NO DESKTOP CAPTURE IMPL ON ANDROID" == nullptr);
#endif
}
mCaps.emplace(id,std::move(entry));
}
int
VideoEngine::ReleaseVideoCapture(const int32_t id) {
bool found = false;
WithEntry(id, [&found](CaptureEntry& cap) {
cap.mVideoCaptureModule = nullptr;
found = true;
});
return found ? 0 : (-1);
}
std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo>
VideoEngine::GetOrCreateVideoCaptureDeviceInfo() {
if (mDeviceInfo) {
return mDeviceInfo;
}
switch (mCaptureDevInfo.type) {
case webrtc::CaptureDeviceType::Camera: {
mDeviceInfo.reset(webrtc::VideoCaptureFactory::CreateDeviceInfo(0));
break;
}
case webrtc::CaptureDeviceType::Browser: {
mDeviceInfo.reset(webrtc::BrowserDeviceInfoImpl::CreateDeviceInfo());
break;
}
// Window, Application, and Screen types are handled by DesktopCapture
case webrtc::CaptureDeviceType::Window:
case webrtc::CaptureDeviceType::Application:
case webrtc::CaptureDeviceType::Screen: {
#if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS)
mDeviceInfo.reset(webrtc::DesktopCaptureImpl::CreateDeviceInfo(mId,mCaptureDevInfo.type));
#else
MOZ_ASSERT("GetVideoCaptureDeviceInfo NO DESKTOP CAPTURE IMPL ON ANDROID" == nullptr);
mDeviceInfo.reset();
#endif
break;
}
}
return mDeviceInfo;
}
void
VideoEngine::RemoveRenderer(int capnum) {
WithEntry(capnum, [](CaptureEntry& cap) {
cap.mVideoRender = nullptr;
});
}
const UniquePtr<const webrtc::Config>&
VideoEngine::GetConfiguration() {
return mConfig;
}
RefPtr<VideoEngine> VideoEngine::Create(UniquePtr<const webrtc::Config>&& aConfig) {
LOG((__PRETTY_FUNCTION__));
LOG(("Creating new VideoEngine with CaptureDeviceType %s",
aConfig->Get<webrtc::CaptureDeviceInfo>().TypeName()));
RefPtr<VideoEngine> engine(new VideoEngine(std::move(aConfig)));
return engine;
}
VideoEngine::CaptureEntry::CaptureEntry(int32_t aCapnum,
rtc::scoped_refptr<webrtc::VideoCaptureModule> aCapture,
webrtc::VideoRender * aRenderer):
mCapnum(aCapnum),
mVideoCaptureModule(aCapture),
mVideoRender(aRenderer)
{}
rtc::scoped_refptr<webrtc::VideoCaptureModule>
VideoEngine::CaptureEntry::VideoCapture() {
return mVideoCaptureModule;
}
const UniquePtr<webrtc::VideoRender>&
VideoEngine::CaptureEntry::VideoRenderer() {
if (!mVideoRender) {
MOZ_ASSERT(mCapnum != -1);
// Create a VideoRender on demand
mVideoRender = UniquePtr<webrtc::VideoRender>(
webrtc::VideoRender::CreateVideoRender(mCapnum,nullptr,false,webrtc::kRenderExternal));
}
return mVideoRender;
}
int32_t
VideoEngine::CaptureEntry::Capnum() const {
return mCapnum;
}
bool VideoEngine::WithEntry(const int32_t entryCapnum,
const std::function<void(CaptureEntry &entry)>&& fn) {
auto it = mCaps.find(entryCapnum);
if (it == mCaps.end()) {
return false;
}
fn(it->second);
return true;
}
int32_t
VideoEngine::GenerateId() {
// XXX Something better than this (a map perhaps, or a simple boolean TArray, given
// the number in-use is O(1) normally!)
return mId = sId++;
}
VideoEngine::VideoEngine(UniquePtr<const webrtc::Config>&& aConfig):
mCaptureDevInfo(aConfig->Get<webrtc::CaptureDeviceInfo>()),
mDeviceInfo(nullptr),
mConfig(std::move(aConfig))
{
LOG((__PRETTY_FUNCTION__));
}
}
}

View file

@ -0,0 +1,104 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_VideoEngine_h
#define mozilla_VideoEngine_h
#include "MediaEngine.h"
#include "VideoFrameUtils.h"
#include "mozilla/media/MediaUtils.h"
#include "webrtc/common.h"
#include "webrtc/modules/video_capture/video_capture_impl.h"
#include "webrtc/modules/video_render/video_render.h"
#include "webrtc/modules/video_capture/video_capture_defines.h"
#include "webrtc/modules/video_capture/video_capture_factory.h"
#include "webrtc/video_engine/desktop_capture_impl.h"
#include <memory>
#include <functional>
namespace mozilla {
namespace camera {
// Historically the video engine was part of webrtc
// it was removed (and reimplemented in Talk)
class VideoEngine
{
private:
virtual ~VideoEngine (){};
public:
VideoEngine (){};
NS_INLINE_DECL_REFCOUNTING(VideoEngine)
static RefPtr<VideoEngine> Create(UniquePtr<const webrtc::Config>&& aConfig);
#if defined(ANDROID)
static int SetAndroidObjects(JavaVM* javaVM);
#endif
void CreateVideoCapture(int32_t& id, const char* deviceUniqueIdUTF8);
int ReleaseVideoCapture(const int32_t id);
// VideoEngine is responsible for any cleanup in its modules
static void Delete(VideoEngine * engine) { }
/** Returns or creates a new new DeviceInfo.
* It is cached to prevent repeated lengthy polling for "realness"
* of the hardware devices. This could be handled in a more elegant
* way in the future.
* @return on failure the shared_ptr will be null, otherwise it will contain a DeviceInfo.
* @see bug 1305212 https://bugzilla.mozilla.org/show_bug.cgi?id=1305212
*/
std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo> GetOrCreateVideoCaptureDeviceInfo();
void RemoveRenderer(int capnum);
const UniquePtr<const webrtc::Config>& GetConfiguration();
void Startup() {
mIsRunning = true;
}
void Shutdown() {
mIsRunning = false;
}
bool IsRunning() const {
return mIsRunning;
}
class CaptureEntry {
public:
CaptureEntry(int32_t aCapnum,
rtc::scoped_refptr<webrtc::VideoCaptureModule> aCapture,
webrtc::VideoRender* aRenderer);
int32_t Capnum() const;
rtc::scoped_refptr<webrtc::VideoCaptureModule> VideoCapture();
const UniquePtr<webrtc::VideoRender> & VideoRenderer();
private:
int32_t mCapnum;
rtc::scoped_refptr<webrtc::VideoCaptureModule> mVideoCaptureModule;
UniquePtr<webrtc::VideoRender> mVideoRender;
friend class VideoEngine;
};
// Returns true iff an entry for capnum exists
bool WithEntry(const int32_t entryCapnum, const std::function<void(CaptureEntry &entry)>&& fn);
private:
explicit VideoEngine(UniquePtr<const webrtc::Config>&& aConfig);
bool mIsRunning;
int32_t mId;
webrtc::CaptureDeviceInfo mCaptureDevInfo;
std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo> mDeviceInfo;
UniquePtr<const webrtc::Config> mConfig;
std::map<int32_t, CaptureEntry> mCaps;
int32_t GenerateId();
static int32_t sId;
};
}
}
#endif

View file

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoFrameUtils.h"
#include "webrtc/video_frame.h"
#include "mozilla/ShmemPool.h"
namespace mozilla {
size_t
VideoFrameUtils::TotalRequiredBufferSize(
const webrtc::VideoFrame& aVideoFrame)
{
static const webrtc::PlaneType kPlanes[] =
{webrtc::kYPlane, webrtc::kUPlane, webrtc::kVPlane};
if (aVideoFrame.IsZeroSize()) {
return 0;
}
size_t sum = 0;
for (auto plane : kPlanes) {
sum += aVideoFrame.allocated_size(plane);
}
return sum;
}
void VideoFrameUtils::InitFrameBufferProperties(
const webrtc::VideoFrame& aVideoFrame,
camera::VideoFrameProperties& aDestProps)
{
// The VideoFrameBuffer image data stored in the accompanying buffer
// the buffer is at least this size of larger.
aDestProps.bufferSize() = TotalRequiredBufferSize(aVideoFrame);
aDestProps.timeStamp() = aVideoFrame.timestamp();
aDestProps.ntpTimeMs() = aVideoFrame.ntp_time_ms();
aDestProps.renderTimeMs() = aVideoFrame.render_time_ms();
aDestProps.rotation() = aVideoFrame.rotation();
aDestProps.yAllocatedSize() = aVideoFrame.allocated_size(webrtc::kYPlane);
aDestProps.uAllocatedSize() = aVideoFrame.allocated_size(webrtc::kYPlane);
aDestProps.vAllocatedSize() = aVideoFrame.allocated_size(webrtc::kYPlane);
aDestProps.width() = aVideoFrame.width();
aDestProps.height() = aVideoFrame.height();
aDestProps.yStride() = aVideoFrame.stride(webrtc::kYPlane);
aDestProps.uStride() = aVideoFrame.stride(webrtc::kUPlane);
aDestProps.vStride() = aVideoFrame.stride(webrtc::kVPlane);
}
void VideoFrameUtils::CopyVideoFrameBuffers(uint8_t* aDestBuffer,
const size_t aDestBufferSize,
const webrtc::VideoFrame& aFrame)
{
static const webrtc::PlaneType planes[] = {webrtc::kYPlane, webrtc::kUPlane, webrtc::kVPlane};
size_t aggregateSize = TotalRequiredBufferSize(aFrame);
MOZ_ASSERT(aDestBufferSize >= aggregateSize);
// If planes are ordered YUV and contiguous then do a single copy
if ((aFrame.buffer(webrtc::kYPlane) != nullptr)
// Check that the three planes are ordered
&& (aFrame.buffer(webrtc::kYPlane) < aFrame.buffer(webrtc::kUPlane))
&& (aFrame.buffer(webrtc::kUPlane) < aFrame.buffer(webrtc::kVPlane))
// Check that the last plane ends at firstPlane[totalsize]
&& (&aFrame.buffer(webrtc::kYPlane)[aggregateSize] == &aFrame.buffer(webrtc::kVPlane)[aFrame.allocated_size(webrtc::kVPlane)]))
{
memcpy(aDestBuffer,aFrame.buffer(webrtc::kYPlane),aggregateSize);
return;
}
// Copy each plane
size_t offset = 0;
for (auto plane: planes) {
memcpy(&aDestBuffer[offset], aFrame.buffer(plane), aFrame.allocated_size(plane));
offset += aFrame.allocated_size(plane);
}
}
void VideoFrameUtils::CopyVideoFrameBuffers(ShmemBuffer& aDestShmem,
const webrtc::VideoFrame& aVideoFrame)
{
CopyVideoFrameBuffers(aDestShmem.Get().get<uint8_t>(), aDestShmem.Get().Size<uint8_t>(), aVideoFrame);
}
}

View file

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_VideoFrameUtil_h
#define mozilla_VideoFrameUtil_h
#include "mozilla/camera/PCameras.h"
namespace webrtc {
class VideoFrame;
}
namespace mozilla
{
class ShmemBuffer;
// Util methods for working with webrtc::VideoFrame(s) and
// the IPC classes that are used to deliver their contents to the
// MediaEnginge
class VideoFrameUtils {
public:
// Returns the total number of bytes necessary to copy a VideoFrame's buffer
// across all planes.
static size_t TotalRequiredBufferSize(const webrtc::VideoFrame & frame);
// Initializes a camera::VideoFrameProperties from a VideoFrameBuffer
static void InitFrameBufferProperties(const webrtc::VideoFrame& aVideoFrame,
camera::VideoFrameProperties & aDestProperties);
// Copies the buffers out of a VideoFrameBuffer into a buffer.
// Attempts to make as few memcopies as possible.
static void CopyVideoFrameBuffers(uint8_t * aDestBuffer,
const size_t aDestBufferSize,
const webrtc::VideoFrame & aVideoFrame);
// Copies the buffers in a VideoFrameBuffer into a Shmem
// returns the eno from the underlying memcpy.
static void CopyVideoFrameBuffers(ShmemBuffer & aDestShmem,
const webrtc::VideoFrame & aVideoFrame);
};
} /* namespace mozilla */
#endif

View file

@ -1,4 +1,4 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@ -10,6 +10,8 @@ if CONFIG['MOZ_WEBRTC']:
'LoadManager.h',
'LoadManagerFactory.h',
'LoadMonitor.h',
'VideoEngine.h',
'VideoFrameUtils.h'
]
SOURCES += [
'CamerasChild.cpp',
@ -18,6 +20,8 @@ if CONFIG['MOZ_WEBRTC']:
'LoadManagerFactory.cpp',
'LoadMonitor.cpp',
'ShmemPool.cpp',
'VideoEngine.cpp',
'VideoFrameUtils.cpp'
]
LOCAL_INCLUDES += [
'/media/webrtc/signaling',
@ -29,6 +33,9 @@ if CONFIG['OS_TARGET'] == 'WINNT':
else:
DEFINES['WEBRTC_POSIX'] = True
if CONFIG['OS_TARGET'] == 'Android':
DEFINES['WEBRTC_ANDROID'] = True
if CONFIG['OS_TARGET'] == 'Android':
EXPORTS += [