mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 15:28:39 +09:00
[WebRTC] updated to upstream branch 49 and related.
this patch is based on 38d7a7883...226f2f0bd
This commit is contained in:
parent
e79847e7b9
commit
a3239eaa4d
2838 changed files with 151221 additions and 159688 deletions
|
|
@ -36,6 +36,8 @@ gyp_vars = {
|
|||
# don't use openssl
|
||||
'use_openssl': 0,
|
||||
|
||||
'debug': 1 if CONFIG['DEBUG'] else 0,
|
||||
|
||||
'use_x11': 1 if CONFIG['MOZ_X11'] else 0,
|
||||
'use_glib': 1 if CONFIG['GLIB_LIBS'] else 0,
|
||||
|
||||
|
|
|
|||
|
|
@ -146,8 +146,16 @@ CaptureStreamTestHelper.prototype = {
|
|||
info("Waiting for video " + video.id + " to match [" +
|
||||
refColor.data.join(',') + "] - " + refColor.name +
|
||||
" (" + infoString + ")");
|
||||
var paintedFrames = video.mozPaintedFrames-1;
|
||||
return this.waitForPixel(video, 0, 0,
|
||||
px => this.isPixel(px, refColor, threshold))
|
||||
px => { if (paintedFrames != video.mozPaintedFrames) {
|
||||
info("Frame: " + video.mozPaintedFrames +
|
||||
" IsPixel ref=" + refColor.data +
|
||||
" threshold=" + threshold +
|
||||
" value=" + px);
|
||||
paintedFrames = video.mozPaintedFrames;
|
||||
}
|
||||
return this.isPixel(px, refColor, threshold); })
|
||||
.then(() => ok(true, video.id + " " + infoString));
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
185
dom/media/systemservices/VideoEngine.cpp
Normal file
185
dom/media/systemservices/VideoEngine.cpp
Normal 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__));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
104
dom/media/systemservices/VideoEngine.h
Normal file
104
dom/media/systemservices/VideoEngine.h
Normal 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
|
||||
92
dom/media/systemservices/VideoFrameUtils.cpp
Normal file
92
dom/media/systemservices/VideoFrameUtils.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
51
dom/media/systemservices/VideoFrameUtils.h
Normal file
51
dom/media/systemservices/VideoFrameUtils.h
Normal 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
|
||||
|
|
@ -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 += [
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulato
|
|||
skip-if = true # needed by test_enumerateDevices.html on builders
|
||||
[test_ondevicechange.html]
|
||||
skip-if = os == 'android'
|
||||
[test_getUserMedia_active_autoplay.html]
|
||||
[test_getUserMedia_audioCapture.html]
|
||||
skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_getUserMedia_addTrackRemoveTrack.html]
|
||||
|
|
@ -99,7 +98,7 @@ skip-if = toolkit == 'android' # websockets don't work on android (bug 1266217)
|
|||
[test_peerConnection_basicAudioNATRelayTCP.html]
|
||||
skip-if = toolkit == 'android' # websockets don't work on android (bug 1266217)
|
||||
[test_peerConnection_basicAudioRequireEOC.html]
|
||||
skip-if = (android_version == '18' && debug) # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_basicAudioPcmaPcmuOnly.html]
|
||||
skip-if = android_version == '18'
|
||||
[test_peerConnection_basicAudioDynamicPtMissingRtpmap.html]
|
||||
|
|
@ -127,7 +126,7 @@ skip-if = os == 'android' # bug 1043403
|
|||
[test_peerConnection_bug822674.html]
|
||||
[test_peerConnection_bug825703.html]
|
||||
[test_peerConnection_bug827843.html]
|
||||
skip-if = (android_version == '18' && debug) # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_bug834153.html]
|
||||
[test_peerConnection_bug1013809.html]
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
|
|
|
|||
|
|
@ -1415,13 +1415,17 @@ PeerConnectionWrapper.prototype = {
|
|||
* A promise that resolves when media is flowing.
|
||||
*/
|
||||
waitForRtpFlow(track) {
|
||||
var hasFlow = stats => {
|
||||
var rtp = stats.get([...stats.keys()].find(key =>
|
||||
var hasFlow = (stats, retries) => {
|
||||
info("Checking for stats in " + JSON.stringify(stats) + " for " + track.kind
|
||||
+ " track " + track.id + ", retry number " + retries);
|
||||
var rtp = stats.get([...Object.keys(stats)].find(key =>
|
||||
!stats.get(key).isRemote && stats.get(key).type.endsWith("boundrtp")));
|
||||
ok(rtp, "Should have RTP stats for track " + track.id);
|
||||
if (!rtp) {
|
||||
|
||||
return false;
|
||||
}
|
||||
info("Should have RTP stats for track " + track.id);
|
||||
info("RTP stats: "+JSON.stringify(rtp));
|
||||
var nrPackets = rtp[rtp.type == "outboundrtp" ? "packetsSent"
|
||||
: "packetsReceived"];
|
||||
info("Track " + track.id + " has " + nrPackets + " " +
|
||||
|
|
@ -1429,12 +1433,44 @@ PeerConnectionWrapper.prototype = {
|
|||
return nrPackets > 0;
|
||||
};
|
||||
|
||||
info("Checking RTP packet flow for track " + track.id);
|
||||
// Time between stats checks
|
||||
var retryInterval = 500;
|
||||
// Timeout in ms
|
||||
var timeoutInterval = 30000;
|
||||
// Check hasFlow at a reasonable interval
|
||||
var checkStats = new Promise((resolve, reject)=>{
|
||||
var retries = 0;
|
||||
var timer = setInterval(()=>{
|
||||
this._pc.getStats(track).then(stats=>{
|
||||
if (hasFlow(stats, retries)) {
|
||||
clearInterval(timer);
|
||||
ok(true, "RTP flowing for " + track.kind + " track " + track.id);
|
||||
resolve();
|
||||
}
|
||||
retries = retries + 1;
|
||||
// This is not accurate but it will tear down
|
||||
// the timer eventually and probably not
|
||||
// before timeoutInterval has elapsed.
|
||||
if ((retries * retryInterval) > timeoutInterval) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
}, retryInterval);
|
||||
});
|
||||
|
||||
var retry = (delay) => this._pc.getStats(track)
|
||||
.then(stats => hasFlow(stats)? ok(true, "RTP flowing for track " + track.id) :
|
||||
wait(delay).then(retry(1000)));
|
||||
return retry(200);
|
||||
info("Checking RTP packet flow for track " + track.id);
|
||||
var retry = Promise.race([checkStats.then(new Promise((resolve, reject)=>{
|
||||
info("checkStats completed for " + track.kind + " track " + track.id);
|
||||
resolve();
|
||||
})),
|
||||
new Promise((accept,reject)=>wait(timeoutInterval).then(()=>{
|
||||
info("Timeout checking for stats for track " + track.id + " after " + timeoutInterval + "ms");
|
||||
reject("Timeout checking for stats for " + track.kind
|
||||
+ " track " + track.id + " after " + timeoutInterval + "ms");
|
||||
})
|
||||
)]);
|
||||
|
||||
return retry;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -1536,7 +1572,9 @@ PeerConnectionWrapper.prototype = {
|
|||
var minimum = this.whenCreated - 1000; // on Windows XP (Bug 979649)
|
||||
if (isWinXP) {
|
||||
todo(false, "Can't reliably test rtcp timestamps on WinXP (Bug 979649)");
|
||||
} else if (!twoMachines) {
|
||||
|
||||
} else if (false) { // Bug 1325430 - timestamps aren't working properly in update 49
|
||||
// else if (!twoMachines) {
|
||||
// Bug 1225729: On android, sometimes the first RTCP of the first
|
||||
// test run gets this value, likely because no RTP has been sent yet.
|
||||
if (res.timestamp != 2085978496000) {
|
||||
|
|
@ -1584,8 +1622,17 @@ PeerConnectionWrapper.prototype = {
|
|||
ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived");
|
||||
ok(rem.packetsLost !== undefined, "Rtcp packetsLost");
|
||||
ok(rem.bytesReceived >= rem.packetsReceived, "Rtcp bytesReceived");
|
||||
if (!this.disableRtpCountChecking) {
|
||||
ok(rem.packetsReceived <= res.packetsSent, "No more than sent packets");
|
||||
if (false) { // Bug 1325430 if (!this.disableRtpCountChecking) {
|
||||
// no guarantee which one is newer!
|
||||
// Note: this must change when we add a timestamp field to remote RTCP reports
|
||||
// and make rem.timestamp be the reception time
|
||||
if (res.timestamp >= rem.timestamp) {
|
||||
ok(rem.packetsReceived <= res.packetsSent, "No more than sent packets");
|
||||
} else {
|
||||
info("REVERSED timestamps: rec:" +
|
||||
rem.packetsReceived + " time:" + rem.timestamp + " sent:" + res.packetsSent + " time:" + res.timestamp);
|
||||
}
|
||||
// Else we may have received more than outdated Rtcp packetsSent
|
||||
ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
|
||||
}
|
||||
ok(rem.jitter !== undefined, "Rtcp jitter");
|
||||
|
|
|
|||
|
|
@ -46,6 +46,18 @@ runNetworkTest(() => {
|
|||
// i.e., this order of `requestFrame(); draw();` should work.
|
||||
stream.requestFrame();
|
||||
h.drawColor(canvas, h.red);
|
||||
var i = 0;
|
||||
return setInterval(function() {
|
||||
try {
|
||||
info("draw " + i ? "green" : "red");
|
||||
h.drawColor(canvas, i ? h.green : h.red);
|
||||
i = 1 - i;
|
||||
stream.requestFrame();
|
||||
} catch (e) {
|
||||
// ignore; stream might have shut down, and we don't bother clearing
|
||||
// the setInterval.
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
function PC_REMOTE_WAIT_FOR_REMOTE_RED() {
|
||||
return h.waitForPixelColor(mediaElement, h.red, 128,
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ runNetworkTest(() => {
|
|||
|
||||
if (!program) {
|
||||
ok(false, "Program should link");
|
||||
return Promise.reject();
|
||||
return Promise.reject("Program should link");
|
||||
}
|
||||
gl.useProgram(program);
|
||||
|
||||
|
|
@ -100,6 +100,16 @@ runNetworkTest(() => {
|
|||
},
|
||||
function DRAW_LOCAL_RED() {
|
||||
h.drawColor(canvas, h.red);
|
||||
return setInterval(function() {
|
||||
try {
|
||||
info("draw");
|
||||
h.drawColor(canvas, h.red);
|
||||
test.pcLocal.canvasStream.requestFrame();
|
||||
} catch (e) {
|
||||
// ignore; stream might have shut down, and we don't bother clearing
|
||||
// the setInterval.
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
function WAIT_FOR_REMOTE_RED() {
|
||||
return h.waitForPixelColor(vremote, h.red, 128,
|
||||
|
|
|
|||
|
|
@ -72,15 +72,38 @@ runNetworkTest(() => {
|
|||
// After requesting a frame it will be captured at the time of next render.
|
||||
// Next render will happen at next stable state, at the earliest,
|
||||
// i.e., this order of `requestFrame(); draw();` should work.
|
||||
stream1.requestFrame();
|
||||
h.drawColor(canvas1, h.red);
|
||||
stream1.requestFrame();
|
||||
var i = 0;
|
||||
return setInterval(function() {
|
||||
try {
|
||||
info("draw " + i ? "green" : "red");
|
||||
h.drawColor(canvas1, i ? h.green : h.red);
|
||||
i = 1 - i;
|
||||
stream1.requestFrame();
|
||||
} catch (e) {
|
||||
// ignore; stream might have shut down, and we don't bother clearing
|
||||
// the setInterval.
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
function DRAW_LOCAL2_RED() {
|
||||
// After requesting a frame it will be captured at the time of next render.
|
||||
// Next render will happen at next stable state, at the earliest,
|
||||
// i.e., this order of `requestFrame(); draw();` should work.
|
||||
stream2.requestFrame();
|
||||
h.drawColor(canvas2, h.red);
|
||||
stream2.requestFrame();
|
||||
return setInterval(function() {
|
||||
try {
|
||||
info("draw");
|
||||
h.drawColor(canvas2, i ? h.green : h.red);
|
||||
i = 1 - i;
|
||||
stream2.requestFrame();
|
||||
} catch (e) {
|
||||
// ignore; stream might have shut down, and we don't bother clearing
|
||||
// the setInterval.
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
function WAIT_FOR_REMOTE1_RED() {
|
||||
return h.waitForPixelColor(vremote1, h.red, 128,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,8 @@
|
|||
test.originalOffer.sdp, test._remote_answer.sdp);
|
||||
info("Answer with RIDs: " + JSON.stringify(test._remote_answer));
|
||||
ok(test._remote_answer.sdp.match(/a=simulcast:/), "Modified answer has simulcast");
|
||||
ok(test._remote_answer.sdp.match(/a=rid:/), "Modified answer has rid");
|
||||
ok(test._remote_answer.sdp.match(/a=rid:foo/), "Modified answer has rid foo");
|
||||
ok(test._remote_answer.sdp.match(/a=rid:bar/), "Modified answer has rid bar");
|
||||
}
|
||||
]);
|
||||
|
||||
|
|
@ -118,18 +119,8 @@
|
|||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
ok(vlocal.videoWidth > 0, "source width is positive");
|
||||
ok(vlocal.videoHeight > 0, "source height is positive");
|
||||
is(vremote.videoWidth, vlocal.videoWidth / 2, "sink is 1/2 width of source");
|
||||
is(vremote.videoHeight, vlocal.videoHeight / 2, "sink is 1/2 height of source");
|
||||
},
|
||||
function PC_REMOTE_SET_RTP_NONEXISTENT_RID(test) {
|
||||
// Now, cause pcRemote to filter out everything, just to make sure
|
||||
// selectRecvSsrc is working.
|
||||
selectRecvSsrc(test.pcRemote, 2);
|
||||
},
|
||||
function PC_REMOTE_ENSURE_NO_FRAMES() {
|
||||
var vremote = test.pcRemote.remoteMediaElements[0];
|
||||
ok(vremote, "Should have remote video element for pcRemote");
|
||||
return helper.verifyNoFrames(vremote);
|
||||
is(vremote.videoWidth, vlocal.videoWidth, "sink is same width as source");
|
||||
is(vremote.videoHeight, vlocal.videoHeight, "sink is same height as source");
|
||||
},
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,18 @@ runNetworkTest(() => {
|
|||
// i.e., this order of `requestFrame(); draw();` should work.
|
||||
stream1.requestFrame();
|
||||
h1.drawColor(canvas1, h1.red);
|
||||
var i = 0;
|
||||
return setInterval(function() {
|
||||
try {
|
||||
info("draw " + i ? "green" : "red");
|
||||
h1.drawColor(canvas1, i ? h1.green : h1.red);
|
||||
i = 1 - i;
|
||||
stream1.requestFrame();
|
||||
} catch (e) {
|
||||
// ignore; stream might have shut down, and we don't bother clearing
|
||||
// the setInterval.
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
function WAIT_FOR_REMOTE_RED() {
|
||||
return h1.waitForPixelColor(vremote1, h1.red, 128,
|
||||
|
|
|
|||
|
|
@ -390,22 +390,4 @@ MediaEngineCameraVideoSource::SetDirectListeners(bool aHasDirectListeners)
|
|||
mHasDirectListeners = aHasDirectListeners;
|
||||
}
|
||||
|
||||
bool operator == (const webrtc::CaptureCapability& a,
|
||||
const webrtc::CaptureCapability& b)
|
||||
{
|
||||
return a.width == b.width &&
|
||||
a.height == b.height &&
|
||||
a.maxFPS == b.maxFPS &&
|
||||
a.rawType == b.rawType &&
|
||||
a.codecType == b.codecType &&
|
||||
a.expectedCaptureDelay == b.expectedCaptureDelay &&
|
||||
a.interlaced == b.interlaced;
|
||||
};
|
||||
|
||||
bool operator != (const webrtc::CaptureCapability& a,
|
||||
const webrtc::CaptureCapability& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -11,15 +11,18 @@
|
|||
|
||||
// conflicts with #include of scoped_ptr.h
|
||||
#undef FF
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
// Avoid warnings about redefinition of WARN_UNUSED_RESULT
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
// WebRTC includes
|
||||
#include "webrtc/modules/video_capture/video_capture_defines.h"
|
||||
|
||||
namespace webrtc {
|
||||
using CaptureCapability = VideoCaptureCapability;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
bool operator == (const webrtc::CaptureCapability& a,
|
||||
const webrtc::CaptureCapability& b);
|
||||
bool operator != (const webrtc::CaptureCapability& a,
|
||||
const webrtc::CaptureCapability& b);
|
||||
|
||||
class MediaEngineCameraVideoSource : public MediaEngineVideoSource
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -350,23 +350,23 @@ MediaEngineRemoteVideoSource::NotifyPull(MediaStreamGraph* aGraph,
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
MediaEngineRemoteVideoSource::FrameSizeChange(unsigned int w, unsigned int h,
|
||||
unsigned int streams)
|
||||
void
|
||||
MediaEngineRemoteVideoSource::FrameSizeChange(unsigned int w, unsigned int h)
|
||||
{
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
LOG(("MediaEngineRemoteVideoSource Video FrameSizeChange: %ux%u", w, h));
|
||||
return 0;
|
||||
#if defined(MOZ_WIDGET_GONK)
|
||||
mMonitor.AssertCurrentThreadOwns(); // mWidth and mHeight are protected...
|
||||
#endif
|
||||
if ((mWidth < 0) || (mHeight < 0) ||
|
||||
(w != (unsigned int) mWidth) || (h != (unsigned int) mHeight)) {
|
||||
LOG(("MediaEngineRemoteVideoSource Video FrameSizeChange: %ux%u was %ux%u", w, h, mWidth, mHeight));
|
||||
mWidth = w;
|
||||
mHeight = h;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
||||
size_t size,
|
||||
uint32_t time_stamp,
|
||||
int64_t ntp_time,
|
||||
int64_t render_time,
|
||||
void *handle)
|
||||
MediaEngineRemoteVideoSource::DeliverFrame(uint8_t* aBuffer ,
|
||||
const camera::VideoFrameProperties& aProps)
|
||||
{
|
||||
// Check for proper state.
|
||||
if (mState != kStarted) {
|
||||
|
|
@ -374,15 +374,13 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) (mWidth*mHeight + 2*(((mWidth+1)/2)*((mHeight+1)/2))) != size) {
|
||||
MOZ_ASSERT(false, "Wrong size frame in DeliverFrame!");
|
||||
return 0;
|
||||
}
|
||||
// Update the dimensions
|
||||
FrameSizeChange(aProps.width(), aProps.height());
|
||||
|
||||
// Create a video frame and append it to the track.
|
||||
RefPtr<layers::PlanarYCbCrImage> image = mImageContainer->CreatePlanarYCbCrImage();
|
||||
|
||||
uint8_t* frame = static_cast<uint8_t*> (buffer);
|
||||
uint8_t* frame = static_cast<uint8_t*> (aBuffer);
|
||||
const uint8_t lumaBpp = 8;
|
||||
const uint8_t chromaBpp = 4;
|
||||
|
||||
|
|
@ -407,8 +405,9 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
|||
|
||||
#ifdef DEBUG
|
||||
static uint32_t frame_num = 0;
|
||||
LOGFRAME(("frame %d (%dx%d); timestamp %u, ntp_time %" PRIu64 ", render_time %" PRIu64,
|
||||
frame_num++, mWidth, mHeight, time_stamp, ntp_time, render_time));
|
||||
LOGFRAME(("frame %d (%dx%d); timeStamp %u, ntpTimeMs %" PRIu64 ", renderTimeMs %" PRIu64,
|
||||
frame_num++, mWidth, mHeight,
|
||||
aProps.timeStamp(), aProps.ntpTimeMs(), aProps.renderTimeMs()));
|
||||
#endif
|
||||
|
||||
// we don't touch anything in 'this' until here (except for snapshot,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
// Avoid warnings about redefinition of WARN_UNUSED_RESULT
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaEngineCameraVideoSource.h"
|
||||
#include "VideoSegment.h"
|
||||
|
|
@ -31,40 +33,29 @@
|
|||
|
||||
// WebRTC library includes follow
|
||||
#include "webrtc/common.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
|
||||
// Camera Access via IPC
|
||||
#include "CamerasChild.h"
|
||||
|
||||
#include "NullTransport.h"
|
||||
|
||||
namespace webrtc {
|
||||
class I420VideoFrame;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* The WebRTC implementation of the MediaEngine interface.
|
||||
*/
|
||||
class MediaEngineRemoteVideoSource : public MediaEngineCameraVideoSource,
|
||||
public webrtc::ExternalRenderer
|
||||
public camera::FrameRelay
|
||||
{
|
||||
typedef MediaEngineCameraVideoSource Super;
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// Old ExternalRenderer
|
||||
void FrameSizeChange(unsigned int w, unsigned int h) override;
|
||||
// ExternalRenderer
|
||||
int FrameSizeChange(unsigned int w, unsigned int h,
|
||||
unsigned int streams) override;
|
||||
int DeliverFrame(unsigned char* buffer,
|
||||
size_t size,
|
||||
uint32_t time_stamp,
|
||||
int64_t ntp_time,
|
||||
int64_t render_time,
|
||||
void *handle) override;
|
||||
// XXX!!!! FIX THIS
|
||||
int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override { return 0; };
|
||||
bool IsTextureSupported() override { return false; };
|
||||
int DeliverFrame(uint8_t* buffer,
|
||||
const camera::VideoFrameProperties& properties) override;
|
||||
|
||||
// MediaEngineCameraVideoSource
|
||||
MediaEngineRemoteVideoSource(int aIndex, mozilla::camera::CaptureEngine aCapEngine,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "MediaEngineCameraVideoSource.h"
|
||||
#include "VideoSegment.h"
|
||||
|
|
@ -36,6 +37,8 @@
|
|||
|
||||
#include "MediaEngineWrapper.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "CamerasChild.h"
|
||||
|
||||
// WebRTC library includes follow
|
||||
#include "webrtc/common.h"
|
||||
// Audio Engine
|
||||
|
|
@ -52,11 +55,9 @@
|
|||
// Video Engine
|
||||
// conflicts with #include of scoped_ptr.h
|
||||
#undef FF
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "CamerasChild.h"
|
||||
|
||||
// WebRTC imports
|
||||
#include "webrtc/modules/video_capture/video_capture_defines.h"
|
||||
|
||||
#include "NullTransport.h"
|
||||
#include "AudioOutputObserver.h"
|
||||
|
|
@ -256,10 +257,10 @@ public:
|
|||
MOZ_ASSERT(mDevices);
|
||||
|
||||
if (mInUseCount == 0) {
|
||||
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> ptrVoERender;
|
||||
ptrVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
|
||||
if (ptrVoERender) {
|
||||
ptrVoERender->SetExternalRecordingStatus(true);
|
||||
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> ptrVoEXMedia;
|
||||
ptrVoEXMedia = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
|
||||
if (ptrVoEXMedia) {
|
||||
ptrVoEXMedia->SetExternalRecordingStatus(true);
|
||||
}
|
||||
mAnyInUse = true;
|
||||
}
|
||||
|
|
@ -475,9 +476,9 @@ public:
|
|||
const nsString& aDeviceId) const override;
|
||||
|
||||
// VoEMediaProcess.
|
||||
void Process(int channel, webrtc::ProcessingTypes type,
|
||||
int16_t audio10ms[], int length,
|
||||
int samplingFreq, bool isStereo) override;
|
||||
virtual void Process(int channel, webrtc::ProcessingTypes type,
|
||||
int16_t audio10ms[], size_t length,
|
||||
int samplingFreq, bool isStereo) override;
|
||||
|
||||
void Shutdown() override;
|
||||
|
||||
|
|
|
|||
|
|
@ -824,7 +824,7 @@ typedef int16_t sample;
|
|||
void
|
||||
MediaEngineWebRTCMicrophoneSource::Process(int channel,
|
||||
webrtc::ProcessingTypes type,
|
||||
sample *audio10ms, int length,
|
||||
sample *audio10ms, size_t length,
|
||||
int samplingFreq, bool isStereo)
|
||||
{
|
||||
MOZ_ASSERT(!PassThrough(), "This should be bypassed when in PassThrough mode.");
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
using dom::ConstrainBooleanParameters;
|
||||
using dom::OwningLongOrConstrainLongRange;
|
||||
|
||||
template<class ValueType>
|
||||
template<class ConstrainRange>
|
||||
void
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ nrappkit copyright:
|
|||
#include "mozilla/Unused.h"
|
||||
#include "databuffer.h"
|
||||
|
||||
// mozilla/utils.h defines this as well
|
||||
#ifdef UNIMPLEMENTED
|
||||
#undef UNIMPLEMENTED
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "nr_api.h"
|
||||
#include "async_wait.h"
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ include('/build/gyp.mozbuild')
|
|||
webrtc_non_unified_sources = [
|
||||
'trunk/webrtc/common_audio/vad/vad_core.c', # Because of name clash in the kInitCheck variable
|
||||
'trunk/webrtc/common_audio/vad/webrtc_vad.c', # Because of name clash in the kInitCheck variable
|
||||
'trunk/webrtc/modules/audio_coding/acm2/codec_manager.cc', # Because of duplicate IsCodecRED/etc
|
||||
'trunk/webrtc/modules/audio_coding/codecs/g722/g722_decode.c', # Because of name clash in the saturate function
|
||||
'trunk/webrtc/modules/audio_coding/codecs/g722/g722_encode.c', # Because of name clash in the saturate function
|
||||
'trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c', # Because of name clash in the kDampFilter variable
|
||||
'trunk/webrtc/modules/audio_coding/codecs/isac/fix/source/pitch_filter_c.c', # Because of name clash in the kDampFilter variable
|
||||
'trunk/webrtc/modules/audio_coding/main/acm2/codec_manager.cc', # Because of duplicate IsCodecRED/etc
|
||||
'trunk/webrtc/modules/audio_coding/neteq/audio_vector.cc', # Because of explicit template specializations
|
||||
'trunk/webrtc/modules/audio_device/android/audio_manager.cc', # Because of TAG redefinition
|
||||
'trunk/webrtc/modules/audio_device/android/audio_record_jni.cc', # Becuse of commonly named module static vars
|
||||
'trunk/webrtc/modules/audio_device/android/audio_track_jni.cc', # Becuse of commonly named module static vars
|
||||
'trunk/webrtc/modules/audio_device/android/audio_track_jni.cc', # Becuse of commonly named module static vars
|
||||
'trunk/webrtc/modules/audio_device/android/opensles_player.cc', # Because of TAG redefinition
|
||||
'trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc', # Because of LATE()
|
||||
'trunk/webrtc/modules/audio_device/linux/audio_mixer_manager_pulse_linux.cc',# Because of LATE()
|
||||
'trunk/webrtc/modules/audio_device/opensl/opensles_input.cc', # Because of name clash in the kOption variable
|
||||
'trunk/webrtc/modules/audio_device/opensl/opensles_output.cc', # Because of name clash in the kOption variable
|
||||
'trunk/webrtc/modules/audio_device/opensl/single_rw_fifo.cc', # Because of name clash with #define FF
|
||||
'trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc', # Because of ordering assumptions in strsafe.h
|
||||
'trunk/webrtc/modules/audio_processing/aec/aec_core.c', # Because of name clash in the ComfortNoise function
|
||||
|
|
@ -34,12 +34,15 @@ webrtc_non_unified_sources = [
|
|||
'trunk/webrtc/modules/audio_processing/gain_control_impl.cc', # Because of name clash in the Handle typedef
|
||||
'trunk/webrtc/modules/audio_processing/high_pass_filter_impl.cc', # Because of name clash in the Handle typedef
|
||||
'trunk/webrtc/modules/audio_processing/noise_suppression_impl.cc', # Because of name clash in the Handle typedef
|
||||
'trunk/webrtc/modules/remote_bitrate_estimator/mimd_rate_control.cc', # Because of duplicate definitions of static consts against aimd_rate_control.cc
|
||||
'trunk/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.cc', # Because of duplicate definitions of static consts against remote_bitrate_estimator_abs_send_time.cc
|
||||
'trunk/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.cc', # Because of identically named functions and vars between tmmbr.cc and tmmbn.cc in an anonymous namespaces
|
||||
'trunk/webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.cc', # Because of identically named functions and vars between tmmbr.cc and tmmbn.cc in an anonymous namespaces
|
||||
'trunk/webrtc/modules/video_capture/android/device_info_android.cc', # Because of duplicate module static variable names
|
||||
'trunk/webrtc/modules/video_capture/android/video_capture_android.cc', # Because of duplicate module static variable names
|
||||
'trunk/webrtc/modules/video_capture/windows/device_info_ds.cc', # Because of the MEDIASUBTYPE_HDYC variable
|
||||
'trunk/webrtc/modules/video_capture/windows/help_functions_ds.cc', # Because of initguid.h
|
||||
'trunk/webrtc/modules/video_capture/windows/sink_filter_ds.cc', # Because of the MEDIASUBTYPE_HDYC variable and initguid.h
|
||||
'trunk/webrtc/video_engine/overuse_frame_detector.cc', # Because of name clash with call_stats.cc on kWeightFactor
|
||||
'trunk/webrtc/video/overuse_frame_detector.cc', # Because of name clash with call_stats.cc on kWeightFactor
|
||||
]
|
||||
|
||||
GYP_DIRS += ['trunk']
|
||||
|
|
@ -65,7 +68,6 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']:
|
|||
'signaling/src/common/browser_logging/CSFLog.cpp',
|
||||
'signaling/src/jsep/JsepSessionImpl.cpp',
|
||||
'signaling/src/media-conduit/AudioConduit.cpp',
|
||||
'signaling/src/media-conduit/CodecStatistics.cpp',
|
||||
'signaling/src/media-conduit/MediaCodecVideoCodec.cpp',
|
||||
'signaling/src/media-conduit/VideoConduit.cpp',
|
||||
'signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp',
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@
|
|||
'./src/media-conduit/AudioConduit.cpp',
|
||||
'./src/media-conduit/VideoConduit.h',
|
||||
'./src/media-conduit/VideoConduit.cpp',
|
||||
'./src/media-conduit/CodecStatistics.h',
|
||||
'./src/media-conduit/CodecStatistics.cpp',
|
||||
'./src/media-conduit/RunningStat.h',
|
||||
# Common
|
||||
'./src/common/CommonTypes.h',
|
||||
|
|
|
|||
|
|
@ -41,6 +41,18 @@ public:
|
|||
scaleDownBy == constraints.scaleDownBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the constraints affecting resolution are equal.
|
||||
*/
|
||||
bool ResolutionEquals(const EncodingConstraints& constraints) const
|
||||
{
|
||||
return
|
||||
maxWidth == constraints.maxWidth &&
|
||||
maxHeight == constraints.maxHeight &&
|
||||
maxFs == constraints.maxFs &&
|
||||
scaleDownBy == constraints.scaleDownBy;
|
||||
}
|
||||
|
||||
uint32_t maxWidth;
|
||||
uint32_t maxHeight;
|
||||
uint32_t maxFps;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/transport.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
@ -18,6 +18,23 @@ namespace mozilla {
|
|||
class NullTransport : public webrtc::Transport
|
||||
{
|
||||
public:
|
||||
virtual bool SendRtp(const uint8_t* packet,
|
||||
size_t length,
|
||||
const webrtc::PacketOptions& options) override
|
||||
{
|
||||
(void) packet;
|
||||
(void) length;
|
||||
(void) options;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool SendRtcp(const uint8_t* packet, size_t length) override
|
||||
{
|
||||
(void) packet;
|
||||
(void) length;
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
virtual int SendPacket(int channel, const void *data, size_t len)
|
||||
{
|
||||
(void) channel; (void) data;
|
||||
|
|
@ -29,7 +46,7 @@ public:
|
|||
(void) channel; (void) data;
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
NullTransport() {}
|
||||
|
||||
virtual ~NullTransport() {}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "prenv.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
#include "nscore.h"
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "logging.h"
|
||||
|
||||
#include "webrtc/config.h"
|
||||
#include "signaling/src/jsep/JsepSessionImpl.h"
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
|
@ -116,15 +117,35 @@ JsepSessionImpl::AddTrack(const RefPtr<JsepTrack>& track)
|
|||
{
|
||||
mLastError.clear();
|
||||
MOZ_ASSERT(track->GetDirection() == sdp::kSend);
|
||||
|
||||
MOZ_MTLOG(ML_DEBUG, "Adding track.");
|
||||
if (track->GetMediaType() != SdpMediaSection::kApplication) {
|
||||
track->SetCNAME(mCNAME);
|
||||
|
||||
if (track->GetSsrcs().empty()) {
|
||||
uint32_t ssrc;
|
||||
// Establish minimum number of required SSRCs
|
||||
// Note that AddTrack is only for send direction
|
||||
size_t minimumSsrcCount = 0;
|
||||
std::vector<JsepTrack::JsConstraints> constraints;
|
||||
track->GetJsConstraints(&constraints);
|
||||
for (auto constraint : constraints) {
|
||||
if (constraint.rid != "") {
|
||||
minimumSsrcCount++;
|
||||
}
|
||||
}
|
||||
// We need at least 1 SSRC
|
||||
minimumSsrcCount = std::max<size_t>(1, minimumSsrcCount);
|
||||
size_t currSsrcCount = track->GetSsrcs().size();
|
||||
if (currSsrcCount < minimumSsrcCount ) {
|
||||
MOZ_MTLOG(ML_DEBUG,
|
||||
"Adding " << (minimumSsrcCount - currSsrcCount) << " SSRCs.");
|
||||
}
|
||||
while (track->GetSsrcs().size() < minimumSsrcCount) {
|
||||
uint32_t ssrc=0;
|
||||
nsresult rv = CreateSsrc(&ssrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
track->AddSsrc(ssrc);
|
||||
// Don't add duplicate ssrcs
|
||||
std::vector<uint32_t> ssrcs = track->GetSsrcs();
|
||||
if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) == ssrcs.end()) {
|
||||
track->AddSsrc(ssrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -287,19 +308,62 @@ JsepSessionImpl::SetParameters(const std::string& streamId,
|
|||
// Add RtpStreamId Extmap
|
||||
// SdpDirectionAttribute::Direction is a bitmask
|
||||
SdpDirectionAttribute::Direction addVideoExt = SdpDirectionAttribute::kInactive;
|
||||
SdpDirectionAttribute::Direction addAudioExt = SdpDirectionAttribute::kInactive;
|
||||
for (auto constraintEntry: constraints) {
|
||||
if (constraintEntry.rid != "") {
|
||||
if (it->mTrack->GetMediaType() == SdpMediaSection::kVideo) {
|
||||
addVideoExt = static_cast<SdpDirectionAttribute::Direction>(addVideoExt
|
||||
| it->mTrack->GetDirection());
|
||||
switch (it->mTrack->GetMediaType()) {
|
||||
case SdpMediaSection::kVideo: {
|
||||
addVideoExt = static_cast<SdpDirectionAttribute::Direction>(addVideoExt
|
||||
| it->mTrack->GetDirection());
|
||||
break;
|
||||
}
|
||||
case SdpMediaSection::kAudio: {
|
||||
addAudioExt = static_cast<SdpDirectionAttribute::Direction>(addAudioExt
|
||||
| it->mTrack->GetDirection());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addVideoExt != SdpDirectionAttribute::kInactive) {
|
||||
AddVideoRtpExtension("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", addVideoExt);
|
||||
}
|
||||
if (addAudioExt != SdpDirectionAttribute::kInactive) {
|
||||
AddAudioRtpExtension("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", addAudioExt);
|
||||
}
|
||||
|
||||
it->mTrack->SetJsConstraints(constraints);
|
||||
|
||||
auto track = it->mTrack;
|
||||
if (track->GetDirection() == sdp::kSend) {
|
||||
// Establish minimum number of required SSRCs
|
||||
// Note that AddTrack is only for send direction
|
||||
size_t minimumSsrcCount = 0;
|
||||
std::vector<JsepTrack::JsConstraints> constraints;
|
||||
track->GetJsConstraints(&constraints);
|
||||
for (auto constraint : constraints) {
|
||||
if (constraint.rid != "") {
|
||||
minimumSsrcCount++;
|
||||
}
|
||||
}
|
||||
// We need at least 1 SSRC
|
||||
minimumSsrcCount = std::max<size_t>(1, minimumSsrcCount);
|
||||
size_t currSsrcCount = track->GetSsrcs().size();
|
||||
if (currSsrcCount < minimumSsrcCount ) {
|
||||
MOZ_MTLOG(ML_DEBUG,
|
||||
"Adding " << (minimumSsrcCount - currSsrcCount) << " SSRCs.");
|
||||
}
|
||||
while (track->GetSsrcs().size() < minimumSsrcCount) {
|
||||
uint32_t ssrc=0;
|
||||
nsresult rv = CreateSsrc(&ssrc);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Don't add duplicate ssrcs
|
||||
std::vector<uint32_t> ssrcs = track->GetSsrcs();
|
||||
if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) == ssrcs.end()) {
|
||||
track->AddSsrc(ssrc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -2218,6 +2282,7 @@ JsepSessionImpl::SetupDefaultCodecs()
|
|||
);
|
||||
mSupportedCodecs.values.push_back(ulpfec);
|
||||
|
||||
|
||||
mSupportedCodecs.values.push_back(new JsepApplicationCodecDescription(
|
||||
"5000",
|
||||
"webrtc-datachannel",
|
||||
|
|
|
|||
|
|
@ -261,6 +261,9 @@ JsepTrack::CreateEncodings(
|
|||
const std::vector<JsepCodecDescription*>& negotiatedCodecs,
|
||||
JsepTrackNegotiatedDetails* negotiatedDetails)
|
||||
{
|
||||
negotiatedDetails->mTias = remote.GetBandwidth("TIAS");
|
||||
// TODO add support for b=AS if TIAS is not set (bug 976521)
|
||||
|
||||
std::vector<SdpRidAttributeList::Rid> rids;
|
||||
GetRids(remote, sdp::kRecv, &rids); // Get rids we will send
|
||||
NegotiateRids(rids, &mJsEncodeConstraints);
|
||||
|
|
@ -294,8 +297,6 @@ JsepTrack::CreateEncodings(
|
|||
encoding->mConstraints = jsConstraints.constraints;
|
||||
}
|
||||
}
|
||||
|
||||
encoding->UpdateMaxBitrate(remote);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef _JSEPTRACK_H_
|
||||
#define _JSEPTRACK_H_
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
|
@ -28,6 +29,10 @@ namespace mozilla {
|
|||
class JsepTrackNegotiatedDetails
|
||||
{
|
||||
public:
|
||||
JsepTrackNegotiatedDetails() :
|
||||
mTias(0)
|
||||
{}
|
||||
|
||||
size_t
|
||||
GetEncodingCount() const
|
||||
{
|
||||
|
|
@ -51,17 +56,32 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ForEachRTPHeaderExtension(
|
||||
const std::function<void(const SdpExtmapAttributeList::Extmap& extmap)> & fn) const
|
||||
{
|
||||
for(auto entry: mExtmap) {
|
||||
fn(entry.second);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GetUniquePayloadTypes() const
|
||||
{
|
||||
return mUniquePayloadTypes;
|
||||
}
|
||||
|
||||
uint32_t GetTias() const
|
||||
{
|
||||
return mTias;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class JsepTrack;
|
||||
|
||||
std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
|
||||
std::vector<uint8_t> mUniquePayloadTypes;
|
||||
PtrVector<JsepTrackEncoding> mEncodings;
|
||||
uint32_t mTias; // bits per second
|
||||
};
|
||||
|
||||
class JsepTrack
|
||||
|
|
|
|||
|
|
@ -38,16 +38,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
void UpdateMaxBitrate(const SdpMediaSection& remote)
|
||||
{
|
||||
uint32_t tias = remote.GetBandwidth("TIAS");
|
||||
// select minimum of the two which is not zero
|
||||
mConstraints.maxBr = std::min(tias ? tias : mConstraints.maxBr,
|
||||
mConstraints.maxBr ? mConstraints.maxBr :
|
||||
tias);
|
||||
// TODO add support for b=AS if TIAS is not set (bug 976521)
|
||||
}
|
||||
|
||||
EncodingConstraints mConstraints;
|
||||
std::string mRid;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,11 +25,11 @@
|
|||
|
||||
#include "webrtc/common.h"
|
||||
#include "webrtc/modules/audio_processing/include/audio_processing.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
|
||||
#include "webrtc/voice_engine/include/voe_dtmf.h"
|
||||
#include "webrtc/voice_engine/include/voe_errors.h"
|
||||
#include "webrtc/voice_engine/voice_engine_impl.h"
|
||||
#include "webrtc/system_wrappers/interface/clock.h"
|
||||
#include "webrtc/system_wrappers/include/clock.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
@ -89,7 +89,9 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
mPtrVoEBase->StopSend(mChannel);
|
||||
mPtrVoEBase->StopReceive(mChannel);
|
||||
mPtrVoEBase->DeleteChannel(mChannel);
|
||||
mPtrVoEBase->Terminate();
|
||||
// We don't Terminate() the VoEBase here, because the Call (owned by
|
||||
// PeerConnectionMedia) actually owns the (shared) VoEBase/VoiceEngine
|
||||
// here
|
||||
}
|
||||
|
||||
// We shouldn't delete the VoiceEngine until all these are released!
|
||||
|
|
@ -103,21 +105,24 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
mPtrVoERTP_RTCP = nullptr;
|
||||
mPtrRTP = nullptr;
|
||||
|
||||
if(mVoiceEngine)
|
||||
if (mVoiceEngine)
|
||||
{
|
||||
webrtc::VoiceEngine::Delete(mVoiceEngine);
|
||||
}
|
||||
}
|
||||
|
||||
bool WebrtcAudioConduit::SetLocalSSRC(unsigned int ssrc)
|
||||
bool WebrtcAudioConduit::SetLocalSSRCs(const std::vector<unsigned int> & aSSRCs)
|
||||
{
|
||||
unsigned int oldSsrc;
|
||||
if (!GetLocalSSRC(&oldSsrc)) {
|
||||
// This should hold true until the WebRTC.org VoE refactor
|
||||
MOZ_ASSERT(aSSRCs.size() == 1,"WebrtcAudioConduit::SetLocalSSRCs accepts exactly 1 ssrc.");
|
||||
|
||||
std::vector<unsigned int> oldSsrcs = GetLocalSSRCs();
|
||||
if (oldSsrcs.empty()) {
|
||||
MOZ_ASSERT(false, "GetLocalSSRC failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oldSsrc == ssrc) {
|
||||
if (oldSsrcs == aSSRCs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +131,7 @@ bool WebrtcAudioConduit::SetLocalSSRC(unsigned int ssrc)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mPtrRTP->SetLocalSSRC(mChannel, ssrc)) {
|
||||
if (mPtrRTP->SetLocalSSRC(mChannel, aSSRCs[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -138,8 +143,12 @@ bool WebrtcAudioConduit::SetLocalSSRC(unsigned int ssrc)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WebrtcAudioConduit::GetLocalSSRC(unsigned int* ssrc) {
|
||||
return !mPtrRTP->GetLocalSSRC(mChannel, *ssrc);
|
||||
std::vector<unsigned int> WebrtcAudioConduit::GetLocalSSRCs() const {
|
||||
unsigned int ssrc;
|
||||
if (!mPtrRTP->GetLocalSSRC(mChannel, ssrc)) {
|
||||
return std::vector<unsigned int>(1,ssrc);
|
||||
}
|
||||
return std::vector<unsigned int>();
|
||||
}
|
||||
|
||||
bool WebrtcAudioConduit::GetRemoteSSRC(unsigned int* ssrc) {
|
||||
|
|
@ -270,6 +279,13 @@ MediaConduitErrorCode WebrtcAudioConduit::Init()
|
|||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
// init the engine with our audio device layer
|
||||
if(mPtrVoEBase->Init() == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if(!(mPtrVoENetwork = VoENetwork::GetInterface(mVoiceEngine)))
|
||||
{
|
||||
CSFLogError(logTag, "%s Unable to initialize VoENetwork", __FUNCTION__);
|
||||
|
|
@ -310,13 +326,6 @@ MediaConduitErrorCode WebrtcAudioConduit::Init()
|
|||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
// init the engine with our audio device layer
|
||||
if(mPtrVoEBase->Init() == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine Base Not Initialized", __FUNCTION__);
|
||||
return kMediaConduitSessionNotInited;
|
||||
}
|
||||
|
||||
if( (mChannel = mPtrVoEBase->CreateChannel()) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s VoiceEngine Channel creation failed",__FUNCTION__);
|
||||
|
|
@ -857,7 +866,6 @@ WebrtcAudioConduit::StartReceiving()
|
|||
return kMediaConduitUnknownError;
|
||||
}
|
||||
|
||||
|
||||
if(mPtrVoEBase->StartPlayout(mChannel) == -1)
|
||||
{
|
||||
CSFLogError(logTag, "%s Starting playout Failed", __FUNCTION__);
|
||||
|
|
@ -871,9 +879,12 @@ WebrtcAudioConduit::StartReceiving()
|
|||
|
||||
//WebRTC::RTP Callback Implementation
|
||||
// Called on AudioGUM or MSG thread
|
||||
int WebrtcAudioConduit::SendPacket(int channel, const void* data, size_t len)
|
||||
bool
|
||||
WebrtcAudioConduit::SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
const webrtc::PacketOptions& options)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d", __FUNCTION__, channel);
|
||||
CSFLogDebug(logTag, "%s: len %lu", __FUNCTION__, (unsigned long)len);
|
||||
|
||||
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
|
||||
if (MOZ_LOG_TEST(GetLatencyLog(), LogLevel::Debug)) {
|
||||
|
|
@ -888,25 +899,30 @@ int WebrtcAudioConduit::SendPacket(int channel, const void* data, size_t len)
|
|||
}
|
||||
#endif
|
||||
ReentrantMonitorAutoEnter enter(mTransportMonitor);
|
||||
// XXX(pkerr) - the PacketOptions are being ignored. This parameter was added along
|
||||
// with the Call API update in the webrtc.org codebase.
|
||||
// The only field in it is the packet_id, which is used when the header
|
||||
// extension for TransportSequenceNumber is being used, which we don't.
|
||||
(void) options;
|
||||
if(mTransmitterTransport &&
|
||||
(mTransmitterTransport->SendRtpPacket(data, len) == NS_OK))
|
||||
{
|
||||
CSFLogDebug(logTag, "%s Sent RTP Packet ", __FUNCTION__);
|
||||
return len;
|
||||
return true;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s RTP Packet Send Failed ", __FUNCTION__);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Called on WebRTC Process thread and perhaps others
|
||||
int WebrtcAudioConduit::SendRTCPPacket(int channel, const void* data, size_t len)
|
||||
bool
|
||||
WebrtcAudioConduit::SendRtcp(const uint8_t* data, size_t len)
|
||||
{
|
||||
CSFLogDebug(logTag, "%s : channel %d , len %lu, first rtcp = %u ",
|
||||
CSFLogDebug(logTag, "%s : len %lu, first rtcp = %u ",
|
||||
__FUNCTION__,
|
||||
channel,
|
||||
(unsigned long) len,
|
||||
static_cast<unsigned>(((uint8_t *) data)[1]));
|
||||
static_cast<unsigned>(data[1]));
|
||||
|
||||
// We come here if we have only one pipeline/conduit setup,
|
||||
// such as for unidirectional streams.
|
||||
|
|
@ -917,14 +933,14 @@ int WebrtcAudioConduit::SendRTCPPacket(int channel, const void* data, size_t len
|
|||
{
|
||||
// Might be a sender report, might be a receiver report, we don't know.
|
||||
CSFLogDebug(logTag, "%s Sent RTCP Packet ", __FUNCTION__);
|
||||
return len;
|
||||
return true;
|
||||
} else if(mTransmitterTransport &&
|
||||
(mTransmitterTransport->SendRtcpPacket(data, len) == NS_OK)) {
|
||||
CSFLogDebug(logTag, "%s Sent RTCP Packet (sender report) ", __FUNCTION__);
|
||||
return len;
|
||||
return true;
|
||||
} else {
|
||||
CSFLogError(logTag, "%s RTCP Packet Send Failed ", __FUNCTION__);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
// Audio Engine Includes
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/transport.h"
|
||||
#include "webrtc/voice_engine/include/voe_base.h"
|
||||
#include "webrtc/voice_engine/include/voe_volume_control.h"
|
||||
#include "webrtc/voice_engine/include/voe_codec.h"
|
||||
|
|
@ -45,8 +46,8 @@ NTPtoDOMHighResTimeStamp(uint32_t ntpHigh, uint32_t ntpLow);
|
|||
* Concrete class for Audio session. Hooks up
|
||||
* - media-source and target to external transport
|
||||
*/
|
||||
class WebrtcAudioConduit:public AudioSessionConduit
|
||||
,public webrtc::Transport
|
||||
class WebrtcAudioConduit: public AudioSessionConduit
|
||||
, public webrtc::Transport
|
||||
{
|
||||
public:
|
||||
//VoiceEngine defined constant for Payload Name Size.
|
||||
|
|
@ -150,20 +151,22 @@ public:
|
|||
* Webrtc transport implementation to send and receive RTP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VoiceEngine
|
||||
*/
|
||||
virtual int SendPacket(int channel, const void *data, size_t len) override;
|
||||
virtual bool SendRtp(const uint8_t* data,
|
||||
size_t len,
|
||||
const webrtc::PacketOptions& options) override;
|
||||
|
||||
/**
|
||||
* Webrtc transport implementation to send and receive RTCP packet.
|
||||
* AudioConduit registers itself as ExternalTransport to the VoiceEngine
|
||||
*/
|
||||
virtual int SendRTCPPacket(int channel, const void *data, size_t len) override;
|
||||
|
||||
virtual bool SendRtcp(const uint8_t *data,
|
||||
size_t len) override;
|
||||
|
||||
virtual uint64_t CodecPluginID() override { return 0; }
|
||||
|
||||
virtual void DeleteStreams() override {}
|
||||
|
||||
WebrtcAudioConduit():
|
||||
|
||||
explicit WebrtcAudioConduit():
|
||||
mVoiceEngine(nullptr),
|
||||
mTransportMonitor("WebrtcAudioConduit"),
|
||||
mTransmitterTransport(nullptr),
|
||||
|
|
@ -188,8 +191,17 @@ public:
|
|||
|
||||
int GetChannel() { return mChannel; }
|
||||
webrtc::VoiceEngine* GetVoiceEngine() { return mVoiceEngine; }
|
||||
bool SetLocalSSRC(unsigned int ssrc) override;
|
||||
bool GetLocalSSRC(unsigned int* ssrc) override;
|
||||
|
||||
/* Set Local SSRC list.
|
||||
* Note: Until the refactor of the VoE into the call API is complete
|
||||
* this list should contain only a single ssrc.
|
||||
*/
|
||||
bool SetLocalSSRCs(const std::vector<unsigned int>& aSSRCs) override;
|
||||
std::vector<unsigned int> GetLocalSSRCs() const override;
|
||||
bool SetRemoteSSRC(unsigned int ssrc) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool GetRemoteSSRC(unsigned int* ssrc) override;
|
||||
bool SetLocalCNAME(const char* cname) override;
|
||||
bool GetVideoEncoderStats(double* framerateMean,
|
||||
|
|
|
|||
|
|
@ -90,10 +90,15 @@ public:
|
|||
bool mRembFbSet;
|
||||
bool mFECFbSet;
|
||||
|
||||
uint32_t mTias;
|
||||
EncodingConstraints mEncodingConstraints;
|
||||
struct SimulcastEncoding {
|
||||
std::string rid;
|
||||
EncodingConstraints constraints;
|
||||
bool operator==(const SimulcastEncoding& aOther) const {
|
||||
return rid == aOther.rid &&
|
||||
constraints == aOther.constraints;
|
||||
}
|
||||
};
|
||||
std::vector<SimulcastEncoding> mSimulcastEncodings;
|
||||
std::string mSpropParameterSets;
|
||||
|
|
@ -103,6 +108,28 @@ public:
|
|||
uint8_t mPacketizationMode;
|
||||
// TODO: add external negotiated SPS/PPS
|
||||
|
||||
bool operator==(const VideoCodecConfig& aRhs) const {
|
||||
if (mType != aRhs.mType ||
|
||||
mName != aRhs.mName ||
|
||||
mAckFbTypes != aRhs.mAckFbTypes ||
|
||||
mNackFbTypes != aRhs.mNackFbTypes ||
|
||||
mCcmFbTypes != aRhs.mCcmFbTypes ||
|
||||
mRembFbSet != aRhs.mRembFbSet ||
|
||||
mFECFbSet != aRhs.mFECFbSet ||
|
||||
mTias != aRhs.mTias ||
|
||||
!(mEncodingConstraints == aRhs.mEncodingConstraints) ||
|
||||
!(mSimulcastEncodings == aRhs.mSimulcastEncodings) ||
|
||||
mSpropParameterSets != aRhs.mSpropParameterSets ||
|
||||
mProfile != aRhs.mProfile ||
|
||||
mConstraints != aRhs.mConstraints ||
|
||||
mLevel != aRhs.mLevel ||
|
||||
mPacketizationMode != aRhs.mPacketizationMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
VideoCodecConfig(int type,
|
||||
std::string name,
|
||||
const EncodingConstraints& constraints,
|
||||
|
|
@ -110,6 +137,7 @@ public:
|
|||
mType(type),
|
||||
mName(name),
|
||||
mFECFbSet(false),
|
||||
mTias(0),
|
||||
mEncodingConstraints(constraints),
|
||||
mProfile(0x42),
|
||||
mConstraints(0xE0),
|
||||
|
|
@ -125,6 +153,20 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool ResolutionEquals(const VideoCodecConfig& aConfig) const
|
||||
{
|
||||
if (mSimulcastEncodings.size() != aConfig.mSimulcastEncodings.size()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < mSimulcastEncodings.size(); ++i) {
|
||||
if (!mSimulcastEncodings[i].constraints.ResolutionEquals(
|
||||
aConfig.mSimulcastEncodings[i].constraints)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing seems to use this right now. Do we intend to support this
|
||||
// someday?
|
||||
bool RtcpFbAckIsSet(const std::string& type) const
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
VideoEncoder* GmpVideoCodec::CreateEncoder() {
|
||||
return static_cast<VideoEncoder*>(new WebrtcVideoEncoderProxy());
|
||||
WebrtcVideoEncoder* GmpVideoCodec::CreateEncoder() {
|
||||
return new WebrtcVideoEncoderProxy();
|
||||
}
|
||||
|
||||
VideoDecoder* GmpVideoCodec::CreateDecoder() {
|
||||
return static_cast<VideoDecoder*>(new WebrtcVideoDecoderProxy());
|
||||
WebrtcVideoDecoder* GmpVideoCodec::CreateDecoder() {
|
||||
return new WebrtcVideoDecoderProxy();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
namespace mozilla {
|
||||
class GmpVideoCodec {
|
||||
public:
|
||||
static VideoEncoder* CreateEncoder();
|
||||
static VideoDecoder* CreateDecoder();
|
||||
static WebrtcVideoEncoder* CreateEncoder();
|
||||
static WebrtcVideoDecoder* CreateDecoder();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace mozilla {
|
|||
|
||||
static const char* logTag ="MediaCodecVideoCodec";
|
||||
|
||||
VideoEncoder* MediaCodecVideoCodec::CreateEncoder(CodecType aCodecType) {
|
||||
WebrtcVideoEncoder* MediaCodecVideoCodec::CreateEncoder(CodecType aCodecType) {
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
if (aCodecType == CODEC_VP8) {
|
||||
return new WebrtcMediaCodecVP8VideoEncoder();
|
||||
|
|
@ -20,7 +20,7 @@ VideoEncoder* MediaCodecVideoCodec::CreateEncoder(CodecType aCodecType) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
VideoDecoder* MediaCodecVideoCodec::CreateDecoder(CodecType aCodecType) {
|
||||
WebrtcVideoDecoder* MediaCodecVideoCodec::CreateDecoder(CodecType aCodecType) {
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
if (aCodecType == CODEC_VP8) {
|
||||
return new WebrtcMediaCodecVP8VideoDecoder();
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ class MediaCodecVideoCodec {
|
|||
* Create encoder object for codec type |aCodecType|. Return |nullptr| when
|
||||
* failed.
|
||||
*/
|
||||
static VideoEncoder* CreateEncoder(CodecType aCodecType);
|
||||
static WebrtcVideoEncoder* CreateEncoder(CodecType aCodecType);
|
||||
|
||||
/**
|
||||
* Create decoder object for codec type |aCodecType|. Return |nullptr| when
|
||||
* failed.
|
||||
*/
|
||||
static VideoDecoder* CreateDecoder(CodecType aCodecType);
|
||||
static WebrtcVideoDecoder* CreateDecoder(CodecType aCodecType);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ kMediaConduitKeyFrameRequestError, // Can't set KeyFrameRequest mode
|
|||
kMediaConduitNACKStatusError, // Can't set NACK mode
|
||||
kMediaConduitTMMBRStatusError, // Can't set TMMBR mode
|
||||
kMediaConduitFECStatusError, // Can't set FEC mode
|
||||
kMediaConduitHybridNACKFECStatusError // Can't set Hybrid NACK / FEC mode
|
||||
kMediaConduitHybridNACKFECStatusError, // Can't set Hybrid NACK / FEC mode
|
||||
kMediaConduitVideoSendStreamError // WebRTC video send stream failure
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -9,20 +9,64 @@
|
|||
#include "nsXPCOM.h"
|
||||
#include "nsDOMNavigationTiming.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/utils.h"
|
||||
#include "CodecConfig.h"
|
||||
#include "VideoTypes.h"
|
||||
#include "MediaConduitErrors.h"
|
||||
|
||||
#include "ImageContainer.h"
|
||||
|
||||
#include "webrtc/call.h"
|
||||
#include "webrtc/config.h"
|
||||
#include "webrtc/common_types.h"
|
||||
namespace webrtc {
|
||||
class I420VideoFrame;
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
class VideoFrame;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Wrap the webrtc.org Call class adding mozilla add/ref support.
|
||||
class WebRtcCallWrapper : public RefCounted<WebRtcCallWrapper>
|
||||
{
|
||||
public:
|
||||
typedef webrtc::Call::Config Config;
|
||||
|
||||
static RefPtr<WebRtcCallWrapper> Create(const Config& config)
|
||||
{
|
||||
return new WebRtcCallWrapper(webrtc::Call::Create(config));
|
||||
}
|
||||
|
||||
webrtc::Call* Call() const
|
||||
{
|
||||
return mCall.get();
|
||||
}
|
||||
|
||||
virtual ~WebRtcCallWrapper()
|
||||
{
|
||||
if (mCall->voice_engine()) {
|
||||
webrtc::VoiceEngine* voice_engine = mCall->voice_engine();
|
||||
mCall.reset(nullptr); // Force it to release the voice engine reference
|
||||
// Delete() must be after all refs are released
|
||||
webrtc::VoiceEngine::Delete(voice_engine);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebRtcCallWrapper)
|
||||
|
||||
private:
|
||||
WebRtcCallWrapper() = delete;
|
||||
explicit WebRtcCallWrapper(webrtc::Call* aCall)
|
||||
: mCall(aCall) {}
|
||||
DISALLOW_COPY_AND_ASSIGN(WebRtcCallWrapper);
|
||||
UniquePtr<webrtc::Call> mCall;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract Interface for transporting RTP packets - audio/vidoeo
|
||||
* The consumers of this interface are responsible for passing in
|
||||
|
|
@ -40,7 +84,7 @@ public:
|
|||
* @param len : Length of the media packet
|
||||
* @result : NS_OK on success, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult SendRtpPacket(const void* data, int len) = 0;
|
||||
virtual nsresult SendRtpPacket(const uint8_t* data, size_t len) = 0;
|
||||
|
||||
/**
|
||||
* RTCP Transport Function to be implemented by concrete transport implementation
|
||||
|
|
@ -48,7 +92,7 @@ public:
|
|||
* @param len : Length of the RTCP packet
|
||||
* @result : NS_OK on success, NS_ERROR_FAILURE otherwise
|
||||
*/
|
||||
virtual nsresult SendRtcpPacket(const void* data, int len) = 0;
|
||||
virtual nsresult SendRtcpPacket(const uint8_t* data, size_t len) = 0;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportInterface)
|
||||
};
|
||||
|
||||
|
|
@ -193,9 +237,15 @@ public:
|
|||
*/
|
||||
virtual MediaConduitErrorCode SetReceiverTransport(RefPtr<TransportInterface> aTransport) = 0;
|
||||
|
||||
virtual bool SetLocalSSRC(unsigned int ssrc) = 0;
|
||||
virtual bool GetLocalSSRC(unsigned int* ssrc) = 0;
|
||||
/* Sets the local SSRCs
|
||||
* @return true iff the local ssrcs == aSSRCs upon return
|
||||
* Note: this is an ordered list and {a,b,c} != {b,a,c}
|
||||
*/
|
||||
virtual bool SetLocalSSRCs(const std::vector<unsigned int>& aSSRCs) = 0;
|
||||
virtual std::vector<unsigned int> GetLocalSSRCs() const = 0;
|
||||
|
||||
virtual bool GetRemoteSSRC(unsigned int* ssrc) = 0;
|
||||
virtual bool SetRemoteSSRC(unsigned int ssrc) = 0;
|
||||
virtual bool SetLocalCNAME(const char* cname) = 0;
|
||||
|
||||
/**
|
||||
|
|
@ -265,10 +315,12 @@ class VideoSessionConduit : public MediaSessionConduit
|
|||
public:
|
||||
/**
|
||||
* Factory function to create and initialize a Video Conduit Session
|
||||
* return: Concrete VideoSessionConduitObject or nullptr in the case
|
||||
* @param webrtc::Call instance shared by paired audio and video
|
||||
* media conduits
|
||||
* @result Concrete VideoSessionConduitObject or nullptr in the case
|
||||
* of failure
|
||||
*/
|
||||
static RefPtr<VideoSessionConduit> Create();
|
||||
static RefPtr<VideoSessionConduit> Create(RefPtr<WebRtcCallWrapper> aCall);
|
||||
|
||||
enum FrameRequestType
|
||||
{
|
||||
|
|
@ -287,15 +339,28 @@ public:
|
|||
|
||||
virtual Type type() const { return VIDEO; }
|
||||
|
||||
/**
|
||||
* Adds negotiated RTP extensions
|
||||
*/
|
||||
virtual void AddLocalRTPExtensions(const std::vector<webrtc::RtpExtension>& extensions) = 0;
|
||||
|
||||
/**
|
||||
* Returns the negotiated RTP extensions
|
||||
*/
|
||||
virtual std::vector<webrtc::RtpExtension> GetLocalRTPExtensions() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Function to attach Renderer end-point of the Media-Video conduit.
|
||||
* @param aRenderer : Reference to the concrete Video renderer implementation
|
||||
* Note: Multiple invocations of this API shall remove an existing renderer
|
||||
* and attaches the new to the Conduit.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachRenderer(RefPtr<VideoRenderer> aRenderer) = 0;
|
||||
virtual MediaConduitErrorCode AttachRenderer(RefPtr<mozilla::VideoRenderer> aRenderer) = 0;
|
||||
virtual void DetachRenderer() = 0;
|
||||
|
||||
virtual bool SetRemoteSSRC(unsigned int ssrc) = 0;
|
||||
|
||||
/**
|
||||
* Function to deliver a capture video frame for encoding and transport
|
||||
* @param video_frame: pointer to captured video-frame.
|
||||
|
|
@ -313,7 +378,7 @@ public:
|
|||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time) = 0;
|
||||
virtual MediaConduitErrorCode SendVideoFrame(webrtc::I420VideoFrame& frame) = 0;
|
||||
virtual MediaConduitErrorCode SendVideoFrame(webrtc::VideoFrame& frame) = 0;
|
||||
|
||||
virtual MediaConduitErrorCode ConfigureCodecMode(webrtc::VideoCodecMode) = 0;
|
||||
/**
|
||||
|
|
@ -335,31 +400,7 @@ public:
|
|||
*
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<VideoCodecConfig* >& recvCodecConfigList) = 0;
|
||||
|
||||
/**
|
||||
* Set an external encoder
|
||||
* @param encoder
|
||||
* @result: on success, we will use the specified encoder
|
||||
*/
|
||||
virtual MediaConduitErrorCode SetExternalSendCodec(VideoCodecConfig* config,
|
||||
VideoEncoder* encoder) = 0;
|
||||
|
||||
/**
|
||||
* Set an external decoder
|
||||
* @param decoder
|
||||
* @result: on success, we will use the specified decoder
|
||||
*/
|
||||
virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
|
||||
VideoDecoder* decoder) = 0;
|
||||
|
||||
/**
|
||||
* Function to enable the RTP Stream ID (RID) extension
|
||||
* @param enabled: enable extension
|
||||
* @param id: id to be used for this rtp header extension
|
||||
* NOTE: See VideoConduit for more information
|
||||
*/
|
||||
virtual MediaConduitErrorCode EnableRTPStreamIdExtension(bool enabled, uint8_t id) = 0;
|
||||
const std::vector<VideoCodecConfig* >& recvCodecConfigList) = 0;
|
||||
|
||||
/**
|
||||
* These methods allow unit tests to double-check that the
|
||||
|
|
@ -410,11 +451,13 @@ class AudioSessionConduit : public MediaSessionConduit
|
|||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Factory function to create and initialize an Audio Conduit Session
|
||||
* return: Concrete AudioSessionConduitObject or nullptr in the case
|
||||
* of failure
|
||||
*/
|
||||
/**
|
||||
* Factory function to create and initialize an Audio Conduit Session
|
||||
* @param webrtc::Call instance shared by paired audio and video
|
||||
* media conduits
|
||||
* @result Concrete AudioSessionConduitObject or nullptr in the case
|
||||
* of failure
|
||||
*/
|
||||
static RefPtr<AudioSessionConduit> Create();
|
||||
|
||||
virtual ~AudioSessionConduit() {}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
VideoEncoder*
|
||||
WebrtcVideoEncoder*
|
||||
OMXVideoCodec::CreateEncoder(CodecType aCodecType)
|
||||
{
|
||||
if (aCodecType == CODEC_H264) {
|
||||
|
|
@ -19,7 +19,7 @@ OMXVideoCodec::CreateEncoder(CodecType aCodecType)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
VideoDecoder*
|
||||
WebrtcVideoDecoder*
|
||||
OMXVideoCodec::CreateDecoder(CodecType aCodecType) {
|
||||
if (aCodecType == CODEC_H264) {
|
||||
return new WebrtcOMXH264VideoDecoder();
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ class OMXVideoCodec {
|
|||
* Create encoder object for codec type |aCodecType|. Return |nullptr| when
|
||||
* failed.
|
||||
*/
|
||||
static VideoEncoder* CreateEncoder(CodecType aCodecType);
|
||||
static WebrtcVideoEncoder* CreateEncoder(CodecType aCodecType);
|
||||
|
||||
/**
|
||||
* Create decoder object for codec type |aCodecType|. Return |nullptr| when
|
||||
* failed.
|
||||
*/
|
||||
static VideoDecoder* CreateDecoder(CodecType aCodecType);
|
||||
static WebrtcVideoDecoder* CreateDecoder(CodecType aCodecType);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,59 +5,54 @@
|
|||
#ifndef VIDEO_SESSION_H_
|
||||
#define VIDEO_SESSION_H_
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include "LoadManager.h"
|
||||
#include "LoadManagerFactory.h"
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "MediaEngineWrapper.h"
|
||||
#include "CodecStatistics.h"
|
||||
#include "LoadManagerFactory.h"
|
||||
#include "LoadManager.h"
|
||||
#include "RunningStat.h"
|
||||
#include "runnable_utils.h"
|
||||
|
||||
// conflicts with #include of scoped_ptr.h
|
||||
#undef FF
|
||||
// Video Engine Includes
|
||||
#include "webrtc/call.h"
|
||||
#include "webrtc/common_types.h"
|
||||
#ifdef FF
|
||||
#undef FF // Avoid name collision between scoped_ptr.h and nsCRTGlue.h.
|
||||
#endif
|
||||
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
|
||||
#include "webrtc/video_engine/include/vie_base.h"
|
||||
#include "webrtc/video_engine/include/vie_capture.h"
|
||||
#include "webrtc/video_engine/include/vie_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_external_codec.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
#include "webrtc/video_engine/include/vie_network.h"
|
||||
#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
|
||||
|
||||
#include "webrtc/video_decoder.h"
|
||||
#include "webrtc/video_encoder.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
/** This file hosts several structures identifying different aspects
|
||||
* of a RTP Session.
|
||||
*/
|
||||
|
||||
using webrtc::ViEBase;
|
||||
using webrtc::ViENetwork;
|
||||
using webrtc::ViECodec;
|
||||
using webrtc::ViECapture;
|
||||
using webrtc::ViERender;
|
||||
using webrtc::ViEExternalCapture;
|
||||
using webrtc::ViEExternalCodec;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
const int kVideoMtu = 1200;
|
||||
const int kQpMax = 56;
|
||||
|
||||
class WebrtcAudioConduit;
|
||||
class nsThread;
|
||||
|
||||
// Interface of external video encoder for WebRTC.
|
||||
class WebrtcVideoEncoder:public VideoEncoder
|
||||
,public webrtc::VideoEncoder
|
||||
{};
|
||||
class WebrtcVideoEncoder : public VideoEncoder
|
||||
, public webrtc::VideoEncoder
|
||||
{
|
||||
};
|
||||
|
||||
// Interface of external video decoder for WebRTC.
|
||||
class WebrtcVideoDecoder:public VideoDecoder
|
||||
,public webrtc::VideoDecoder
|
||||
{};
|
||||
class WebrtcVideoDecoder : public VideoDecoder
|
||||
, public webrtc::VideoDecoder
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Concrete class for Video session. Hooks up
|
||||
|
|
@ -65,12 +60,30 @@ class WebrtcVideoDecoder:public VideoDecoder
|
|||
*/
|
||||
class WebrtcVideoConduit : public VideoSessionConduit
|
||||
, public webrtc::Transport
|
||||
, public webrtc::ExternalRenderer
|
||||
, public webrtc::VideoRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
/* Default minimum bitrate for video streams. */
|
||||
static const uint32_t kDefaultMinBitrate_bps;
|
||||
/* Default start a.k.a. target bitrate for video streams. */
|
||||
static const uint32_t kDefaultStartBitrate_bps;
|
||||
/* Default maximum bitrate for video streams. */
|
||||
static const uint32_t kDefaultMaxBitrate_bps;
|
||||
|
||||
//VoiceEngine defined constant for Payload Name Size.
|
||||
static const unsigned int CODEC_PLNAME_SIZE;
|
||||
|
||||
/**
|
||||
* Add rtp extensions to the the VideoSendStream
|
||||
* Note: upon a name collision the old extension is removed and the new one
|
||||
* takes its place.
|
||||
* TODO(@@NG) promote this the MediaConduitInterface when the VoE rework
|
||||
* hits Webrtc.org.
|
||||
*/
|
||||
void AddLocalRTPExtensions(const std::vector<webrtc::RtpExtension>& extensions) override;
|
||||
std::vector<webrtc::RtpExtension> GetLocalRTPExtensions() const override;
|
||||
|
||||
/**
|
||||
* Set up A/V sync between this (incoming) VideoConduit and an audio conduit.
|
||||
*/
|
||||
|
|
@ -78,24 +91,24 @@ public:
|
|||
|
||||
/**
|
||||
* Function to attach Renderer end-point for the Media-Video conduit.
|
||||
* @param aRenderer : Reference to the concrete Video renderer implementation
|
||||
* @param aRenderer : Reference to the concrete mozilla Video renderer implementation
|
||||
* Note: Multiple invocations of this API shall remove an existing renderer
|
||||
* and attaches the new to the Conduit.
|
||||
*/
|
||||
virtual MediaConduitErrorCode AttachRenderer(RefPtr<VideoRenderer> aVideoRenderer) override;
|
||||
virtual MediaConduitErrorCode AttachRenderer(RefPtr<mozilla::VideoRenderer> aVideoRenderer) override;
|
||||
virtual void DetachRenderer() override;
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTP Frames to the VideoEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTPPacket(const void *data, int len) override;
|
||||
virtual MediaConduitErrorCode ReceivedRTPPacket(const void* data, int len) override;
|
||||
|
||||
/**
|
||||
* APIs used by the registered external transport to this Conduit to
|
||||
* feed in received RTP Frames to the VideoEngine for decoding
|
||||
*/
|
||||
virtual MediaConduitErrorCode ReceivedRTCPPacket(const void *data, int len) override;
|
||||
virtual MediaConduitErrorCode ReceivedRTCPPacket(const void* data, int len) override;
|
||||
|
||||
virtual MediaConduitErrorCode StopTransmitting() override;
|
||||
virtual MediaConduitErrorCode StartTransmitting() override;
|
||||
|
|
@ -127,7 +140,7 @@ public:
|
|||
* transmission sub-system on the engine.
|
||||
*/
|
||||
virtual MediaConduitErrorCode ConfigureRecvMediaCodecs(
|
||||
const std::vector<VideoCodecConfig* >& codecConfigList) override;
|
||||
const std::vector<VideoCodecConfig* >& codecConfigList) override;
|
||||
|
||||
/**
|
||||
* Register Transport for this Conduit. RTP and RTCP frames from the VideoEngine
|
||||
|
|
@ -142,15 +155,13 @@ public:
|
|||
* @param width, height: dimensions of the frame
|
||||
* @param cap: user-enforced max bitrate, or 0
|
||||
* @param aLastFramerateTenths: holds the current input framerate
|
||||
* @param out_start, out_min, out_max: bitrate results
|
||||
* @param aVideoStream stream to apply bitrates to
|
||||
*/
|
||||
void SelectBitrates(unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned int cap,
|
||||
mozilla::Atomic<int32_t, mozilla::Relaxed>& aLastFramerateTenths,
|
||||
unsigned int& out_min,
|
||||
unsigned int& out_start,
|
||||
unsigned int& out_max);
|
||||
int cap,
|
||||
int32_t aLastFramerateTenths,
|
||||
webrtc::VideoStream& aVideoStream);
|
||||
|
||||
/**
|
||||
* Function to select and change the encoding resolution based on incoming frame size
|
||||
|
|
@ -160,7 +171,7 @@ public:
|
|||
*/
|
||||
bool SelectSendResolution(unsigned short width,
|
||||
unsigned short height,
|
||||
webrtc::I420VideoFrame *frame);
|
||||
webrtc::VideoFrame* frame);
|
||||
|
||||
/**
|
||||
* Function to reconfigure the current send codec for a different
|
||||
|
|
@ -170,7 +181,7 @@ public:
|
|||
*/
|
||||
nsresult ReconfigureSendCodec(unsigned short width,
|
||||
unsigned short height,
|
||||
webrtc::I420VideoFrame *frame);
|
||||
webrtc::VideoFrame* frame);
|
||||
|
||||
/**
|
||||
* Function to select and change the encoding frame rate based on incoming frame rate
|
||||
|
|
@ -178,7 +189,10 @@ public:
|
|||
* @param current framerate
|
||||
* @result new framerate
|
||||
*/
|
||||
unsigned int SelectSendFrameRate(unsigned int framerate) const;
|
||||
unsigned int SelectSendFrameRate(const VideoCodecConfig* codecConfig,
|
||||
unsigned int old_framerate,
|
||||
unsigned short sending_width,
|
||||
unsigned short sending_height) const;
|
||||
|
||||
/**
|
||||
* Function to deliver a capture video frame for encoding and transport
|
||||
|
|
@ -192,66 +206,44 @@ public:
|
|||
* This ensures the inserted video-frames can be transmitted by the conduit
|
||||
*/
|
||||
virtual MediaConduitErrorCode SendVideoFrame(unsigned char* video_frame,
|
||||
unsigned int video_frame_length,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time) override;
|
||||
virtual MediaConduitErrorCode SendVideoFrame(webrtc::I420VideoFrame& frame) override;
|
||||
unsigned int video_frame_length,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
VideoType video_type,
|
||||
uint64_t capture_time) override;
|
||||
virtual MediaConduitErrorCode SendVideoFrame(webrtc::VideoFrame& frame) override;
|
||||
|
||||
/**
|
||||
* Set an external encoder object |encoder| to the payload type |pltype|
|
||||
* for sender side codec.
|
||||
*/
|
||||
virtual MediaConduitErrorCode SetExternalSendCodec(VideoCodecConfig* config,
|
||||
VideoEncoder* encoder) override;
|
||||
|
||||
/**
|
||||
* Set an external decoder object |decoder| to the payload type |pltype|
|
||||
* for receiver side codec.
|
||||
*/
|
||||
virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
|
||||
VideoDecoder* decoder) override;
|
||||
|
||||
/**
|
||||
* Enables use of Rtp Stream Id, and sets the extension ID.
|
||||
*/
|
||||
virtual MediaConduitErrorCode EnableRTPStreamIdExtension(bool enabled, uint8_t id) override;
|
||||
|
||||
/**
|
||||
/**
|
||||
* webrtc::Transport method implementation
|
||||
* ---------------------------------------
|
||||
* Webrtc transport implementation to send and receive RTP packet.
|
||||
* VideoConduit registers itself as ExternalTransport to the VideoEngine
|
||||
* VideoConduit registers itself as ExternalTransport to the VideoStream
|
||||
*/
|
||||
virtual int SendPacket(int channel, const void *data, size_t len) override;
|
||||
virtual bool SendRtp(const uint8_t* packet, size_t length,
|
||||
const webrtc::PacketOptions& options) override;
|
||||
|
||||
/**
|
||||
* webrtc::Transport method implementation
|
||||
* ---------------------------------------
|
||||
* Webrtc transport implementation to send and receive RTCP packet.
|
||||
* VideoConduit registers itself as ExternalTransport to the VideoEngine
|
||||
*/
|
||||
virtual int SendRTCPPacket(int channel, const void *data, size_t len) override;
|
||||
virtual bool SendRtcp(const uint8_t* packet, size_t length) override;
|
||||
|
||||
|
||||
/**
|
||||
* Webrtc External Renderer Implementation APIs.
|
||||
* Raw I420 Frames are delivred to the VideoConduit by the VideoEngine
|
||||
* webrtc::VideoRenderer implementation
|
||||
* ------------------------------------
|
||||
* webrtc::VideoFrames are delivered to the VideoConduit by the VideoReceiveStream.
|
||||
*/
|
||||
virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int) override;
|
||||
|
||||
virtual int DeliverFrame(unsigned char*, size_t, uint32_t , int64_t,
|
||||
int64_t, void *handle) override;
|
||||
|
||||
virtual int DeliverFrame(unsigned char*, size_t, uint32_t, uint32_t, uint32_t , int64_t,
|
||||
int64_t, void *handle);
|
||||
|
||||
virtual int DeliverI420Frame(const webrtc::I420VideoFrame& webrtc_frame) override;
|
||||
virtual void RenderFrame(const webrtc::VideoFrame& video_frame,
|
||||
int time_to_render_ms) override;
|
||||
|
||||
/**
|
||||
* Does DeliverFrame() support a null buffer and non-null handle
|
||||
* (video texture)?
|
||||
* B2G support it (when using HW video decoder with graphic buffer output).
|
||||
* XXX Investigate! Especially for Android
|
||||
* webrtc::VideoRenderer implementation
|
||||
* ------------------------------------
|
||||
*/
|
||||
virtual bool IsTextureSupported() override {
|
||||
virtual bool IsTextureSupported() const override {
|
||||
#ifdef WEBRTC_GONK
|
||||
return true;
|
||||
#else
|
||||
|
|
@ -259,6 +251,14 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* webrtc::VideoRenderer implementation
|
||||
* ------------------------------------
|
||||
*/
|
||||
virtual bool SmoothsRenderedFrames() const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual uint64_t CodecPluginID() override;
|
||||
|
||||
unsigned short SendingWidth() override {
|
||||
|
|
@ -285,17 +285,17 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
WebrtcVideoConduit();
|
||||
explicit WebrtcVideoConduit(RefPtr<WebRtcCallWrapper> aCall);
|
||||
virtual ~WebrtcVideoConduit();
|
||||
|
||||
MediaConduitErrorCode InitMain();
|
||||
virtual MediaConduitErrorCode Init();
|
||||
|
||||
int GetChannel() { return mChannel; }
|
||||
webrtc::VideoEngine* GetVideoEngine() { return mVideoEngine; }
|
||||
bool GetLocalSSRC(unsigned int* ssrc) override;
|
||||
bool SetLocalSSRC(unsigned int ssrc) override;
|
||||
std::vector<unsigned int> GetLocalSSRCs() const override;
|
||||
bool SetLocalSSRCs(const std::vector<unsigned int> & ssrcs) override;
|
||||
|
||||
bool GetRemoteSSRC(unsigned int* ssrc) override;
|
||||
bool SetRemoteSSRC(unsigned int ssrc) override;
|
||||
bool SetLocalCNAME(const char* cname) override;
|
||||
bool GetVideoEncoderStats(double* framerateMean,
|
||||
double* framerateStdDev,
|
||||
|
|
@ -325,25 +325,91 @@ public:
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(WebrtcVideoConduit);
|
||||
|
||||
static inline bool OnThread(nsIEventTarget *thread)
|
||||
{
|
||||
bool on;
|
||||
nsresult rv;
|
||||
rv = thread->IsOnCurrentThread(&on);
|
||||
/** Shared statistics for receive and transmit video streams
|
||||
*/
|
||||
class StreamStatistics {
|
||||
public:
|
||||
void Update(const double aFrameRate, const double aBitrate);
|
||||
/**
|
||||
* Returns gathered stream statistics
|
||||
* @param aOutFrMean: mean framerate
|
||||
* @param aOutFrStdDev: standard deviation of framerate
|
||||
* @param aOutBrMean: mean bitrate
|
||||
* @param aOutBrStdDev: standard deviation of bitrate
|
||||
*/
|
||||
bool GetVideoStreamStats(double& aOutFrMean,
|
||||
double& aOutFrStdDev,
|
||||
double& aOutBrMean,
|
||||
double& aOutBrStdDev) const;
|
||||
private:
|
||||
RunningStat mFrameRate;
|
||||
RunningStat mBitrate;
|
||||
};
|
||||
|
||||
// If the target thread has already shut down, we don't want to assert.
|
||||
if (rv != NS_ERROR_NOT_INITIALIZED) {
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
/**
|
||||
* Statistics for sending streams
|
||||
*/
|
||||
class SendStreamStatistics : public StreamStatistics {
|
||||
public:
|
||||
/**
|
||||
* Returns the calculate number of dropped frames
|
||||
* @param aOutDroppedFrames: the number of dropped frames
|
||||
*/
|
||||
void DroppedFrames(uint32_t& aOutDroppedFrames) const;
|
||||
void Update(const webrtc::VideoSendStream::Stats& aStats);
|
||||
/**
|
||||
* Call once for every frame delivered for encoding
|
||||
*/
|
||||
void SentFrame() {
|
||||
++mSentFrames;
|
||||
}
|
||||
private:
|
||||
uint32_t mDroppedFrames = 0;
|
||||
mozilla::Atomic<int32_t> mSentFrames;
|
||||
};
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return false;
|
||||
}
|
||||
return on;
|
||||
}
|
||||
|
||||
//Local database of currently applied receive codecs
|
||||
typedef std::vector<VideoCodecConfig* > RecvCodecList;
|
||||
/** Statistics for receiving streams
|
||||
*/
|
||||
class ReceiveStreamStatistics : public StreamStatistics {
|
||||
public:
|
||||
/**
|
||||
* Returns the number of discarded packets
|
||||
* @param aOutDiscPackets: number of discarded packets
|
||||
*/
|
||||
void DiscardedPackets(uint32_t& aOutDiscPackets) const;
|
||||
void Update(const webrtc::VideoReceiveStream::Stats& aStats);
|
||||
private:
|
||||
uint32_t mDiscardedPackets = 0;
|
||||
};
|
||||
/*
|
||||
* Stores encoder configuration information and produces
|
||||
* a VideoEncoderConfig from it.
|
||||
*/
|
||||
class VideoEncoderConfigBuilder {
|
||||
public:
|
||||
/**
|
||||
* Stores extended data for Simulcast Streams
|
||||
*/
|
||||
class SimulcastStreamConfig {
|
||||
public:
|
||||
int jsMaxBitrate; // user-controlled max bitrate
|
||||
double jsScaleDownBy=1.0; // user-controlled downscale
|
||||
};
|
||||
void SetEncoderSpecificSettings(void* aSettingsObj);
|
||||
void SetMinTransmitBitrateBps(int aXmitMinBps);
|
||||
void SetContentType(webrtc::VideoEncoderConfig::ContentType aContentType);
|
||||
void SetResolutionDivisor(unsigned char aDivisor);
|
||||
void AddStream(webrtc::VideoStream aStream);
|
||||
void AddStream(webrtc::VideoStream aStream,const SimulcastStreamConfig& aSimulcastConfig);
|
||||
size_t StreamCount();
|
||||
void ClearStreams();
|
||||
void ForEachStream(
|
||||
const std::function<void(webrtc::VideoStream&, SimulcastStreamConfig&, const size_t index)> && f);
|
||||
webrtc::VideoEncoderConfig GenerateConfig();
|
||||
private:
|
||||
webrtc::VideoEncoderConfig mConfig;
|
||||
std::vector<SimulcastStreamConfig> mSimulcastStreams;
|
||||
};
|
||||
|
||||
//Function to convert between WebRTC and Conduit codec structures
|
||||
void CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
|
||||
|
|
@ -355,36 +421,37 @@ private:
|
|||
//Utility function to dump recv codec database
|
||||
void DumpCodecDB() const;
|
||||
|
||||
bool CodecsDifferent(const nsTArray<UniquePtr<VideoCodecConfig>>& a,
|
||||
const nsTArray<UniquePtr<VideoCodecConfig>>& b);
|
||||
|
||||
// Video Latency Test averaging filter
|
||||
void VideoLatencyUpdate(uint64_t new_sample);
|
||||
|
||||
// Utility function to determine RED and ULPFEC payload types
|
||||
bool DetermineREDAndULPFECPayloadTypes(uint8_t &payload_type_red, uint8_t &payload_type_ulpfec);
|
||||
MediaConduitErrorCode CreateSendStream();
|
||||
void DeleteSendStream();
|
||||
MediaConduitErrorCode CreateRecvStream();
|
||||
void DeleteRecvStream();
|
||||
|
||||
webrtc::VideoDecoder* CreateDecoder(webrtc::VideoDecoder::DecoderType aType);
|
||||
webrtc::VideoEncoder* CreateEncoder(webrtc::VideoEncoder::EncoderType aType,
|
||||
bool enable_simulcast);
|
||||
|
||||
MediaConduitErrorCode DeliverPacket(const void *data, int len);
|
||||
|
||||
webrtc::VideoEngine* mVideoEngine;
|
||||
mozilla::ReentrantMonitor mTransportMonitor;
|
||||
RefPtr<TransportInterface> mTransmitterTransport;
|
||||
RefPtr<TransportInterface> mReceiverTransport;
|
||||
RefPtr<VideoRenderer> mRenderer;
|
||||
|
||||
ScopedCustomReleasePtr<webrtc::ViEBase> mPtrViEBase;
|
||||
ScopedCustomReleasePtr<webrtc::ViECapture> mPtrViECapture;
|
||||
ScopedCustomReleasePtr<webrtc::ViECodec> mPtrViECodec;
|
||||
ScopedCustomReleasePtr<webrtc::ViENetwork> mPtrViENetwork;
|
||||
ScopedCustomReleasePtr<webrtc::ViERender> mPtrViERender;
|
||||
ScopedCustomReleasePtr<webrtc::ViERTP_RTCP> mPtrRTP;
|
||||
ScopedCustomReleasePtr<webrtc::ViEExternalCodec> mPtrExtCodec;
|
||||
|
||||
webrtc::ViEExternalCapture* mPtrExtCapture;
|
||||
RefPtr<mozilla::VideoRenderer> mRenderer;
|
||||
|
||||
// Engine state we are concerned with.
|
||||
mozilla::Atomic<bool> mEngineTransmitting; //If true ==> Transmit Sub-system is up and running
|
||||
mozilla::Atomic<bool> mEngineReceiving; // if true ==> Receive Sus-sysmtem up and running
|
||||
|
||||
int mChannel; // Video Channel for this conduit
|
||||
int mCapId; // Capturer for this conduit
|
||||
//Local database of currently applied receive codecs
|
||||
nsTArray<UniquePtr<VideoCodecConfig>> mRecvCodecList;
|
||||
|
||||
Mutex mCodecMutex; // protects mCurrSendCodecConfig
|
||||
Mutex mCodecMutex; // protects mCurrSendCodecConfig, mVideoSend/RecvStreamStats
|
||||
nsAutoPtr<VideoCodecConfig> mCurSendCodecConfig;
|
||||
bool mInReconfig;
|
||||
|
||||
|
|
@ -400,10 +467,11 @@ private:
|
|||
unsigned short mNumReceivingStreams;
|
||||
bool mVideoLatencyTestEnable;
|
||||
uint64_t mVideoLatencyAvg;
|
||||
uint32_t mMinBitrate;
|
||||
uint32_t mStartBitrate;
|
||||
uint32_t mMaxBitrate;
|
||||
uint32_t mMinBitrateEstimate;
|
||||
int mMinBitrate;
|
||||
int mStartBitrate;
|
||||
int mPrefMaxBitrate;
|
||||
int mMinBitrateEstimate;
|
||||
int mNegotiatedMaxBitrate;
|
||||
|
||||
bool mRtpStreamIdEnabled;
|
||||
uint8_t mRtpStreamIdExtId;
|
||||
|
|
@ -414,16 +482,33 @@ private:
|
|||
|
||||
RefPtr<WebrtcAudioConduit> mSyncedTo;
|
||||
|
||||
nsAutoPtr<VideoCodecConfig> mExternalSendCodec;
|
||||
nsAutoPtr<VideoCodecConfig> mExternalRecvCodec;
|
||||
nsAutoPtr<VideoEncoder> mExternalSendCodecHandle;
|
||||
nsAutoPtr<VideoDecoder> mExternalRecvCodecHandle;
|
||||
|
||||
// statistics object for video codec;
|
||||
nsAutoPtr<VideoCodecStatistics> mVideoCodecStat;
|
||||
|
||||
nsAutoPtr<LoadManager> mLoadManager;
|
||||
webrtc::VideoCodecMode mCodecMode;
|
||||
|
||||
// WEBRTC.ORG Call API
|
||||
RefPtr<WebRtcCallWrapper> mCall;
|
||||
|
||||
webrtc::VideoSendStream* mSendStream;
|
||||
// Must call webrtc::Call::DestroyVideoSendStream to delete
|
||||
webrtc::VideoSendStream::Config mSendStreamConfig;
|
||||
VideoEncoderConfigBuilder mEncoderConfig;
|
||||
webrtc::VideoCodecH264 mEncoderSpecificH264;
|
||||
|
||||
webrtc::VideoReceiveStream* mRecvStream;
|
||||
// Must call webrtc::Call::DestroyVideoReceiveStream to delete
|
||||
webrtc::VideoReceiveStream::Config mRecvStreamConfig;
|
||||
|
||||
// The lifetime of these codecs are maintained by the VideoConduit instance.
|
||||
// They are passed to the webrtc::VideoSendStream or VideoReceiveStream,
|
||||
// on construction.
|
||||
nsAutoPtr<webrtc::VideoEncoder> mEncoder; // only one encoder for now
|
||||
std::vector<std::unique_ptr<webrtc::VideoDecoder>> mDecoders;
|
||||
WebrtcVideoEncoder* mSendCodecPlugin;
|
||||
WebrtcVideoDecoder* mRecvCodecPlugin;
|
||||
|
||||
nsCOMPtr<nsITimer> mVideoStatsTimer;
|
||||
SendStreamStatistics mSendStreamStats;
|
||||
ReceiveStreamStatistics mRecvStreamStats;
|
||||
};
|
||||
} // end namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
#include "gmp-video-frame-i420.h"
|
||||
#include "gmp-video-frame-encoded.h"
|
||||
|
||||
#include "webrtc/video_engine/include/vie_external_codec.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#ifdef LOG
|
||||
|
|
@ -105,28 +103,22 @@ WebrtcGmpVideoEncoder::~WebrtcGmpVideoEncoder()
|
|||
}
|
||||
|
||||
static int
|
||||
WebrtcFrameTypeToGmpFrameType(webrtc::VideoFrameType aIn,
|
||||
WebrtcFrameTypeToGmpFrameType(webrtc::FrameType aIn,
|
||||
GMPVideoFrameType *aOut)
|
||||
{
|
||||
MOZ_ASSERT(aOut);
|
||||
switch(aIn) {
|
||||
case webrtc::kKeyFrame:
|
||||
case webrtc::kVideoFrameKey:
|
||||
*aOut = kGMPKeyFrame;
|
||||
break;
|
||||
case webrtc::kDeltaFrame:
|
||||
case webrtc::kVideoFrameDelta:
|
||||
*aOut = kGMPDeltaFrame;
|
||||
break;
|
||||
case webrtc::kGoldenFrame:
|
||||
*aOut = kGMPGoldenFrame;
|
||||
break;
|
||||
case webrtc::kAltRefFrame:
|
||||
*aOut = kGMPAltRefFrame;
|
||||
break;
|
||||
case webrtc::kSkipFrame:
|
||||
case webrtc::kEmptyFrame:
|
||||
*aOut = kGMPSkipFrame;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected VideoFrameType");
|
||||
MOZ_CRASH("Unexpected webrtc::FrameType");
|
||||
}
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
|
|
@ -134,24 +126,18 @@ WebrtcFrameTypeToGmpFrameType(webrtc::VideoFrameType aIn,
|
|||
|
||||
static int
|
||||
GmpFrameTypeToWebrtcFrameType(GMPVideoFrameType aIn,
|
||||
webrtc::VideoFrameType *aOut)
|
||||
webrtc::FrameType *aOut)
|
||||
{
|
||||
MOZ_ASSERT(aOut);
|
||||
switch(aIn) {
|
||||
case kGMPKeyFrame:
|
||||
*aOut = webrtc::kKeyFrame;
|
||||
*aOut = webrtc::kVideoFrameKey;
|
||||
break;
|
||||
case kGMPDeltaFrame:
|
||||
*aOut = webrtc::kDeltaFrame;
|
||||
break;
|
||||
case kGMPGoldenFrame:
|
||||
*aOut = webrtc::kGoldenFrame;
|
||||
break;
|
||||
case kGMPAltRefFrame:
|
||||
*aOut = webrtc::kAltRefFrame;
|
||||
*aOut = webrtc::kVideoFrameDelta;
|
||||
break;
|
||||
case kGMPSkipFrame:
|
||||
*aOut = webrtc::kSkipFrame;
|
||||
*aOut = webrtc::kEmptyFrame;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected GMPVideoFrameType");
|
||||
|
|
@ -327,9 +313,9 @@ WebrtcGmpVideoEncoder::InitEncoderForSize(unsigned short aWidth,
|
|||
|
||||
|
||||
int32_t
|
||||
WebrtcGmpVideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
|
||||
WebrtcGmpVideoEncoder::Encode(const webrtc::VideoFrame& aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes)
|
||||
{
|
||||
MOZ_ASSERT(aInputImage.width() >= 0 && aInputImage.height() >= 0);
|
||||
// Would be really nice to avoid this sync dispatch, but it would require a
|
||||
|
|
@ -375,9 +361,9 @@ WebrtcGmpVideoEncoder::RegetEncoderForResolutionChange(
|
|||
}
|
||||
|
||||
int32_t
|
||||
WebrtcGmpVideoEncoder::Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
||||
WebrtcGmpVideoEncoder::Encode_g(const webrtc::VideoFrame* aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes)
|
||||
{
|
||||
if (!mGMP) {
|
||||
// destroyed via Terminate(), failed to init, or just not initted yet
|
||||
|
|
@ -540,7 +526,7 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
|
|||
{
|
||||
MutexAutoLock lock(mCallbackMutex);
|
||||
if (mCallback) {
|
||||
webrtc::VideoFrameType ft;
|
||||
webrtc::FrameType ft;
|
||||
GmpFrameTypeToWebrtcFrameType(aEncodedFrame->FrameType(), &ft);
|
||||
uint32_t timestamp = (aEncodedFrame->TimeStamp() * 90ll + 999)/1000;
|
||||
|
||||
|
|
@ -941,7 +927,7 @@ WebrtcGmpVideoDecoder::Decoded(GMPVideoi420Frame* aDecodedFrame)
|
|||
{
|
||||
MutexAutoLock lock(mCallbackMutex);
|
||||
if (mCallback) {
|
||||
webrtc::I420VideoFrame image;
|
||||
webrtc::VideoFrame image;
|
||||
int ret = image.CreateFrame(aDecodedFrame->Buffer(kGMPYPlane),
|
||||
aDecodedFrame->Buffer(kGMPUPlane),
|
||||
aDecodedFrame->Buffer(kGMPVPlane),
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
#include "MediaConduitInterface.h"
|
||||
#include "AudioConduit.h"
|
||||
#include "VideoConduit.h"
|
||||
#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
|
||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||
|
||||
#include "gmp-video-host.h"
|
||||
#include "GMPVideoDecoderProxy.h"
|
||||
|
|
@ -142,9 +142,9 @@ public:
|
|||
int32_t aNumberOfCores,
|
||||
uint32_t aMaxPayloadSize);
|
||||
|
||||
virtual int32_t Encode(const webrtc::I420VideoFrame& aInputImage,
|
||||
virtual int32_t Encode(const webrtc::VideoFrame& aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes);
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes);
|
||||
|
||||
virtual int32_t RegisterEncodeCompleteCallback(
|
||||
webrtc::EncodedImageCallback* aCallback);
|
||||
|
|
@ -220,9 +220,9 @@ private:
|
|||
uint32_t mMaxPayloadSize;
|
||||
};
|
||||
|
||||
int32_t Encode_g(const webrtc::I420VideoFrame* aInputImage,
|
||||
int32_t Encode_g(const webrtc::VideoFrame* aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes);
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes);
|
||||
void RegetEncoderForResolutionChange(
|
||||
uint32_t aWidth,
|
||||
uint32_t aHeight,
|
||||
|
|
@ -316,9 +316,9 @@ class WebrtcVideoEncoderProxy : public WebrtcVideoEncoder
|
|||
}
|
||||
|
||||
int32_t Encode(
|
||||
const webrtc::I420VideoFrame& aInputImage,
|
||||
const webrtc::VideoFrame& aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes) override
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes) override
|
||||
{
|
||||
return mEncoderImpl->Encode(aInputImage,
|
||||
aCodecSpecificInfo,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include "libyuv/convert.h"
|
||||
#include "libyuv/row.h"
|
||||
|
||||
#include "webrtc/modules/video_coding/include/video_error_codes.h"
|
||||
|
||||
#include <webrtc/common_video/libyuv/include/webrtc_libyuv.h>
|
||||
|
||||
using namespace mozilla;
|
||||
|
|
@ -266,7 +268,7 @@ public:
|
|||
void GenerateVideoFrame(
|
||||
size_t width, size_t height, uint32_t timeStamp,
|
||||
void* decoded,
|
||||
webrtc::I420VideoFrame* videoFrame, int color_format) {
|
||||
webrtc::VideoFrame* videoFrame, int color_format) {
|
||||
|
||||
CSFLogDebug(logTag, "%s ", __FUNCTION__);
|
||||
|
||||
|
|
@ -532,7 +534,7 @@ class OutputDrain : public MediaCodecOutputDrain
|
|||
MediaCodec::GlobalRef mCoder;
|
||||
webrtc::EncodedImageCallback* mEncoderCallback;
|
||||
webrtc::DecodedImageCallback* mDecoderCallback;
|
||||
webrtc::I420VideoFrame mVideoFrame;
|
||||
webrtc::VideoFrame mVideoFrame;
|
||||
|
||||
jobjectArray mInputBuffers;
|
||||
jobjectArray mOutputBuffers;
|
||||
|
|
@ -546,7 +548,7 @@ class OutputDrain : public MediaCodecOutputDrain
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebrtcAndroidMediaCodec)
|
||||
};
|
||||
|
||||
static bool I420toNV12(uint8_t* dstY, uint16_t* dstUV, const webrtc::I420VideoFrame& inputImage) {
|
||||
static bool I420toNV12(uint8_t* dstY, uint16_t* dstUV, const webrtc::VideoFrame& inputImage) {
|
||||
uint8_t* buffer = dstY;
|
||||
uint8_t* dst_y = buffer;
|
||||
int dst_stride_y = inputImage.stride(webrtc::kYPlane);
|
||||
|
|
@ -630,9 +632,9 @@ int32_t WebrtcMediaCodecVP8VideoEncoder::InitEncode(
|
|||
}
|
||||
|
||||
int32_t WebrtcMediaCodecVP8VideoEncoder::Encode(
|
||||
const webrtc::I420VideoFrame& inputImage,
|
||||
const webrtc::VideoFrame& inputImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* frame_types) {
|
||||
const std::vector<webrtc::FrameType>* frame_types) {
|
||||
CSFLogDebug(logTag, "%s, w = %d, h = %d", __FUNCTION__, inputImage.width(), inputImage.height());
|
||||
|
||||
if (!mMediaCodecEncoder) {
|
||||
|
|
@ -765,9 +767,9 @@ int32_t WebrtcMediaCodecVP8VideoEncoder::Encode(
|
|||
void* directBuffer = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer)) + offset;
|
||||
|
||||
if (flags == MediaCodec::BUFFER_FLAG_SYNC_FRAME) {
|
||||
mEncodedImage._frameType = webrtc::kKeyFrame;
|
||||
mEncodedImage._frameType = webrtc::kVideoFrameKey;
|
||||
} else {
|
||||
mEncodedImage._frameType = webrtc::kDeltaFrame;
|
||||
mEncodedImage._frameType = webrtc::kVideoFrameDelta;
|
||||
}
|
||||
mEncodedImage._completeFrame = true;
|
||||
|
||||
|
|
@ -910,7 +912,7 @@ int32_t WebrtcMediaCodecVP8VideoDecoder::Decode(
|
|||
return WEBRTC_VIDEO_CODEC_ERROR;
|
||||
}
|
||||
|
||||
if (inputImage._frameType == webrtc::kKeyFrame) {
|
||||
if (inputImage._frameType == webrtc::kVideoFrameKey) {
|
||||
CSFLogDebug(logTag, "%s, inputImage is Golden frame",
|
||||
__FUNCTION__);
|
||||
mFrameWidth = inputImage._encodedWidth;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef WebrtcMediaCodecVP8VideoCodec_h__
|
||||
#define WebrtcMediaCodecVP8VideoCodec_h__
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
|
@ -13,6 +15,8 @@
|
|||
#include "AudioConduit.h"
|
||||
#include "VideoConduit.h"
|
||||
|
||||
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
struct EncodedFrame {
|
||||
|
|
@ -37,9 +41,9 @@ public:
|
|||
int32_t numberOfCores,
|
||||
size_t maxPayloadSize) override;
|
||||
|
||||
virtual int32_t Encode(const webrtc::I420VideoFrame& inputImage,
|
||||
virtual int32_t Encode(const webrtc::VideoFrame& inputImage,
|
||||
const webrtc::CodecSpecificInfo* codecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* frame_types) override;
|
||||
const std::vector<webrtc::FrameType>* frame_types) override;
|
||||
|
||||
virtual int32_t RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback* callback) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ public:
|
|||
CODEC_LOGD("Decoder NewFrame: %dx%d, timestamp %lld, renderTimeMs %lld",
|
||||
picSize.width, picSize.height, timestamp, renderTimeMs);
|
||||
|
||||
nsAutoPtr<webrtc::I420VideoFrame> videoFrame(new webrtc::I420VideoFrame(
|
||||
nsAutoPtr<webrtc::VideoFrame> videoFrame(new webrtc::VideoFrame(
|
||||
new ImageNativeHandle(grallocImage.forget()),
|
||||
picSize.width,
|
||||
picSize.height,
|
||||
|
|
@ -857,9 +857,9 @@ WebrtcOMXH264VideoEncoder::InitEncode(const webrtc::VideoCodec* aCodecSettings,
|
|||
}
|
||||
|
||||
int32_t
|
||||
WebrtcOMXH264VideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
|
||||
WebrtcOMXH264VideoEncoder::Encode(const webrtc::VideoFrame& aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes)
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes)
|
||||
{
|
||||
MOZ_ASSERT(mOMX != nullptr);
|
||||
if (mOMX == nullptr) {
|
||||
|
|
@ -973,7 +973,7 @@ WebrtcOMXH264VideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
|
|||
#endif
|
||||
}
|
||||
|
||||
// Wrap I420VideoFrame input with PlanarYCbCrImage for OMXVideoEncoder.
|
||||
// Wrap VideoFrame input with PlanarYCbCrImage for OMXVideoEncoder.
|
||||
layers::PlanarYCbCrData yuvData;
|
||||
yuvData.mYChannel = const_cast<uint8_t*>(aInputImage.buffer(webrtc::kYPlane));
|
||||
yuvData.mYSize = gfx::IntSize(aInputImage.width(), aInputImage.height());
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ public:
|
|||
int32_t aNumOfCores,
|
||||
size_t aMaxPayloadSize) override;
|
||||
|
||||
virtual int32_t Encode(const webrtc::I420VideoFrame& aInputImage,
|
||||
virtual int32_t Encode(const webrtc::VideoFrame& aInputImage,
|
||||
const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
|
||||
const std::vector<webrtc::VideoFrameType>* aFrameTypes) override;
|
||||
const std::vector<webrtc::FrameType>* aFrameTypes) override;
|
||||
|
||||
virtual int32_t RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback* aCallback) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,9 +57,7 @@
|
|||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include "webrtc/common_types.h"
|
||||
#include "webrtc/common_video/interface/native_handle.h"
|
||||
#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "webrtc/video_engine/include/vie_errors.h"
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
|
|
@ -93,7 +91,7 @@ public:
|
|||
VideoType aVideoType,
|
||||
uint64_t aCaptureTime) = 0;
|
||||
|
||||
virtual void OnVideoFrameConverted(webrtc::I420VideoFrame& aVideoFrame) = 0;
|
||||
virtual void OnVideoFrameConverted(webrtc::VideoFrame& aVideoFrame) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~VideoConverterListener() {}
|
||||
|
|
@ -249,7 +247,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void VideoFrameConverted(webrtc::I420VideoFrame& aVideoFrame)
|
||||
void VideoFrameConverted(webrtc::VideoFrame& aVideoFrame)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
|
|
@ -317,7 +315,7 @@ protected:
|
|||
|
||||
if (destFormat != mozilla::kVideoI420) {
|
||||
unsigned char *video_frame = static_cast<unsigned char*>(basePtr);
|
||||
webrtc::I420VideoFrame i420_frame;
|
||||
webrtc::VideoFrame i420_frame;
|
||||
int stride_y = width;
|
||||
int stride_uv = (width + 1) / 2;
|
||||
int target_width = width;
|
||||
|
|
@ -366,7 +364,7 @@ protected:
|
|||
uint32_t width = yuv->GetSize().width;
|
||||
uint32_t height = yuv->GetSize().height;
|
||||
|
||||
webrtc::I420VideoFrame i420_frame;
|
||||
webrtc::VideoFrame i420_frame;
|
||||
int rv = i420_frame.CreateFrame(y, cb, cr, width, height,
|
||||
yStride, cbCrStride, cbCrStride,
|
||||
webrtc::kVideoRotation_0);
|
||||
|
|
@ -747,25 +745,24 @@ MediaPipeline::UpdateTransport_s(int level,
|
|||
void
|
||||
MediaPipeline::SelectSsrc_m(size_t ssrc_index)
|
||||
{
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
this,
|
||||
&MediaPipeline::SelectSsrc_s,
|
||||
ssrc_index),
|
||||
NS_DISPATCH_NORMAL);
|
||||
if (ssrc_index < ssrcs_received_.size()) {
|
||||
uint32_t ssrc = ssrcs_received_[ssrc_index];
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
this,
|
||||
&MediaPipeline::SelectSsrc_s,
|
||||
ssrc),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
conduit_->SetRemoteSSRC(ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaPipeline::SelectSsrc_s(size_t ssrc_index)
|
||||
MediaPipeline::SelectSsrc_s(uint32_t ssrc)
|
||||
{
|
||||
filter_ = new MediaPipelineFilter;
|
||||
if (ssrc_index < ssrcs_received_.size()) {
|
||||
filter_->AddRemoteSSRC(ssrcs_received_[ssrc_index]);
|
||||
} else {
|
||||
MOZ_MTLOG(ML_WARNING, "SelectSsrc called with " << ssrc_index << " but we "
|
||||
<< "have only seen " << ssrcs_received_.size()
|
||||
<< " ssrcs");
|
||||
}
|
||||
filter_->AddRemoteSSRC(ssrc);
|
||||
}
|
||||
|
||||
void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) {
|
||||
|
|
@ -1274,7 +1271,7 @@ public:
|
|||
aVideoFrame, aVideoFrameLength, aWidth, aHeight, aVideoType, aCaptureTime);
|
||||
}
|
||||
|
||||
void OnVideoFrameConverted(webrtc::I420VideoFrame& aVideoFrame)
|
||||
void OnVideoFrameConverted(webrtc::VideoFrame& aVideoFrame)
|
||||
{
|
||||
MOZ_ASSERT(conduit_->type() == MediaSessionConduit::VIDEO);
|
||||
static_cast<VideoSessionConduit*>(conduit_.get())->SendVideoFrame(aVideoFrame);
|
||||
|
|
@ -1368,7 +1365,7 @@ public:
|
|||
aWidth, aHeight, aVideoType, aCaptureTime);
|
||||
}
|
||||
|
||||
void OnVideoFrameConverted(webrtc::I420VideoFrame& aVideoFrame) override
|
||||
void OnVideoFrameConverted(webrtc::VideoFrame& aVideoFrame) override
|
||||
{
|
||||
MutexAutoLock lock(mutex_);
|
||||
|
||||
|
|
@ -1638,19 +1635,18 @@ MediaPipeline::TransportInfo* MediaPipeline::GetTransportInfo_s(
|
|||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtpPacket(
|
||||
const void *data, int len) {
|
||||
const uint8_t* data, size_t len) {
|
||||
|
||||
nsAutoPtr<DataBuffer> buf(new DataBuffer(static_cast<const uint8_t *>(data),
|
||||
len, len + SRTP_MAX_EXPANSION));
|
||||
nsAutoPtr<DataBuffer> buf(new DataBuffer(data, len, len + SRTP_MAX_EXPANSION));
|
||||
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
RefPtr<MediaPipeline::PipelineTransport>(this),
|
||||
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
|
||||
buf, true),
|
||||
NS_DISPATCH_NORMAL);
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
RefPtr<MediaPipeline::PipelineTransport>(this),
|
||||
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
|
||||
buf, true),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
|
||||
|
|
@ -1705,19 +1701,18 @@ nsresult MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
|
|||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(
|
||||
const void *data, int len) {
|
||||
const uint8_t* data, size_t len) {
|
||||
|
||||
nsAutoPtr<DataBuffer> buf(new DataBuffer(static_cast<const uint8_t *>(data),
|
||||
len, len + SRTP_MAX_EXPANSION));
|
||||
nsAutoPtr<DataBuffer> buf(new DataBuffer(data, len, len + SRTP_MAX_EXPANSION));
|
||||
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
RefPtr<MediaPipeline::PipelineTransport>(this),
|
||||
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
|
||||
buf, false),
|
||||
NS_DISPATCH_NORMAL);
|
||||
RUN_ON_THREAD(sts_thread_,
|
||||
WrapRunnable(
|
||||
RefPtr<MediaPipeline::PipelineTransport>(this),
|
||||
&MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s,
|
||||
buf, false),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipelineTransmit::PipelineListener::
|
||||
|
|
@ -2212,12 +2207,14 @@ public:
|
|||
{
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
ReentrantMonitorAutoEnter enter(monitor_);
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
if (buffer) {
|
||||
// Create a video frame using |buffer|.
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
RefPtr<PlanarYCbCrImage> yuvImage = new GrallocImage();
|
||||
#else
|
||||
RefPtr<PlanarYCbCrImage> yuvImage = image_container_->CreatePlanarYCbCrImage();
|
||||
#endif // MOZ_WIDGET_GONK
|
||||
uint8_t* frame = const_cast<uint8_t*>(static_cast<const uint8_t*> (buffer));
|
||||
|
||||
PlanarYCbCrData yuvData;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "AudioPacketizer.h"
|
||||
#include "StreamTracks.h"
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
|
||||
// Should come from MediaEngine.h, but that's a pain to include here
|
||||
// because of the MOZILLA_EXTERNAL_LINKAGE stuff.
|
||||
|
|
@ -124,7 +124,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
// Used only for testing; installs a MediaPipelineFilter that filters
|
||||
// everything but the nth ssrc
|
||||
void SelectSsrc_m(size_t ssrc_index);
|
||||
void SelectSsrc_s(size_t ssrc_index);
|
||||
void SelectSsrc_s(uint32_t ssrc);
|
||||
|
||||
virtual Direction direction() const { return direction_; }
|
||||
virtual const std::string& trackid() const { return track_id_; }
|
||||
|
|
@ -154,11 +154,6 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
MAX_RTP_TYPE
|
||||
} RtpType;
|
||||
|
||||
protected:
|
||||
virtual ~MediaPipeline();
|
||||
virtual void DetachMedia() {}
|
||||
nsresult AttachTransport_s();
|
||||
|
||||
// Separate class to allow ref counting
|
||||
class PipelineTransport : public TransportInterface {
|
||||
public:
|
||||
|
|
@ -171,8 +166,8 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
void Detach() { pipeline_ = nullptr; }
|
||||
MediaPipeline *pipeline() const { return pipeline_; }
|
||||
|
||||
virtual nsresult SendRtpPacket(const void* data, int len);
|
||||
virtual nsresult SendRtcpPacket(const void* data, int len);
|
||||
virtual nsresult SendRtpPacket(const uint8_t* data, size_t len);
|
||||
virtual nsresult SendRtcpPacket(const uint8_t* data, size_t len);
|
||||
|
||||
private:
|
||||
nsresult SendRtpRtcpPacket_s(nsAutoPtr<DataBuffer> data,
|
||||
|
|
@ -181,6 +176,15 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
MediaPipeline *pipeline_; // Raw pointer to avoid cycles
|
||||
nsCOMPtr<nsIEventTarget> sts_thread_;
|
||||
};
|
||||
|
||||
RefPtr<PipelineTransport> GetPiplelineTransport() {
|
||||
return transport_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~MediaPipeline();
|
||||
virtual void DetachMedia() {}
|
||||
nsresult AttachTransport_s();
|
||||
friend class PipelineTransport;
|
||||
|
||||
class TransportInfo {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "MediaPipelineFilter.h"
|
||||
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/common_types.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
|||
|
|
@ -27,16 +27,6 @@
|
|||
#include "MediaEngine.h"
|
||||
#endif
|
||||
|
||||
#include "GmpVideoCodec.h"
|
||||
#ifdef MOZ_WEBRTC_OMX
|
||||
#include "OMXVideoCodec.h"
|
||||
#include "OMXCodecWrapper.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBRTC_MEDIACODEC
|
||||
#include "MediaCodecVideoCodec.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
#include "mozilla/Preferences.h"
|
||||
#endif
|
||||
|
|
@ -167,6 +157,8 @@ NegotiatedDetailsToVideoCodecConfigs(const JsepTrackNegotiatedDetails& aDetails,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
config->mTias = aDetails.GetTias();
|
||||
|
||||
for (size_t i = 0; i < aDetails.GetEncodingCount(); ++i) {
|
||||
const JsepTrackEncoding& jsepEncoding(aDetails.GetEncoding(i));
|
||||
if (jsepEncoding.HasFormat(codec->mDefaultPt)) {
|
||||
|
|
@ -176,6 +168,7 @@ NegotiatedDetailsToVideoCodecConfigs(const JsepTrackNegotiatedDetails& aDetails,
|
|||
config->mSimulcastEncodings.push_back(encoding);
|
||||
}
|
||||
}
|
||||
|
||||
aConfigs->values.push_back(config);
|
||||
}
|
||||
|
||||
|
|
@ -453,12 +446,14 @@ MediaPipelineFactory::CreateOrUpdateMediaPipeline(
|
|||
RefPtr<MediaSessionConduit> conduit;
|
||||
if (aTrack.GetMediaType() == SdpMediaSection::kAudio) {
|
||||
rv = GetOrCreateAudioConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
} else if (aTrack.GetMediaType() == SdpMediaSection::kVideo) {
|
||||
rv = GetOrCreateVideoConduit(aTrackPair, aTrack, &conduit);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
// We've created the TransportFlow, nothing else to do here.
|
||||
return NS_OK;
|
||||
|
|
@ -730,17 +725,16 @@ MediaPipelineFactory::GetOrCreateAudioConduit(
|
|||
if (!aTrackPair.mSending) {
|
||||
// No send track, but we still need to configure an SSRC for receiver
|
||||
// reports.
|
||||
if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) {
|
||||
if (!conduit->SetLocalSSRCs(std::vector<unsigned int>(1,aTrackPair.mRecvonlySsrc))) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For now we only expect to have one ssrc per local track.
|
||||
auto ssrcs = aTrack.GetSsrcs();
|
||||
if (!ssrcs.empty()) {
|
||||
if (!conduit->SetLocalSSRC(ssrcs.front())) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
if (!conduit->SetLocalSSRCs(ssrcs)) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRCs failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
@ -786,7 +780,6 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
|||
const JsepTrack& aTrack,
|
||||
RefPtr<MediaSessionConduit>* aConduitp)
|
||||
{
|
||||
|
||||
if (!aTrack.GetNegotiatedDetails()) {
|
||||
MOZ_ASSERT(false, "Track is missing negotiated details");
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
|
@ -798,7 +791,7 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
|||
mPCMedia->GetVideoConduit(aTrackPair.mLevel);
|
||||
|
||||
if (!conduit) {
|
||||
conduit = VideoSessionConduit::Create();
|
||||
conduit = VideoSessionConduit::Create(mPCMedia->mCall);
|
||||
if (!conduit) {
|
||||
MOZ_MTLOG(ML_ERROR, "Could not create video conduit");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
@ -822,103 +815,80 @@ MediaPipelineFactory::GetOrCreateVideoConduit(
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
const std::vector<uint32_t>* ssrcs;
|
||||
|
||||
if (receiving) {
|
||||
// NOTE(pkerr) - the Call API requires the both local_ssrc and remote_ssrc be
|
||||
// set to a non-zero value or the CreateVideo...Stream call will fail.
|
||||
if (aTrackPair.mSending) {
|
||||
auto ssrcs = &aTrackPair.mSending->GetSsrcs();
|
||||
ssrcs = &aTrackPair.mSending->GetSsrcs();
|
||||
if (!ssrcs->empty()) {
|
||||
if (!conduit->SetLocalSSRC(ssrcs->front())) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed(1)");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
MOZ_MTLOG(ML_ERROR, "Sending without an SSRC??");
|
||||
return NS_ERROR_FAILURE;
|
||||
conduit->SetLocalSSRCs(*ssrcs);
|
||||
}
|
||||
} else {
|
||||
// No send track, but we still need to configure an SSRC for receiver
|
||||
// reports.
|
||||
if (!conduit->SetLocalSSRC(aTrackPair.mRecvonlySsrc)) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed(2)");
|
||||
if (!conduit->SetLocalSSRCs(std::vector<unsigned int>(1,aTrackPair.mRecvonlySsrc))) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRCs failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Prune out stuff we cannot actually do. We should work to eliminate the
|
||||
// need for this.
|
||||
bool configuredH264 = false;
|
||||
for (size_t i = 0; i < configs.values.size();) {
|
||||
// TODO(bug 1200768): We can only handle configuring one recv H264 codec
|
||||
if (configuredH264 && (configs.values[i]->mName == "H264")) {
|
||||
delete configs.values[i];
|
||||
configs.values.erase(configs.values.begin() + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(bug 1018791): This really should be checked sooner
|
||||
if (EnsureExternalCodec(*conduit, configs.values[i], false)) {
|
||||
delete configs.values[i];
|
||||
configs.values.erase(configs.values.begin() + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (configs.values[i]->mName == "H264") {
|
||||
configuredH264 = true;
|
||||
}
|
||||
++i;
|
||||
ssrcs = &aTrack.GetSsrcs();
|
||||
// NOTE(pkerr) - this is new behavior. Needed because the CreateVideoReceiveStream
|
||||
// method of the Call API will assert (in debug) and fail if a value is not provided
|
||||
// for the remote_ssrc that will be used by the far-end sender.
|
||||
if (ssrcs->empty()) {
|
||||
MOZ_MTLOG(ML_ERROR, "No SSRC set for receive track");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
conduit->SetRemoteSSRC(ssrcs->front());
|
||||
|
||||
auto error = conduit->ConfigureRecvMediaCodecs(configs.values);
|
||||
|
||||
if (error) {
|
||||
MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
} else { //Create a send side
|
||||
// For now we only expect to have one ssrc per local track.
|
||||
auto ssrcs = aTrack.GetSsrcs();
|
||||
if (!ssrcs.empty()) {
|
||||
if (!conduit->SetLocalSSRC(ssrcs.front())) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ssrcs = &aTrack.GetSsrcs();
|
||||
if (ssrcs->empty()) {
|
||||
MOZ_MTLOG(ML_ERROR, "No SSRC set for send track");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!conduit->SetLocalSSRCs(*ssrcs)) {
|
||||
MOZ_MTLOG(ML_ERROR, "SetLocalSSRC failed");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
conduit->SetLocalCNAME(aTrack.GetCNAME().c_str());
|
||||
|
||||
rv = ConfigureVideoCodecMode(aTrack,*conduit);
|
||||
rv = ConfigureVideoCodecMode(aTrack, *conduit);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// TODO(bug 1018791): This really should be checked sooner
|
||||
if (EnsureExternalCodec(*conduit, configs.values[0], true)) {
|
||||
MOZ_MTLOG(ML_ERROR, "External codec not available");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
auto error = conduit->ConfigureSendMediaCodec(configs.values[0]);
|
||||
|
||||
const SdpExtmapAttributeList::Extmap* rtpStreamIdExt =
|
||||
aTrack.GetNegotiatedDetails()->GetExt(
|
||||
"urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
|
||||
|
||||
if (rtpStreamIdExt) {
|
||||
MOZ_MTLOG(ML_DEBUG, "Calling EnableRTPSenderIdExtension");
|
||||
error = conduit->EnableRTPStreamIdExtension(true, rtpStreamIdExt->entry);
|
||||
|
||||
if (error) {
|
||||
MOZ_MTLOG(ML_ERROR, "EnableRTPSenderIdExtension failed: " << error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
const JsepTrackNegotiatedDetails* details = aTrack.GetNegotiatedDetails();
|
||||
if (details) {
|
||||
// @@NG read extmap from track
|
||||
std::vector<webrtc::RtpExtension> extmaps;
|
||||
details->ForEachRTPHeaderExtension(
|
||||
[&conduit,&extmaps](const SdpExtmapAttributeList::Extmap& extmap)
|
||||
{
|
||||
extmaps.emplace_back(extmap.extensionname,extmap.entry);
|
||||
});
|
||||
conduit->AddLocalRTPExtensions(extmaps);
|
||||
}
|
||||
|
||||
*aConduitp = conduit;
|
||||
|
||||
return NS_OK;
|
||||
|
|
@ -970,107 +940,5 @@ MediaPipelineFactory::ConfigureVideoCodecMode(const JsepTrack& aTrack,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add external H.264 video codec.
|
||||
*/
|
||||
MediaConduitErrorCode
|
||||
MediaPipelineFactory::EnsureExternalCodec(VideoSessionConduit& aConduit,
|
||||
VideoCodecConfig* aConfig,
|
||||
bool aIsSend)
|
||||
{
|
||||
if (aConfig->mName == "VP8") {
|
||||
#ifdef MOZ_WEBRTC_MEDIACODEC
|
||||
if (aIsSend) {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
bool enabled = mozilla::Preferences::GetBool("media.navigator.hardware.vp8_encode.acceleration_enabled", false);
|
||||
#else
|
||||
bool enabled = false;
|
||||
#endif
|
||||
if (enabled) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||
if (gfxInfo) {
|
||||
int32_t status;
|
||||
nsCString discardFailureId;
|
||||
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_ENCODE, discardFailureId, &status))) {
|
||||
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
|
||||
NS_WARNING("VP8 encoder hardware is not whitelisted: disabling.\n");
|
||||
} else {
|
||||
VideoEncoder* encoder = nullptr;
|
||||
encoder = MediaCodecVideoCodec::CreateEncoder(MediaCodecVideoCodec::CodecType::CODEC_VP8);
|
||||
if (encoder) {
|
||||
return aConduit.SetExternalSendCodec(aConfig, encoder);
|
||||
}
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
bool enabled = mozilla::Preferences::GetBool("media.navigator.hardware.vp8_decode.acceleration_enabled", false);
|
||||
#else
|
||||
bool enabled = false;
|
||||
#endif
|
||||
if (enabled) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||
if (gfxInfo) {
|
||||
int32_t status;
|
||||
nsCString discardFailureId;
|
||||
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBRTC_HW_ACCELERATION_DECODE, discardFailureId, &status))) {
|
||||
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
|
||||
NS_WARNING("VP8 decoder hardware is not whitelisted: disabling.\n");
|
||||
} else {
|
||||
VideoDecoder* decoder;
|
||||
decoder = MediaCodecVideoCodec::CreateDecoder(MediaCodecVideoCodec::CodecType::CODEC_VP8);
|
||||
if (decoder) {
|
||||
return aConduit.SetExternalRecvCodec(aConfig, decoder);
|
||||
}
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
if (aConfig->mName == "VP9") {
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
if (aConfig->mName == "H264") {
|
||||
if (aConduit.CodecPluginID() != 0) {
|
||||
return kMediaConduitNoError;
|
||||
}
|
||||
// Register H.264 codec.
|
||||
if (aIsSend) {
|
||||
VideoEncoder* encoder = nullptr;
|
||||
#ifdef MOZ_WEBRTC_OMX
|
||||
encoder =
|
||||
OMXVideoCodec::CreateEncoder(OMXVideoCodec::CodecType::CODEC_H264);
|
||||
#else
|
||||
encoder = GmpVideoCodec::CreateEncoder();
|
||||
#endif
|
||||
if (encoder) {
|
||||
return aConduit.SetExternalSendCodec(aConfig, encoder);
|
||||
}
|
||||
return kMediaConduitInvalidSendCodec;
|
||||
}
|
||||
VideoDecoder* decoder = nullptr;
|
||||
#ifdef MOZ_WEBRTC_OMX
|
||||
decoder =
|
||||
OMXVideoCodec::CreateDecoder(OMXVideoCodec::CodecType::CODEC_H264);
|
||||
#else
|
||||
decoder = GmpVideoCodec::CreateDecoder();
|
||||
#endif
|
||||
if (decoder) {
|
||||
return aConduit.SetExternalRecvCodec(aConfig, decoder);
|
||||
}
|
||||
return kMediaConduitInvalidReceiveCodec;
|
||||
}
|
||||
MOZ_MTLOG(ML_ERROR,
|
||||
"Invalid video codec configured: " << aConfig->mName.c_str());
|
||||
return aIsSend ? kMediaConduitInvalidSendCodec
|
||||
: kMediaConduitInvalidReceiveCodec;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
|||
|
|
@ -52,10 +52,6 @@ private:
|
|||
const JsepTrack& aTrack,
|
||||
RefPtr<MediaSessionConduit>* aConduitp);
|
||||
|
||||
MediaConduitErrorCode EnsureExternalCodec(VideoSessionConduit& aConduit,
|
||||
VideoCodecConfig* aConfig,
|
||||
bool aIsSend);
|
||||
|
||||
nsresult CreateOrGetTransportFlow(size_t aLevel, bool aIsRtcp,
|
||||
const JsepTransport& transport,
|
||||
RefPtr<TransportFlow>* out);
|
||||
|
|
|
|||
|
|
@ -2745,7 +2745,11 @@ PeerConnectionImpl::ReplaceTrack(MediaStreamTrack& aThisTrack,
|
|||
// We update the media pipelines here so we can apply different codec
|
||||
// settings for different sources (e.g. screensharing as opposed to camera.)
|
||||
// TODO: We should probably only do this if the source has in fact changed.
|
||||
mMedia->UpdateMediaPipelines(*mJsepSession);
|
||||
|
||||
if (NS_FAILED((rv = mMedia->UpdateMediaPipelines(*mJsepSession)))) {
|
||||
CSFLogError(logTag, "Error Updating MediaPipelines");
|
||||
return rv;
|
||||
}
|
||||
|
||||
pco->OnReplaceTrackSuccess(jrv);
|
||||
if (jrv.Failed()) {
|
||||
|
|
@ -3108,7 +3112,11 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState,
|
|||
// transports, but nothing further needs to be done.
|
||||
mMedia->ActivateOrRemoveTransports(*mJsepSession);
|
||||
if (!rollback) {
|
||||
mMedia->UpdateMediaPipelines(*mJsepSession);
|
||||
if (NS_FAILED(mMedia->UpdateMediaPipelines(*mJsepSession))) {
|
||||
CSFLogError(logTag, "Error Updating MediaPipelines");
|
||||
NS_ASSERTION(false, "Error Updating MediaPipelines in SetSignalingState_m()");
|
||||
// XXX what now? Not much we can do but keep going, without major restructuring
|
||||
}
|
||||
InitializeDataChannel();
|
||||
mMedia->StartIceChecks(*mJsepSession);
|
||||
}
|
||||
|
|
@ -3663,15 +3671,17 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) {
|
|||
idstr.AppendLiteral("_");
|
||||
idstr.AppendInt(mp.level());
|
||||
|
||||
// TODO(@@NG):ssrcs handle Conduits having multiple stats at the same level
|
||||
// This is pending spec work
|
||||
// Gather pipeline stats.
|
||||
switch (mp.direction()) {
|
||||
case MediaPipeline::TRANSMIT: {
|
||||
nsString localId = NS_LITERAL_STRING("outbound_rtp_") + idstr;
|
||||
nsString remoteId;
|
||||
nsString ssrc;
|
||||
unsigned int ssrcval;
|
||||
if (mp.Conduit()->GetLocalSSRC(&ssrcval)) {
|
||||
ssrc.AppendInt(ssrcval);
|
||||
std::vector<unsigned int> ssrcvals = mp.Conduit()->GetLocalSSRCs();
|
||||
if (!ssrcvals.empty()) {
|
||||
ssrc.AppendInt(ssrcvals[0]);
|
||||
}
|
||||
{
|
||||
// First, fill in remote stat with rtcp receiver data, if present.
|
||||
|
|
|
|||
|
|
@ -67,6 +67,14 @@ using namespace dom;
|
|||
|
||||
static const char* logTag = "PeerConnectionMedia";
|
||||
|
||||
//XXX(pkerr) What about bitrate settings? Going with the defaults for now.
|
||||
RefPtr<WebRtcCallWrapper>
|
||||
CreateCall()
|
||||
{
|
||||
WebRtcCallWrapper::Config call_config;
|
||||
return WebRtcCallWrapper::Create(call_config);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionMedia::ReplaceTrack(const std::string& aOldStreamId,
|
||||
const std::string& aOldTrackId,
|
||||
|
|
@ -406,6 +414,9 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
|
|||
}
|
||||
ConnectSignals(mIceCtxHdlr->ctx().get());
|
||||
|
||||
// This webrtc:Call instance will be shared by audio and video media conduits.
|
||||
mCall = CreateCall();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -567,6 +578,7 @@ nsresult PeerConnectionMedia::UpdateMediaPipelines(
|
|||
JsepTrackPair pair = *i;
|
||||
|
||||
if (pair.mReceiving) {
|
||||
|
||||
rv = factory.CreateOrUpdateMediaPipeline(pair, *pair.mReceiving);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
|
|
|||
|
|
@ -410,15 +410,15 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
static_cast<VideoSessionConduit*>(it->second.second.get()));
|
||||
}
|
||||
|
||||
void AddVideoConduit(size_t level, const RefPtr<VideoSessionConduit> &aConduit) {
|
||||
mConduits[level] = std::make_pair(true, aConduit);
|
||||
}
|
||||
|
||||
// Add a conduit
|
||||
void AddAudioConduit(size_t level, const RefPtr<AudioSessionConduit> &aConduit) {
|
||||
mConduits[level] = std::make_pair(false, aConduit);
|
||||
}
|
||||
|
||||
void AddVideoConduit(size_t level, const RefPtr<VideoSessionConduit> &aConduit) {
|
||||
mConduits[level] = std::make_pair(true, aConduit);
|
||||
}
|
||||
|
||||
// ICE state signals
|
||||
sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
|
||||
SignalIceGatheringStateChange;
|
||||
|
|
@ -433,6 +433,8 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
sigslot::signal1<uint16_t>
|
||||
SignalEndOfLocalCandidates;
|
||||
|
||||
RefPtr<WebRtcCallWrapper> mCall;
|
||||
|
||||
private:
|
||||
nsresult InitProxy();
|
||||
class ProtocolProxyQueryHandler : public nsIProtocolProxyCallback {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "runnable_utils.h"
|
||||
#include "PeerConnectionCtx.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/system_wrappers/include/trace.h"
|
||||
|
||||
static const char* logTag = "WebrtcGlobalInformation";
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "mtransport_test_utils.h"
|
||||
#include "runnable_utils.h"
|
||||
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
|
||||
#include "FakeIPC.h"
|
||||
#include "FakeIPC.cpp"
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
# Names should be added to this file like so:
|
||||
# Name or Organization <email address>
|
||||
|
||||
Andrew MacDonald <andrew@webrtc.org>
|
||||
Anil Kumar <an1kumar@gmail.com>
|
||||
Ben Strong <bstrong@gmail.com>
|
||||
Bob Withers <bwit@pobox.com>
|
||||
Bridger Maxwell <bridgeyman@gmail.com>
|
||||
Christophe Dumez <ch.dumez@samsung.com>
|
||||
Colin Plumb
|
||||
Eric Rescorla, RTFM Inc.
|
||||
Eric Rescorla, RTFM Inc. <ekr@rtfm.com>
|
||||
Giji Gangadharan <giji.g@samsung.com>
|
||||
Graham Yoakum <gyoakum@skobalt.com>
|
||||
Jake Hilton <jakehilton@gmail.com>
|
||||
James H. Brown <jbrown@burgoyne.com>
|
||||
Jiawei Ou <jiawei.ou@gmail.com>
|
||||
Jie Mao <maojie0924@gmail.com>
|
||||
Luke Weber
|
||||
Luke Weber <luke.weber@gmail.com>
|
||||
Manish Jethani <manish.jethani@gmail.com>
|
||||
Martin Storsjo <martin@martin.st>
|
||||
Matthias Liebig <matthias.gcode@gmail.com>
|
||||
|
|
@ -21,8 +23,8 @@ Pali Rohar
|
|||
Paul Kapustin <pkapustin@gmail.com>
|
||||
Rafael Lopez Diez <rafalopezdiez@gmail.com>
|
||||
Ralph Giles <giles@ghostscript.com>
|
||||
Robert Nagy
|
||||
Ron Rivest
|
||||
Riku Voipio <riku.voipio@linaro.org>
|
||||
Robert Nagy <robert.nagy@gmail.com>
|
||||
Ryan Yoakum <ryoakum@skobalt.com>
|
||||
Sarah Thompson <sarah@telergy.com>
|
||||
Saul Kravitz <Saul.Kravitz@celera.com>
|
||||
|
|
@ -30,13 +32,19 @@ Silviu Caragea <silviu.cpp@gmail.com>
|
|||
Steve Reid <sreid@sea-to-sky.net>
|
||||
Vicken Simonian <vsimon@gmail.com>
|
||||
Victor Costan <costan@gmail.com>
|
||||
Alexander Brauckmann <a.brauckmann@gmail.com>
|
||||
|
||||
&yet LLC
|
||||
Agora IO
|
||||
ARM Holdings
|
||||
BroadSoft Inc.
|
||||
Google Inc.
|
||||
Intel Corporation
|
||||
MIPS Technologies
|
||||
Mozilla Foundation
|
||||
Opera Software ASA
|
||||
Sinch AB
|
||||
struktur AG
|
||||
Telenor Digital AS
|
||||
Temasys Communications
|
||||
Vonage Holdings Corp.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
vars = {
|
||||
'extra_gyp_flag': '-Dextra_gyp_flag=0',
|
||||
'chromium_git': 'https://chromium.googlesource.com',
|
||||
'chromium_revision': '719b83983be9613eb80e99a0bc645776d59b76b3',
|
||||
'chromium_revision': '099be58b08dadb64b1dc9f359ae097e978df5416',
|
||||
}
|
||||
|
||||
# NOTE: Prefer revision numbers to tags for svn deps. Use http rather than
|
||||
|
|
@ -17,14 +17,14 @@ deps = {
|
|||
'src/third_party/gflags/src':
|
||||
Var('chromium_git') + '/external/gflags/src@e7390f9185c75f8d902c05ed7d20bb94eb914d0c', # from svn revision 82
|
||||
|
||||
'src/third_party/junit':
|
||||
'src/third_party/junit-jar':
|
||||
Var('chromium_git') + '/external/webrtc/deps/third_party/junit@f35596b476aa6e62fd3b3857b9942ddcd13ce35e', # from svn revision 3367
|
||||
}
|
||||
|
||||
deps_os = {
|
||||
'win': {
|
||||
'src/third_party/winsdk_samples/src':
|
||||
Var('chromium_git') + '/external/webrtc/deps/third_party/winsdk_samples_v71@c0cbedd854cb610a53226d9817416c4ab9a7d1e9', # from svn revision 7951
|
||||
Var('chromium_git') + '/external/webrtc/deps/third_party/winsdk_samples_v71@e71b549167a665d7424d6f1dadfbff4b4aad1589',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -34,18 +34,16 @@ include_rules = [
|
|||
# WebRTC production code.
|
||||
'-base',
|
||||
'-chromium',
|
||||
'+external/webrtc/webrtc', # Android platform build.
|
||||
'+gflags',
|
||||
'+libyuv',
|
||||
'+net',
|
||||
'+talk',
|
||||
'+testing',
|
||||
'+third_party',
|
||||
'+unicode',
|
||||
'+webrtc',
|
||||
]
|
||||
|
||||
# checkdeps.py shouldn't check include paths for files in these dirs:
|
||||
skip_child_includes = [
|
||||
'webrtc/overrides',
|
||||
'+vpx',
|
||||
]
|
||||
|
||||
hooks = [
|
||||
|
|
@ -72,6 +70,21 @@ hooks = [
|
|||
'pattern': '.',
|
||||
'action': ['python', 'src/setup_links.py'],
|
||||
},
|
||||
{
|
||||
# This clobbers when necessary (based on get_landmines.py). It should be
|
||||
# an early hook but it will need to be run after syncing Chromium and
|
||||
# setting up the links, so the script actually exists.
|
||||
'name': 'landmines',
|
||||
'pattern': '.',
|
||||
'action': [
|
||||
'python',
|
||||
'src/build/landmines.py',
|
||||
'--landmine-scripts',
|
||||
'src/webrtc/build/get_landmines.py',
|
||||
'--src-dir',
|
||||
'src',
|
||||
],
|
||||
},
|
||||
{
|
||||
# Pull sanitizer-instrumented third-party libraries if requested via
|
||||
# GYP_DEFINES. This could be done as part of sync_chromium.py above
|
||||
|
|
@ -89,6 +102,7 @@ hooks = [
|
|||
'--recursive',
|
||||
'--num_threads=10',
|
||||
'--no_auth',
|
||||
'--quiet',
|
||||
'--bucket', 'chromium-webrtc-resources',
|
||||
'src/resources'],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
andrew@webrtc.org
|
||||
henrika@webrtc.org
|
||||
mflodman@webrtc.org
|
||||
niklas.enbom@webrtc.org
|
||||
|
|
@ -6,6 +5,7 @@ tina.legrand@webrtc.org
|
|||
tommi@webrtc.org
|
||||
per-file .gitignore=*
|
||||
per-file AUTHORS=*
|
||||
per-file .gn=kjellander@webrtc.org
|
||||
per-file BUILD.gn=kjellander@webrtc.org
|
||||
per-file DEPS=*
|
||||
per-file PRESUBMIT.py=kjellander@webrtc.org
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
This folder can be used to pull together the chromium version of webrtc
|
||||
and libjingle, and build the peerconnection sample client and server. This will
|
||||
check out a new repository in which you can build peerconnection_server.
|
||||
|
||||
Steps:
|
||||
1) Create a new directory for the new repository (outside the webrtc repo):
|
||||
mkdir peerconnection
|
||||
cd peerconnection
|
||||
2) gclient config --name trunk http://webrtc.googlecode.com/svn/trunk/peerconnection
|
||||
3) gclient sync
|
||||
4) cd trunk
|
||||
5) make peerconnection_server peerconnection_client
|
||||
23
media/webrtc/trunk/README.md
Normal file
23
media/webrtc/trunk/README.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
**WebRTC is a free, open software project** that provides browsers and mobile
|
||||
applications with Real-Time Communications (RTC) capabilities via simple APIs.
|
||||
The WebRTC components have been optimized to best serve this purpose.
|
||||
|
||||
**Our mission:** To enable rich, high-quality RTC applications to be
|
||||
developed for the browser, mobile platforms, and IoT devices, and allow them
|
||||
all to communicate via a common set of protocols.
|
||||
|
||||
The WebRTC initiative is a project supported by Google, Mozilla and Opera,
|
||||
amongst others. This page is maintained by the Google Chrome team.
|
||||
|
||||
### Development
|
||||
|
||||
See http://www.webrtc.org/native-code/development for instructions on how to get
|
||||
started developing with the native code.
|
||||
|
||||
### More info
|
||||
|
||||
* Official web site: http://www.webrtc.org
|
||||
* Master source code repo: https://chromium.googlesource.com/external/webrtc
|
||||
* Samples and reference apps: https://github.com/webrtc
|
||||
* Mailing list: http://groups.google.com/group/discuss-webrtc
|
||||
* Continuous build: http://build.chromium.org/p/client.webrtc
|
||||
|
|
@ -917,23 +917,24 @@
|
|||
'android_app_version_name%': 'Developer Build',
|
||||
'android_app_version_code%': 0,
|
||||
|
||||
'sas_dll_exists': '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(sas_dll_path))',
|
||||
'wix_exists': '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(wix_path))',
|
||||
'sas_dll_exists': 0, # '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(sas_dll_path))',
|
||||
'wix_exists': 0, # '<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(wix_path))',
|
||||
|
||||
'windows_sdk_default_path': '<(DEPTH)/third_party/platformsdk_win8/files',
|
||||
'directx_sdk_default_path': '<(DEPTH)/third_party/directxsdk/files',
|
||||
# 'directx_sdk_default_path': '<(DEPTH)/third_party/directxsdk/files',
|
||||
'windows_sdk_path%': '<(windows_sdk_default_path)',
|
||||
|
||||
'conditions': [
|
||||
['"<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(windows_sdk_default_path))"=="True"', {
|
||||
'windows_sdk_path%': '<(windows_sdk_default_path)',
|
||||
}, {
|
||||
'windows_sdk_path%': 'C:/Program Files (x86)/Windows Kits/8.0',
|
||||
}],
|
||||
['OS=="win" and "<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(directx_sdk_default_path))"=="True"', {
|
||||
'directx_sdk_path%': '<(directx_sdk_default_path)',
|
||||
}, {
|
||||
'directx_sdk_path%': '$(DXSDK_DIR)',
|
||||
}],
|
||||
#['"<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(windows_sdk_default_path))"=="True"', {
|
||||
# 'windows_sdk_path%': '<(windows_sdk_default_path)',
|
||||
#}, {
|
||||
# 'windows_sdk_path%': 'C:/Program Files (x86)/Windows Kits/8.0',
|
||||
#}],
|
||||
#['OS=="win" and "<!(<(PYTHON) <(DEPTH)/build/dir_exists.py <(directx_sdk_default_path))"=="True"', {
|
||||
# 'directx_sdk_path%': '<(directx_sdk_default_path)',
|
||||
#}, {
|
||||
# 'directx_sdk_path%': '$(DXSDK_DIR)',
|
||||
#}],
|
||||
# If use_official_google_api_keys is already set (to 0 or 1), we
|
||||
# do none of the implicit checking. If it is set to 1 and the
|
||||
# internal keys file is missing, the build will fail at compile
|
||||
|
|
@ -3410,7 +3411,7 @@
|
|||
'<(windows_sdk_path)/Include/shared',
|
||||
'<(windows_sdk_path)/Include/um',
|
||||
'<(windows_sdk_path)/Include/winrt',
|
||||
'<(directx_sdk_path)/Include',
|
||||
# '<(directx_sdk_path)/Include',
|
||||
'$(VSInstallDir)/VC/atlmfc/include',
|
||||
],
|
||||
'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
|
||||
|
|
@ -3442,7 +3443,7 @@
|
|||
'VCLibrarianTool': {
|
||||
'AdditionalOptions': ['/ignore:4221'],
|
||||
'AdditionalLibraryDirectories': [
|
||||
'<(directx_sdk_path)/Lib/x86',
|
||||
# '<(directx_sdk_path)/Lib/x86',
|
||||
'<(windows_sdk_path)/Lib/win8/um/x86',
|
||||
],
|
||||
},
|
||||
|
|
@ -3488,7 +3489,7 @@
|
|||
}],
|
||||
],
|
||||
'AdditionalLibraryDirectories': [
|
||||
'<(directx_sdk_path)/Lib/x86',
|
||||
# '<(directx_sdk_path)/Lib/x86', XXXX
|
||||
'<(windows_sdk_path)/Lib/win8/um/x86',
|
||||
],
|
||||
'GenerateDebugInformation': 'true',
|
||||
|
|
|
|||
|
|
@ -7,10 +7,13 @@
|
|||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'includes': [ 'webrtc/build/common.gypi', ],
|
||||
'includes': [
|
||||
'webrtc/build/common.gypi',
|
||||
'webrtc/video/webrtc_video.gypi',
|
||||
],
|
||||
'variables': {
|
||||
'peerconnection_sample': 'third_party/libjingle/source/talk/examples/peerconnection',
|
||||
},
|
||||
},
|
||||
|
||||
# for mozilla, we want to force stuff to build but we don't want peerconnection_client or server
|
||||
# for unknown reasons, 'targets' must be outside of conditions. And don't try to build a dummy
|
||||
|
|
@ -22,19 +25,21 @@
|
|||
'target_name': 'dummy',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'webrtc/webrtc.gyp:webrtc_lib',
|
||||
'webrtc/modules/modules.gyp:audio_device',
|
||||
'webrtc/modules/modules.gyp:video_capture_module',
|
||||
'webrtc/modules/modules.gyp:video_capture_module_internal_impl',
|
||||
'webrtc/modules/modules.gyp:video_capture_module_internal_impl',
|
||||
'webrtc/modules/modules.gyp:video_render',
|
||||
# 'webrtc/system_wrappers/source/system_wrappers.gyp:system_wrappers',
|
||||
# 'webrtc/system_wrappers/source/system_wrappers.gyp:metrics_default',
|
||||
'webrtc/video_engine/video_engine.gyp:video_engine_core',
|
||||
'webrtc/voice_engine/voice_engine.gyp:voice_engine',
|
||||
# 'webrtc/system_wrappers/source/system_wrappers.gyp:metrics_default',
|
||||
# 'webrtc/video_engine/video_engine.gyp:video_engine_core',
|
||||
'webrtc/voice_engine/voice_engine.gyp:voice_engine',
|
||||
# '<@(webrtc_video_dependencies)',
|
||||
],
|
||||
'conditions': [
|
||||
['OS!="android" and OS!="ios"', {
|
||||
'dependencies': [
|
||||
'webrtc/modules/modules.gyp:desktop_capture',
|
||||
'webrtc/modules/modules.gyp:desktop_capture',
|
||||
],
|
||||
},
|
||||
]],
|
||||
|
|
@ -86,8 +91,8 @@
|
|||
},
|
||||
},
|
||||
'dependencies': [
|
||||
'third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
||||
'third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
|
||||
#'third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
||||
#'third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
|
||||
],
|
||||
'include_dirs': [
|
||||
'src',
|
||||
|
|
@ -114,8 +119,8 @@
|
|||
'<(peerconnection_sample)/client/peer_connection_client.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
||||
'third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
|
||||
#'third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
|
||||
#'third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
|
||||
# TODO(tommi): Switch to this and remove specific gtk dependency
|
||||
# sections below for cflags and link_settings.
|
||||
# '<(DEPTH)/build/linux/system.gyp:gtk',
|
||||
|
|
|
|||
|
|
@ -46,10 +46,13 @@ def FindBuildFiles():
|
|||
build_files.append(file)
|
||||
return build_files
|
||||
|
||||
|
||||
#TODO @@NG Find correct way to pass circular_check to Load
|
||||
# Causes a pickle error in gyp.input.CircularException
|
||||
# see http://stackoverflow.com/questions/4677012/python-cant-pickle-type-x-attribute-lookup-failed
|
||||
# we'll live without the check - jesup
|
||||
def Load(build_files, format, default_variables={},
|
||||
includes=[], depth='.', params=None, check=False,
|
||||
circular_check=True, duplicate_basename_check=True):
|
||||
circular_check=False, duplicate_basename_check=True):
|
||||
"""
|
||||
Loads one or more specified build files.
|
||||
default_variables and includes will be copied before use.
|
||||
|
|
|
|||
31
media/webrtc/trunk/webrtc/.gitignore
vendored
31
media/webrtc/trunk/webrtc/.gitignore
vendored
|
|
@ -1,2 +1,29 @@
|
|||
# This file is for projects that checkout webrtc/ directly (e.g. Chromium).
|
||||
*.mk
|
||||
# This file is for projects that checkout webrtc/ directly (e.g. Chromium). It
|
||||
# is a truncated copy of the .gitignore file in the parent directory.
|
||||
*.DS_Store
|
||||
*.Makefile
|
||||
*.host.mk
|
||||
*.ncb
|
||||
*.ninja
|
||||
*.props
|
||||
*.pyc
|
||||
*.rules
|
||||
*.scons
|
||||
*.sdf
|
||||
*.sln
|
||||
*.suo
|
||||
*.target.mk
|
||||
*.targets
|
||||
*.user
|
||||
*.vcproj
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vpj
|
||||
*.vpw
|
||||
*.vpwhistu
|
||||
*.vtg
|
||||
*.xcodeproj
|
||||
*_proto.xml
|
||||
*_proto_cpp.xml
|
||||
*~
|
||||
.*.sw?
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
|
||||
# TODO(kjellander): Rebase this to webrtc/build/common.gypi changes after r6330.
|
||||
|
||||
import("//build/config/crypto.gni")
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
import("//build/config/sanitizers/sanitizers.gni")
|
||||
import("build/webrtc.gni")
|
||||
import("//third_party/protobuf/proto_library.gni")
|
||||
|
||||
# Contains the defines and includes in common.gypi that are duplicated both as
|
||||
# target_defaults and direct_dependent_settings.
|
||||
|
|
@ -20,13 +21,12 @@ config("common_inherited_config") {
|
|||
defines += [ "WEBRTC_MOZILLA_BUILD" ]
|
||||
}
|
||||
if (build_with_chromium) {
|
||||
defines = [
|
||||
"WEBRTC_CHROMIUM_BUILD",
|
||||
]
|
||||
defines = [ "WEBRTC_CHROMIUM_BUILD" ]
|
||||
include_dirs = [
|
||||
# overrides must be included first as that is the mechanism for
|
||||
# The overrides must be included first as that is the mechanism for
|
||||
# selecting the override headers in Chromium.
|
||||
"overrides",
|
||||
"../webrtc_overrides",
|
||||
|
||||
# Allow includes to be prefixed with webrtc/ in case it is not an
|
||||
# immediate subdirectory of the top-level.
|
||||
"..",
|
||||
|
|
@ -41,6 +41,9 @@ config("common_inherited_config") {
|
|||
"WEBRTC_IOS",
|
||||
]
|
||||
}
|
||||
if (is_ios && rtc_use_objc_h264) {
|
||||
defines += [ "WEBRTC_OBJC_H264" ]
|
||||
}
|
||||
if (is_linux) {
|
||||
defines += [ "WEBRTC_LINUX" ]
|
||||
}
|
||||
|
|
@ -55,9 +58,6 @@ config("common_inherited_config") {
|
|||
"WEBRTC_LINUX",
|
||||
"WEBRTC_ANDROID",
|
||||
]
|
||||
if (rtc_enable_android_opensl) {
|
||||
defines += [ "WEBRTC_ANDROID_OPENSLES" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,6 +76,7 @@ config("common_config") {
|
|||
|
||||
if (rtc_have_dbus_glib) {
|
||||
defines += [ "HAVE_DBUS_GLIB" ]
|
||||
|
||||
# TODO(kjellander): Investigate this, it seems like include <dbus/dbus.h>
|
||||
# is still not found even if the execution of
|
||||
# build/config/linux/pkg-config.py dbus-glib-1 returns correct include
|
||||
|
|
@ -96,6 +97,7 @@ config("common_config") {
|
|||
if (current_cpu != "arm64" || !is_android) {
|
||||
cflags = [
|
||||
"-Wextra",
|
||||
|
||||
# We need to repeat some flags from Chromium"s common.gypi
|
||||
# here that get overridden by -Wextra.
|
||||
"-Wno-unused-parameter",
|
||||
|
|
@ -104,6 +106,7 @@ config("common_config") {
|
|||
]
|
||||
cflags_cc = [
|
||||
"-Wnon-virtual-dtor",
|
||||
|
||||
# This is enabled for clang; enable for gcc as well.
|
||||
"-Woverloaded-virtual",
|
||||
]
|
||||
|
|
@ -116,13 +119,8 @@ config("common_config") {
|
|||
}
|
||||
|
||||
if (current_cpu == "arm64") {
|
||||
defines += [ "WEBRTC_ARCH_ARM" ]
|
||||
# TODO(zhongwei) Defining an unique WEBRTC_NEON and
|
||||
# distinguishing ARMv7 NEON and ARM64 NEON by
|
||||
# WEBRTC_ARCH_ARM_V7 and WEBRTC_ARCH_ARM64 should be better.
|
||||
|
||||
# This macro is used to distinguish ARMv7 NEON and ARM64 NEON
|
||||
defines += [ "WEBRTC_ARCH_ARM64_NEON" ]
|
||||
defines += [ "WEBRTC_ARCH_ARM64" ]
|
||||
defines += [ "WEBRTC_HAS_NEON" ]
|
||||
}
|
||||
|
||||
if (current_cpu == "arm") {
|
||||
|
|
@ -130,9 +128,9 @@ config("common_config") {
|
|||
if (arm_version >= 7) {
|
||||
defines += [ "WEBRTC_ARCH_ARM_V7" ]
|
||||
if (arm_use_neon) {
|
||||
defines += [ "WEBRTC_ARCH_ARM_NEON" ]
|
||||
} else if (is_android) {
|
||||
defines += [ "WEBRTC_DETECT_ARM_NEON" ]
|
||||
defines += [ "WEBRTC_HAS_NEON" ]
|
||||
} else if (arm_optionally_use_neon) {
|
||||
defines += [ "WEBRTC_DETECT_NEON" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -155,10 +153,7 @@ config("common_config") {
|
|||
}
|
||||
}
|
||||
|
||||
# TODO(kjellander): Handle warnings on Windows where WebRTC differ from the
|
||||
# default warnings set in build/config/compiler/BUILD.gn.
|
||||
|
||||
if (is_android && is_clang) {
|
||||
if (is_android && !is_clang) {
|
||||
# The Android NDK doesn"t provide optimized versions of these
|
||||
# functions. Ensure they are disabled for all compilers.
|
||||
cflags += [
|
||||
|
|
@ -174,17 +169,19 @@ source_set("webrtc") {
|
|||
sources = [
|
||||
"call.h",
|
||||
"config.h",
|
||||
"experiments.h",
|
||||
"frame_callback.h",
|
||||
"transport.h",
|
||||
]
|
||||
|
||||
defines = []
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config"]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
|
||||
deps = [
|
||||
":webrtc_common",
|
||||
"audio",
|
||||
"base:rtc_base",
|
||||
"call",
|
||||
"common_audio",
|
||||
"common_video",
|
||||
"modules/audio_coding",
|
||||
|
|
@ -201,16 +198,20 @@ source_set("webrtc") {
|
|||
"system_wrappers",
|
||||
"tools",
|
||||
"video",
|
||||
"video_engine",
|
||||
"voice_engine",
|
||||
]
|
||||
|
||||
if (build_with_chromium) {
|
||||
deps += [
|
||||
"modules/video_capture",
|
||||
"modules/video_render",
|
||||
"modules/video_capture",
|
||||
"modules/video_render",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "ENABLE_RTC_EVENT_LOG" ]
|
||||
deps += [ ":rtc_event_log_proto" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (!build_with_chromium) {
|
||||
|
|
@ -218,8 +219,8 @@ if (!build_with_chromium) {
|
|||
testonly = true
|
||||
deps = [
|
||||
":webrtc",
|
||||
"modules/video_render:video_render_internal_impl",
|
||||
"modules/video_capture:video_capture_internal_impl",
|
||||
"modules/video_render:video_render_internal_impl",
|
||||
"test",
|
||||
]
|
||||
}
|
||||
|
|
@ -229,14 +230,20 @@ source_set("webrtc_common") {
|
|||
sources = [
|
||||
"common_types.cc",
|
||||
"common_types.h",
|
||||
"config.h",
|
||||
"config.cc",
|
||||
"config.h",
|
||||
"engine_configurations.h",
|
||||
"typedefs.h",
|
||||
]
|
||||
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
|
||||
if (is_clang && !is_nacl) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("gtest_prod") {
|
||||
|
|
@ -244,3 +251,48 @@ source_set("gtest_prod") {
|
|||
"test/testsupport/gtest_prod_util.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
proto_library("rtc_event_log_proto") {
|
||||
sources = [
|
||||
"call/rtc_event_log.proto",
|
||||
]
|
||||
proto_out_dir = "webrtc/call"
|
||||
}
|
||||
}
|
||||
|
||||
source_set("rtc_event_log") {
|
||||
sources = [
|
||||
"call/rtc_event_log.cc",
|
||||
"call/rtc_event_log.h",
|
||||
]
|
||||
|
||||
defines = []
|
||||
configs += [ ":common_config" ]
|
||||
public_configs = [ ":common_inherited_config" ]
|
||||
|
||||
deps = [
|
||||
":webrtc_common",
|
||||
]
|
||||
|
||||
if (rtc_enable_protobuf) {
|
||||
defines += [ "ENABLE_RTC_EVENT_LOG" ]
|
||||
deps += [ ":rtc_event_log_proto" ]
|
||||
}
|
||||
if (is_clang && !is_nacl) {
|
||||
# Suppress warnings from Chrome's Clang plugins.
|
||||
# See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
|
||||
configs -= [ "//build/config/clang:find_bad_constructs" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (use_libfuzzer || use_drfuzz) {
|
||||
# This target is only here for gn to discover fuzzer build targets under
|
||||
# webrtc/test/fuzzers/.
|
||||
group("webrtc_fuzzers_dummy") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"test/fuzzers:webrtc_fuzzer_main",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
76
media/webrtc/trunk/webrtc/api/BUILD.gn
Normal file
76
media/webrtc/trunk/webrtc/api/BUILD.gn
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
import("../build/webrtc.gni")
|
||||
|
||||
config("ios_config") {
|
||||
libs = [
|
||||
"CoreGraphics.framework",
|
||||
"GLKit.framework",
|
||||
"OpenGLES.framework",
|
||||
"QuartzCore.framework",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
source_set("rtc_api_objc") {
|
||||
deps = [
|
||||
"//webrtc/base:rtc_base_objc",
|
||||
#"//talk/libjingle:libjingle_peerconnection",
|
||||
]
|
||||
cflags = [
|
||||
"-fobjc-arc",
|
||||
"-Wobjc-missing-property-synthesis",
|
||||
]
|
||||
sources = [
|
||||
# Add these when there's a BUILD.gn for peer connection APIs
|
||||
#"objc/RTCIceCandidate+Private.h",
|
||||
#"objc/RTCIceCandidate.h",
|
||||
#"objc/RTCIceCandidate.mm",
|
||||
#"objc/RTCMediaSource+Private.h",
|
||||
#"objc/RTCMediaSource.h",
|
||||
#"objc/RTCMediaSource.mm",
|
||||
#"objc/RTCMediaStreamTrack+Private.h",
|
||||
#"objc/RTCMediaStreamTrack.h",
|
||||
#"objc/RTCMediaStreamTrack.mm",
|
||||
"objc/RTCIceServer+Private.h",
|
||||
"objc/RTCIceServer.h",
|
||||
"objc/RTCIceServer.mm",
|
||||
"objc/RTCMediaConstraints+Private.h",
|
||||
"objc/RTCMediaConstraints.h",
|
||||
"objc/RTCMediaConstraints.mm",
|
||||
"objc/RTCOpenGLVideoRenderer.h",
|
||||
"objc/RTCOpenGLVideoRenderer.mm",
|
||||
"objc/RTCSessionDescription+Private.h",
|
||||
"objc/RTCSessionDescription.h",
|
||||
"objc/RTCSessionDescription.mm",
|
||||
"objc/RTCStatsReport+Private.h",
|
||||
"objc/RTCStatsReport.h",
|
||||
"objc/RTCStatsReport.mm",
|
||||
"objc/RTCVideoFrame+Private.h",
|
||||
"objc/RTCVideoFrame.h",
|
||||
"objc/RTCVideoFrame.mm",
|
||||
"objc/RTCVideoRenderer.h",
|
||||
"objc/WebRTC-Prefix.pch",
|
||||
]
|
||||
|
||||
if (is_ios) {
|
||||
sources += [
|
||||
"objc/RTCEAGLVideoView.h",
|
||||
"objc/RTCEAGLVideoView.m",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
sources += [
|
||||
"objc/RTCNSGLVideoView.h",
|
||||
"objc/RTCNSGLVideoView.m",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
1
media/webrtc/trunk/webrtc/api/OWNERS
Normal file
1
media/webrtc/trunk/webrtc/api/OWNERS
Normal file
|
|
@ -0,0 +1 @@
|
|||
tkchin@webrtc.org
|
||||
83
media/webrtc/trunk/webrtc/api/api.gyp
Normal file
83
media/webrtc/trunk/webrtc/api/api.gyp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'includes': [ '../build/common.gypi', ],
|
||||
'conditions': [
|
||||
['OS=="ios"', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'rtc_api_objc',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/base/base.gyp:rtc_base_objc',
|
||||
'../../talk/libjingle.gyp:libjingle_peerconnection',
|
||||
],
|
||||
'sources': [
|
||||
'objc/RTCIceCandidate+Private.h',
|
||||
'objc/RTCIceCandidate.h',
|
||||
'objc/RTCIceCandidate.mm',
|
||||
'objc/RTCIceServer+Private.h',
|
||||
'objc/RTCIceServer.h',
|
||||
'objc/RTCIceServer.mm',
|
||||
'objc/RTCMediaConstraints+Private.h',
|
||||
'objc/RTCMediaConstraints.h',
|
||||
'objc/RTCMediaConstraints.mm',
|
||||
'objc/RTCMediaSource+Private.h',
|
||||
'objc/RTCMediaSource.h',
|
||||
'objc/RTCMediaSource.mm',
|
||||
'objc/RTCMediaStreamTrack+Private.h',
|
||||
'objc/RTCMediaStreamTrack.h',
|
||||
'objc/RTCMediaStreamTrack.mm',
|
||||
'objc/RTCOpenGLVideoRenderer.h',
|
||||
'objc/RTCOpenGLVideoRenderer.mm',
|
||||
'objc/RTCSessionDescription+Private.h',
|
||||
'objc/RTCSessionDescription.h',
|
||||
'objc/RTCSessionDescription.mm',
|
||||
'objc/RTCStatsReport+Private.h',
|
||||
'objc/RTCStatsReport.h',
|
||||
'objc/RTCStatsReport.mm',
|
||||
'objc/RTCVideoFrame+Private.h',
|
||||
'objc/RTCVideoFrame.h',
|
||||
'objc/RTCVideoFrame.mm',
|
||||
'objc/RTCVideoRenderer.h',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="ios"', {
|
||||
'sources': [
|
||||
'objc/RTCEAGLVideoView.h',
|
||||
'objc/RTCEAGLVideoView.m',
|
||||
],
|
||||
'all_dependent_settings': {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [
|
||||
'-framework CoreGraphics',
|
||||
'-framework GLKit',
|
||||
'-framework OpenGLES',
|
||||
'-framework QuartzCore',
|
||||
]
|
||||
}
|
||||
}
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'sources': [
|
||||
'objc/RTCNSGLVideoView.h',
|
||||
'objc/RTCNSGLVideoView.m',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'xcode_settings': {
|
||||
'CLANG_ENABLE_OBJC_ARC': 'YES',
|
||||
'CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS': 'YES',
|
||||
'GCC_PREFIX_HEADER': 'objc/WebRTC-Prefix.pch',
|
||||
},
|
||||
}
|
||||
],
|
||||
}], # OS=="ios"
|
||||
],
|
||||
}
|
||||
40
media/webrtc/trunk/webrtc/api/api_tests.gyp
Normal file
40
media/webrtc/trunk/webrtc/api/api_tests.gyp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license
|
||||
# that can be found in the LICENSE file in the root of the source
|
||||
# tree. An additional intellectual property rights grant can be found
|
||||
# in the file PATENTS. All contributing project authors may
|
||||
# be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
{
|
||||
'includes': [ '../build/common.gypi', ],
|
||||
'conditions': [
|
||||
['OS=="ios"', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'rtc_api_objc_test',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'<(webrtc_root)/api/api.gyp:rtc_api_objc',
|
||||
'<(webrtc_root)/base/base_tests.gyp:rtc_base_tests_utils',
|
||||
],
|
||||
'sources': [
|
||||
'objctests/RTCIceCandidateTest.mm',
|
||||
'objctests/RTCIceServerTest.mm',
|
||||
'objctests/RTCMediaConstraintsTest.mm',
|
||||
'objctests/RTCSessionDescriptionTest.mm',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'CLANG_ENABLE_OBJC_ARC': 'YES',
|
||||
'CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS': 'YES',
|
||||
'GCC_PREFIX_HEADER': 'objc/WebRTC-Prefix.pch',
|
||||
# |-ObjC| flag needed to make sure category method implementations
|
||||
# are included:
|
||||
# https://developer.apple.com/library/mac/qa/qa1490/_index.html
|
||||
'OTHER_LDFLAGS': ['-ObjC'],
|
||||
},
|
||||
}
|
||||
],
|
||||
}], # OS=="ios"
|
||||
],
|
||||
}
|
||||
1
media/webrtc/trunk/webrtc/api/objc/OWNERS
Normal file
1
media/webrtc/trunk/webrtc/api/objc/OWNERS
Normal file
|
|
@ -0,0 +1 @@
|
|||
tkchin@webrtc.org
|
||||
3
media/webrtc/trunk/webrtc/api/objc/README
Normal file
3
media/webrtc/trunk/webrtc/api/objc/README
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
This is a work-in-progress to update the Objective-C API according to the W3C
|
||||
specification. The Objective-C API located at talk/app/webrtc/objc is
|
||||
deprecated, but will remain for the time being.
|
||||
35
media/webrtc/trunk/webrtc/api/objc/RTCEAGLVideoView.h
Normal file
35
media/webrtc/trunk/webrtc/api/objc/RTCEAGLVideoView.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "RTCVideoRenderer.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class RTCEAGLVideoView;
|
||||
@protocol RTCEAGLVideoViewDelegate
|
||||
|
||||
- (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* RTCEAGLVideoView is an RTCVideoRenderer which renders video frames in its
|
||||
* bounds using OpenGLES 2.0.
|
||||
*/
|
||||
@interface RTCEAGLVideoView : UIView <RTCVideoRenderer>
|
||||
|
||||
@property(nonatomic, weak) id<RTCEAGLVideoViewDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
259
media/webrtc/trunk/webrtc/api/objc/RTCEAGLVideoView.m
Normal file
259
media/webrtc/trunk/webrtc/api/objc/RTCEAGLVideoView.m
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCEAGLVideoView.h"
|
||||
|
||||
#import <GLKit/GLKit.h>
|
||||
|
||||
#import "RTCVideoFrame.h"
|
||||
#import "RTCOpenGLVideoRenderer.h"
|
||||
|
||||
// RTCDisplayLinkTimer wraps a CADisplayLink and is set to fire every two screen
|
||||
// refreshes, which should be 30fps. We wrap the display link in order to avoid
|
||||
// a retain cycle since CADisplayLink takes a strong reference onto its target.
|
||||
// The timer is paused by default.
|
||||
@interface RTCDisplayLinkTimer : NSObject
|
||||
|
||||
@property(nonatomic) BOOL isPaused;
|
||||
|
||||
- (instancetype)initWithTimerHandler:(void (^)(void))timerHandler;
|
||||
- (void)invalidate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RTCDisplayLinkTimer {
|
||||
CADisplayLink *_displayLink;
|
||||
void (^_timerHandler)(void);
|
||||
}
|
||||
|
||||
- (instancetype)initWithTimerHandler:(void (^)(void))timerHandler {
|
||||
NSParameterAssert(timerHandler);
|
||||
if (self = [super init]) {
|
||||
_timerHandler = timerHandler;
|
||||
_displayLink =
|
||||
[CADisplayLink displayLinkWithTarget:self
|
||||
selector:@selector(displayLinkDidFire:)];
|
||||
_displayLink.paused = YES;
|
||||
// Set to half of screen refresh, which should be 30fps.
|
||||
[_displayLink setFrameInterval:2];
|
||||
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop]
|
||||
forMode:NSRunLoopCommonModes];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (BOOL)isPaused {
|
||||
return _displayLink.paused;
|
||||
}
|
||||
|
||||
- (void)setIsPaused:(BOOL)isPaused {
|
||||
_displayLink.paused = isPaused;
|
||||
}
|
||||
|
||||
- (void)invalidate {
|
||||
[_displayLink invalidate];
|
||||
}
|
||||
|
||||
- (void)displayLinkDidFire:(CADisplayLink *)displayLink {
|
||||
_timerHandler();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// RTCEAGLVideoView wraps a GLKView which is setup with
|
||||
// enableSetNeedsDisplay = NO for the purpose of gaining control of
|
||||
// exactly when to call -[GLKView display]. This need for extra
|
||||
// control is required to avoid triggering method calls on GLKView
|
||||
// that results in attempting to bind the underlying render buffer
|
||||
// when the drawable size would be empty which would result in the
|
||||
// error GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT. -[GLKView display] is
|
||||
// the method that will trigger the binding of the render
|
||||
// buffer. Because the standard behaviour of -[UIView setNeedsDisplay]
|
||||
// is disabled for the reasons above, the RTCEAGLVideoView maintains
|
||||
// its own |isDirty| flag.
|
||||
|
||||
@interface RTCEAGLVideoView () <GLKViewDelegate>
|
||||
// |videoFrame| is set when we receive a frame from a worker thread and is read
|
||||
// from the display link callback so atomicity is required.
|
||||
@property(atomic, strong) RTCVideoFrame *videoFrame;
|
||||
@property(nonatomic, readonly) GLKView *glkView;
|
||||
@property(nonatomic, readonly) RTCOpenGLVideoRenderer *glRenderer;
|
||||
@end
|
||||
|
||||
@implementation RTCEAGLVideoView {
|
||||
RTCDisplayLinkTimer *_timer;
|
||||
// This flag should only be set and read on the main thread (e.g. by
|
||||
// setNeedsDisplay)
|
||||
BOOL _isDirty;
|
||||
}
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize videoFrame = _videoFrame;
|
||||
@synthesize glkView = _glkView;
|
||||
@synthesize glRenderer = _glRenderer;
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
if (self = [super initWithFrame:frame]) {
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
|
||||
if (self = [super initWithCoder:aDecoder]) {
|
||||
[self configure];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)configure {
|
||||
EAGLContext *glContext =
|
||||
[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
||||
if (!glContext) {
|
||||
glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
}
|
||||
_glRenderer = [[RTCOpenGLVideoRenderer alloc] initWithContext:glContext];
|
||||
|
||||
// GLKView manages a framebuffer for us.
|
||||
_glkView = [[GLKView alloc] initWithFrame:CGRectZero
|
||||
context:glContext];
|
||||
_glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
|
||||
_glkView.drawableDepthFormat = GLKViewDrawableDepthFormatNone;
|
||||
_glkView.drawableStencilFormat = GLKViewDrawableStencilFormatNone;
|
||||
_glkView.drawableMultisample = GLKViewDrawableMultisampleNone;
|
||||
_glkView.delegate = self;
|
||||
_glkView.layer.masksToBounds = YES;
|
||||
_glkView.enableSetNeedsDisplay = NO;
|
||||
[self addSubview:_glkView];
|
||||
|
||||
// Listen to application state in order to clean up OpenGL before app goes
|
||||
// away.
|
||||
NSNotificationCenter *notificationCenter =
|
||||
[NSNotificationCenter defaultCenter];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(willResignActive)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
[notificationCenter addObserver:self
|
||||
selector:@selector(didBecomeActive)
|
||||
name:UIApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
// Frames are received on a separate thread, so we poll for current frame
|
||||
// using a refresh rate proportional to screen refresh frequency. This
|
||||
// occurs on the main thread.
|
||||
__weak RTCEAGLVideoView *weakSelf = self;
|
||||
_timer = [[RTCDisplayLinkTimer alloc] initWithTimerHandler:^{
|
||||
RTCEAGLVideoView *strongSelf = weakSelf;
|
||||
[strongSelf displayLinkTimerDidFire];
|
||||
}];
|
||||
[self setupGL];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
UIApplicationState appState =
|
||||
[UIApplication sharedApplication].applicationState;
|
||||
if (appState == UIApplicationStateActive) {
|
||||
[self teardownGL];
|
||||
}
|
||||
[_timer invalidate];
|
||||
}
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)setNeedsDisplay {
|
||||
[super setNeedsDisplay];
|
||||
_isDirty = YES;
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplayInRect:(CGRect)rect {
|
||||
[super setNeedsDisplayInRect:rect];
|
||||
_isDirty = YES;
|
||||
}
|
||||
|
||||
- (void)layoutSubviews {
|
||||
[super layoutSubviews];
|
||||
_glkView.frame = self.bounds;
|
||||
}
|
||||
|
||||
#pragma mark - GLKViewDelegate
|
||||
|
||||
// This method is called when the GLKView's content is dirty and needs to be
|
||||
// redrawn. This occurs on main thread.
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
|
||||
// The renderer will draw the frame to the framebuffer corresponding to the
|
||||
// one used by |view|.
|
||||
[_glRenderer drawFrame:self.videoFrame];
|
||||
}
|
||||
|
||||
#pragma mark - RTCVideoRenderer
|
||||
|
||||
// These methods may be called on non-main thread.
|
||||
- (void)setSize:(CGSize)size {
|
||||
__weak RTCEAGLVideoView *weakSelf = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
RTCEAGLVideoView *strongSelf = weakSelf;
|
||||
[strongSelf.delegate videoView:strongSelf didChangeVideoSize:size];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)renderFrame:(RTCVideoFrame *)frame {
|
||||
self.videoFrame = frame;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)displayLinkTimerDidFire {
|
||||
// Don't render unless video frame have changed or the view content
|
||||
// has explicitly been marked dirty.
|
||||
if (!_isDirty && _glRenderer.lastDrawnFrame == self.videoFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Always reset isDirty at this point, even if -[GLKView display]
|
||||
// won't be called in the case the drawable size is empty.
|
||||
_isDirty = NO;
|
||||
|
||||
// Only call -[GLKView display] if the drawable size is
|
||||
// non-empty. Calling display will make the GLKView setup its
|
||||
// render buffer if necessary, but that will fail with error
|
||||
// GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT if size is empty.
|
||||
if (self.bounds.size.width > 0 && self.bounds.size.height > 0) {
|
||||
[_glkView display];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupGL {
|
||||
self.videoFrame = nil;
|
||||
[_glRenderer setupGL];
|
||||
_timer.isPaused = NO;
|
||||
}
|
||||
|
||||
- (void)teardownGL {
|
||||
self.videoFrame = nil;
|
||||
_timer.isPaused = YES;
|
||||
[_glkView deleteDrawable];
|
||||
[_glRenderer teardownGL];
|
||||
}
|
||||
|
||||
- (void)didBecomeActive {
|
||||
[self setupGL];
|
||||
}
|
||||
|
||||
- (void)willResignActive {
|
||||
[self teardownGL];
|
||||
}
|
||||
|
||||
@end
|
||||
36
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate+Private.h
Normal file
36
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate+Private.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCIceCandidate.h"
|
||||
|
||||
#include "talk/app/webrtc/jsep.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCIceCandidate ()
|
||||
|
||||
/**
|
||||
* The native IceCandidateInterface representation of this RTCIceCandidate
|
||||
* object. This is needed to pass to the underlying C++ APIs.
|
||||
*/
|
||||
@property(nonatomic, readonly)
|
||||
rtc::scoped_ptr<webrtc::IceCandidateInterface> nativeCandidate;
|
||||
|
||||
/**
|
||||
* Initialize an RTCIceCandidate from a native IceCandidateInterface. No
|
||||
* ownership is taken of the native candidate.
|
||||
*/
|
||||
- (instancetype)initWithNativeCandidate:
|
||||
(webrtc::IceCandidateInterface *)candidate;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
44
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate.h
Normal file
44
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCIceCandidate : NSObject
|
||||
|
||||
/**
|
||||
* If present, the identifier of the "media stream identification" for the media
|
||||
* component this candidate is associated with.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSString *sdpMid;
|
||||
|
||||
/**
|
||||
* The index (starting at zero) of the media description this candidate is
|
||||
* associated with in the SDP.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSInteger sdpMLineIndex;
|
||||
|
||||
/** The SDP string for this candidate. */
|
||||
@property(nonatomic, readonly) NSString *sdp;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
* Initialize an RTCIceCandidate from SDP.
|
||||
*/
|
||||
- (instancetype)initWithSdp:(NSString *)sdp
|
||||
sdpMLineIndex:(NSInteger)sdpMLineIndex
|
||||
sdpMid:(nullable NSString *)sdpMid
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
70
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate.mm
Normal file
70
media/webrtc/trunk/webrtc/api/objc/RTCIceCandidate.mm
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCIceCandidate.h"
|
||||
|
||||
#import "webrtc/api/objc/RTCIceCandidate+Private.h"
|
||||
#import "webrtc/base/objc/NSString+StdString.h"
|
||||
#import "webrtc/base/objc/RTCLogging.h"
|
||||
|
||||
@implementation RTCIceCandidate
|
||||
|
||||
@synthesize sdpMid = _sdpMid;
|
||||
@synthesize sdpMLineIndex = _sdpMLineIndex;
|
||||
@synthesize sdp = _sdp;
|
||||
|
||||
- (instancetype)initWithSdp:(NSString *)sdp
|
||||
sdpMLineIndex:(NSInteger)sdpMLineIndex
|
||||
sdpMid:(NSString *)sdpMid {
|
||||
NSParameterAssert(sdp.length);
|
||||
if (self = [super init]) {
|
||||
_sdpMid = [sdpMid copy];
|
||||
_sdpMLineIndex = sdpMLineIndex;
|
||||
_sdp = [sdp copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"RTCIceCandidate:\n%@\n%ld\n%@",
|
||||
_sdpMid,
|
||||
(long)_sdpMLineIndex,
|
||||
_sdp];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (instancetype)initWithNativeCandidate:
|
||||
(webrtc::IceCandidateInterface *)candidate {
|
||||
NSParameterAssert(candidate);
|
||||
std::string sdp;
|
||||
candidate->ToString(&sdp);
|
||||
|
||||
return [self initWithSdp:[NSString stringForStdString:sdp]
|
||||
sdpMLineIndex:candidate->sdp_mline_index()
|
||||
sdpMid:[NSString stringForStdString:candidate->sdp_mid()]];
|
||||
}
|
||||
|
||||
- (rtc::scoped_ptr<webrtc::IceCandidateInterface>)nativeCandidate {
|
||||
webrtc::SdpParseError error;
|
||||
|
||||
webrtc::IceCandidateInterface *candidate = webrtc::CreateIceCandidate(
|
||||
_sdpMid.stdString, _sdpMLineIndex, _sdp.stdString, &error);
|
||||
|
||||
if (!candidate) {
|
||||
RTCLog(@"Failed to create ICE candidate: %s\nline: %s",
|
||||
error.description.c_str(),
|
||||
error.line.c_str());
|
||||
}
|
||||
|
||||
return rtc::scoped_ptr<webrtc::IceCandidateInterface>(candidate);
|
||||
}
|
||||
|
||||
@end
|
||||
28
media/webrtc/trunk/webrtc/api/objc/RTCIceServer+Private.h
Normal file
28
media/webrtc/trunk/webrtc/api/objc/RTCIceServer+Private.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCIceServer.h"
|
||||
|
||||
#include "talk/app/webrtc/peerconnectioninterface.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCIceServer ()
|
||||
|
||||
/**
|
||||
* IceServer struct representation of this RTCIceServer object's data.
|
||||
* This is needed to pass to the underlying C++ APIs.
|
||||
*/
|
||||
@property(nonatomic, readonly)
|
||||
webrtc::PeerConnectionInterface::IceServer iceServer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
42
media/webrtc/trunk/webrtc/api/objc/RTCIceServer.h
Normal file
42
media/webrtc/trunk/webrtc/api/objc/RTCIceServer.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCIceServer : NSObject
|
||||
|
||||
/** URI(s) for this server represented as NSStrings. */
|
||||
@property(nonatomic, copy, readonly) NSArray<NSString *> *urlStrings;
|
||||
|
||||
/** Username to use if this RTCIceServer object is a TURN server. */
|
||||
@property(nonatomic, copy, readonly, nullable) NSString *username;
|
||||
|
||||
/** Credential to use if this RTCIceServer object is a TURN server. */
|
||||
@property(nonatomic, copy, readonly, nullable) NSString *credential;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Convenience initializer for a server with no authentication (e.g. STUN). */
|
||||
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings;
|
||||
|
||||
/**
|
||||
* Initialize an RTCIceServer with its associated URLs, optional username,
|
||||
* optional credential, and credentialType.
|
||||
*/
|
||||
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
|
||||
username:(nullable NSString *)username
|
||||
credential:(nullable NSString *)credential
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
64
media/webrtc/trunk/webrtc/api/objc/RTCIceServer.mm
Normal file
64
media/webrtc/trunk/webrtc/api/objc/RTCIceServer.mm
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCIceServer.h"
|
||||
|
||||
#import "webrtc/api/objc/RTCIceServer+Private.h"
|
||||
#import "webrtc/base/objc/NSString+StdString.h"
|
||||
|
||||
@implementation RTCIceServer
|
||||
|
||||
@synthesize urlStrings = _urlStrings;
|
||||
@synthesize username = _username;
|
||||
@synthesize credential = _credential;
|
||||
|
||||
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings {
|
||||
NSParameterAssert(urlStrings.count);
|
||||
return [self initWithURLStrings:urlStrings
|
||||
username:nil
|
||||
credential:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithURLStrings:(NSArray<NSString *> *)urlStrings
|
||||
username:(NSString *)username
|
||||
credential:(NSString *)credential {
|
||||
NSParameterAssert(urlStrings.count);
|
||||
if (self = [super init]) {
|
||||
_urlStrings = [[NSArray alloc] initWithArray:urlStrings copyItems:YES];
|
||||
_username = [username copy];
|
||||
_credential = [credential copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"RTCIceServer:\n%@\n%@\n%@",
|
||||
_urlStrings,
|
||||
_username,
|
||||
_credential];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (webrtc::PeerConnectionInterface::IceServer)iceServer {
|
||||
__block webrtc::PeerConnectionInterface::IceServer iceServer;
|
||||
|
||||
iceServer.username = [NSString stdStringForString:_username];
|
||||
iceServer.password = [NSString stdStringForString:_credential];
|
||||
|
||||
[_urlStrings enumerateObjectsUsingBlock:^(NSString *url,
|
||||
NSUInteger idx,
|
||||
BOOL *stop) {
|
||||
iceServer.urls.push_back(url.stdString);
|
||||
}];
|
||||
return iceServer;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCMediaConstraints.h"
|
||||
|
||||
#include "talk/app/webrtc/mediaconstraintsinterface.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class MediaConstraints : public MediaConstraintsInterface {
|
||||
public:
|
||||
virtual ~MediaConstraints();
|
||||
MediaConstraints();
|
||||
MediaConstraints(
|
||||
const MediaConstraintsInterface::Constraints& mandatory,
|
||||
const MediaConstraintsInterface::Constraints& optional);
|
||||
virtual const Constraints& GetMandatory() const;
|
||||
virtual const Constraints& GetOptional() const;
|
||||
|
||||
private:
|
||||
MediaConstraintsInterface::Constraints mandatory_;
|
||||
MediaConstraintsInterface::Constraints optional_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaConstraints ()
|
||||
|
||||
/**
|
||||
* A MediaConstraints representation of this RTCMediaConstraints object. This is
|
||||
* needed to pass to the underlying C++ APIs.
|
||||
*/
|
||||
- (rtc::scoped_ptr<webrtc::MediaConstraints>)nativeConstraints;
|
||||
|
||||
/** Return a native Constraints object representing these constraints */
|
||||
+ (webrtc::MediaConstraintsInterface::Constraints)
|
||||
nativeConstraintsForConstraints:
|
||||
(NSDictionary<NSString *, NSString *> *)constraints;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
28
media/webrtc/trunk/webrtc/api/objc/RTCMediaConstraints.h
Normal file
28
media/webrtc/trunk/webrtc/api/objc/RTCMediaConstraints.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaConstraints : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
/** Initialize with mandatory and/or optional constraints. */
|
||||
- (instancetype)initWithMandatoryConstraints:
|
||||
(nullable NSDictionary<NSString *, NSString *> *)mandatory
|
||||
optionalConstraints:
|
||||
(nullable NSDictionary<NSString *, NSString *> *)optional
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
92
media/webrtc/trunk/webrtc/api/objc/RTCMediaConstraints.mm
Normal file
92
media/webrtc/trunk/webrtc/api/objc/RTCMediaConstraints.mm
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCMediaConstraints.h"
|
||||
|
||||
#import "webrtc/api/objc/RTCMediaConstraints+Private.h"
|
||||
#import "webrtc/base/objc/NSString+StdString.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
MediaConstraints::~MediaConstraints() {}
|
||||
|
||||
MediaConstraints::MediaConstraints() {}
|
||||
|
||||
MediaConstraints::MediaConstraints(
|
||||
const MediaConstraintsInterface::Constraints& mandatory,
|
||||
const MediaConstraintsInterface::Constraints& optional)
|
||||
: mandatory_(mandatory), optional_(optional) {}
|
||||
|
||||
const MediaConstraintsInterface::Constraints&
|
||||
MediaConstraints::GetMandatory() const {
|
||||
return mandatory_;
|
||||
}
|
||||
|
||||
const MediaConstraintsInterface::Constraints&
|
||||
MediaConstraints::GetOptional() const {
|
||||
return optional_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@implementation RTCMediaConstraints {
|
||||
NSDictionary<NSString *, NSString *> *_mandatory;
|
||||
NSDictionary<NSString *, NSString *> *_optional;
|
||||
}
|
||||
|
||||
- (instancetype)initWithMandatoryConstraints:
|
||||
(NSDictionary<NSString *, NSString *> *)mandatory
|
||||
optionalConstraints:
|
||||
(NSDictionary<NSString *, NSString *> *)optional {
|
||||
if (self = [super init]) {
|
||||
_mandatory = [[NSDictionary alloc] initWithDictionary:mandatory
|
||||
copyItems:YES];
|
||||
_optional = [[NSDictionary alloc] initWithDictionary:optional
|
||||
copyItems:YES];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"RTCMediaConstraints:\n%@\n%@",
|
||||
_mandatory,
|
||||
_optional];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (rtc::scoped_ptr<webrtc::MediaConstraints>)nativeConstraints {
|
||||
webrtc::MediaConstraintsInterface::Constraints mandatory =
|
||||
[[self class] nativeConstraintsForConstraints:_mandatory];
|
||||
webrtc::MediaConstraintsInterface::Constraints optional =
|
||||
[[self class] nativeConstraintsForConstraints:_optional];
|
||||
|
||||
webrtc::MediaConstraints *nativeConstraints =
|
||||
new webrtc::MediaConstraints(mandatory, optional);
|
||||
return rtc::scoped_ptr<webrtc::MediaConstraints>(nativeConstraints);
|
||||
}
|
||||
|
||||
+ (webrtc::MediaConstraintsInterface::Constraints)
|
||||
nativeConstraintsForConstraints:
|
||||
(NSDictionary<NSString *, NSString *> *)constraints {
|
||||
webrtc::MediaConstraintsInterface::Constraints nativeConstraints;
|
||||
for (NSString *key in constraints) {
|
||||
NSAssert([key isKindOfClass:[NSString class]],
|
||||
@"%@ is not an NSString.", key);
|
||||
NSAssert([constraints[key] isKindOfClass:[NSString class]],
|
||||
@"%@ is not an NSString.", constraints[key]);
|
||||
nativeConstraints.push_back(webrtc::MediaConstraintsInterface::Constraint(
|
||||
key.stdString, constraints[key].stdString));
|
||||
}
|
||||
return nativeConstraints;
|
||||
}
|
||||
|
||||
@end
|
||||
41
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource+Private.h
Normal file
41
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource+Private.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCMediaSource.h"
|
||||
|
||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaSource ()
|
||||
|
||||
/**
|
||||
* The MediaSourceInterface object passed to this RTCMediaSource during
|
||||
* construction.
|
||||
*/
|
||||
@property(nonatomic, readonly)
|
||||
rtc::scoped_refptr<webrtc::MediaSourceInterface> nativeMediaSource;
|
||||
|
||||
/** Initialize an RTCMediaSource from a native MediaSourceInterface. */
|
||||
- (instancetype)initWithNativeMediaSource:
|
||||
(rtc::scoped_refptr<webrtc::MediaSourceInterface>)nativeMediaSource
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (webrtc::MediaSourceInterface::SourceState)nativeSourceStateForState:
|
||||
(RTCSourceState)state;
|
||||
|
||||
+ (RTCSourceState)sourceStateForNativeState:
|
||||
(webrtc::MediaSourceInterface::SourceState)nativeState;
|
||||
|
||||
+ (NSString *)stringForState:(RTCSourceState)state;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
31
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource.h
Normal file
31
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, RTCSourceState) {
|
||||
RTCSourceStateInitializing,
|
||||
RTCSourceStateLive,
|
||||
RTCSourceStateEnded,
|
||||
RTCSourceStateMuted,
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaSource : NSObject
|
||||
|
||||
/** The current state of the RTCMediaSource. */
|
||||
@property(nonatomic, readonly) RTCSourceState state;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
84
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource.mm
Normal file
84
media/webrtc/trunk/webrtc/api/objc/RTCMediaSource.mm
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCMediaSource.h"
|
||||
|
||||
#import "webrtc/api/objc/RTCMediaSource+Private.h"
|
||||
|
||||
@implementation RTCMediaSource {
|
||||
rtc::scoped_refptr<webrtc::MediaSourceInterface> _nativeMediaSource;
|
||||
}
|
||||
|
||||
- (RTCSourceState)state {
|
||||
return [[self class] sourceStateForNativeState:_nativeMediaSource->state()];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"RTCMediaSource:\n%@",
|
||||
[[self class] stringForState:self.state]];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (rtc::scoped_refptr<webrtc::MediaSourceInterface>)nativeMediaSource {
|
||||
return _nativeMediaSource;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNativeMediaSource:
|
||||
(rtc::scoped_refptr<webrtc::MediaSourceInterface>)nativeMediaSource {
|
||||
NSParameterAssert(nativeMediaSource);
|
||||
if (self = [super init]) {
|
||||
_nativeMediaSource = nativeMediaSource;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (webrtc::MediaSourceInterface::SourceState)nativeSourceStateForState:
|
||||
(RTCSourceState)state {
|
||||
switch (state) {
|
||||
case RTCSourceStateInitializing:
|
||||
return webrtc::MediaSourceInterface::kInitializing;
|
||||
case RTCSourceStateLive:
|
||||
return webrtc::MediaSourceInterface::kLive;
|
||||
case RTCSourceStateEnded:
|
||||
return webrtc::MediaSourceInterface::kEnded;
|
||||
case RTCSourceStateMuted:
|
||||
return webrtc::MediaSourceInterface::kMuted;
|
||||
}
|
||||
}
|
||||
|
||||
+ (RTCSourceState)sourceStateForNativeState:
|
||||
(webrtc::MediaSourceInterface::SourceState)nativeState {
|
||||
switch (nativeState) {
|
||||
case webrtc::MediaSourceInterface::kInitializing:
|
||||
return RTCSourceStateInitializing;
|
||||
case webrtc::MediaSourceInterface::kLive:
|
||||
return RTCSourceStateLive;
|
||||
case webrtc::MediaSourceInterface::kEnded:
|
||||
return RTCSourceStateEnded;
|
||||
case webrtc::MediaSourceInterface::kMuted:
|
||||
return RTCSourceStateMuted;
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)stringForState:(RTCSourceState)state {
|
||||
switch (state) {
|
||||
case RTCSourceStateInitializing:
|
||||
return @"Initializing";
|
||||
case RTCSourceStateLive:
|
||||
return @"Live";
|
||||
case RTCSourceStateEnded:
|
||||
return @"Ended";
|
||||
case RTCSourceStateMuted:
|
||||
return @"Muted";
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import "RTCMediaStreamTrack.h"
|
||||
|
||||
#include "talk/app/webrtc/mediastreaminterface.h"
|
||||
#include "webrtc/base/scoped_ptr.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaStreamTrack ()
|
||||
|
||||
/**
|
||||
* The native MediaStreamTrackInterface representation of this
|
||||
* RTCMediaStreamTrack object. This is needed to pass to the underlying C++
|
||||
* APIs.
|
||||
*/
|
||||
@property(nonatomic, readonly)
|
||||
rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> nativeTrack;
|
||||
|
||||
/**
|
||||
* Initialize an RTCMediaStreamTrack from a native MediaStreamTrackInterface.
|
||||
*/
|
||||
- (instancetype)initWithNativeTrack:
|
||||
(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface>)nativeTrack
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
+ (webrtc::MediaStreamTrackInterface::TrackState)nativeTrackStateForState:
|
||||
(RTCMediaStreamTrackState)state;
|
||||
|
||||
+ (RTCMediaStreamTrackState)trackStateForNativeState:
|
||||
(webrtc::MediaStreamTrackInterface::TrackState)nativeState;
|
||||
|
||||
+ (NSString *)stringForState:(RTCMediaStreamTrackState)state;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
47
media/webrtc/trunk/webrtc/api/objc/RTCMediaStreamTrack.h
Normal file
47
media/webrtc/trunk/webrtc/api/objc/RTCMediaStreamTrack.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Represents the state of the track. This exposes the same states in C++,
|
||||
* which include two more states than are in the W3C spec.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, RTCMediaStreamTrackState) {
|
||||
RTCMediaStreamTrackStateInitializing,
|
||||
RTCMediaStreamTrackStateLive,
|
||||
RTCMediaStreamTrackStateEnded,
|
||||
RTCMediaStreamTrackStateFailed,
|
||||
};
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RTCMediaStreamTrack : NSObject
|
||||
|
||||
/**
|
||||
* The kind of track. For example, "audio" if this track represents an audio
|
||||
* track and "video" if this track represents a video track.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSString *kind;
|
||||
|
||||
/** An identifier string. */
|
||||
@property(nonatomic, readonly) NSString *trackId;
|
||||
|
||||
/** The enabled state of the track. */
|
||||
@property(nonatomic) BOOL isEnabled;
|
||||
|
||||
/** The state of the track. */
|
||||
@property(nonatomic, readonly) RTCMediaStreamTrackState readyState;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue