[WebRTC] updated to upstream branch 49 and related.

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

View file

@ -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',

View file

@ -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;

View file

@ -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() {}

View file

@ -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

View file

@ -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",

View file

@ -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);
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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,

View file

@ -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

View file

@ -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();
}
}

View file

@ -10,8 +10,8 @@
namespace mozilla {
class GmpVideoCodec {
public:
static VideoEncoder* CreateEncoder();
static VideoDecoder* CreateDecoder();
static WebrtcVideoEncoder* CreateEncoder();
static WebrtcVideoDecoder* CreateDecoder();
};
}

View file

@ -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();

View file

@ -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);
};
}

View file

@ -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

View file

@ -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() {}

View file

@ -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();

View file

@ -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

View file

@ -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

View file

@ -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),

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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());

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -9,7 +9,7 @@
#include "MediaPipelineFilter.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/common_types.h"
namespace mozilla {

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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;

View file

@ -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 {

View file

@ -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";

View file

@ -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"