mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1091242 - Part 2: New JSEP handling code. See https://github.com/unicorn-wg/gecko-dev/tree/multistream_rebase for more history. r=ehugg, r=jesup
This commit is contained in:
parent
b942d9f5bb
commit
a49b1b7a20
620
media/webrtc/signaling/src/jsep/JsepCodecDescription.h
Normal file
620
media/webrtc/signaling/src/jsep/JsepCodecDescription.h
Normal file
@ -0,0 +1,620 @@
|
||||
/* 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 _JSEPCODECDESCRIPTION_H_
|
||||
#define _JSEPCODECDESCRIPTION_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#define JSEP_CODEC_CLONE(T) \
|
||||
virtual JsepCodecDescription* Clone() const MOZ_OVERRIDE \
|
||||
{ \
|
||||
return new T(*this); \
|
||||
}
|
||||
|
||||
// A single entry in our list of known codecs.
|
||||
struct JsepCodecDescription {
|
||||
JsepCodecDescription(mozilla::SdpMediaSection::MediaType type,
|
||||
const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint32_t clock,
|
||||
uint32_t channels,
|
||||
bool enabled)
|
||||
: mType(type),
|
||||
mDefaultPt(defaultPt),
|
||||
mName(name),
|
||||
mClock(clock),
|
||||
mChannels(channels),
|
||||
mEnabled(enabled)
|
||||
{
|
||||
}
|
||||
virtual ~JsepCodecDescription() {}
|
||||
|
||||
virtual JsepCodecDescription* Clone() const = 0;
|
||||
virtual void AddFmtps(SdpFmtpAttributeList& fmtp) const = 0;
|
||||
virtual void AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const = 0;
|
||||
virtual bool LoadFmtps(const SdpFmtpAttributeList::Parameters& params) = 0;
|
||||
virtual bool LoadRtcpFbs(
|
||||
const SdpRtcpFbAttributeList::Feedback& feedback) = 0;
|
||||
|
||||
static bool
|
||||
GetPtAsInt(const std::string& ptString, uint16_t* ptOutparam)
|
||||
{
|
||||
char* end;
|
||||
unsigned long pt = strtoul(ptString.c_str(), &end, 10);
|
||||
size_t length = static_cast<size_t>(end - ptString.c_str());
|
||||
if ((pt > UINT16_MAX) || (length != ptString.size())) {
|
||||
return false;
|
||||
}
|
||||
*ptOutparam = pt;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GetPtAsInt(uint16_t* ptOutparam) const
|
||||
{
|
||||
return GetPtAsInt(mDefaultPt, ptOutparam);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Matches(const std::string& fmt, const SdpMediaSection& remoteMsection) const
|
||||
{
|
||||
auto& attrs = remoteMsection.GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kRtpmapAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList& rtpmap = attrs.GetRtpmap();
|
||||
if (!rtpmap.HasEntry(fmt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SdpRtpmapAttributeList::Rtpmap& entry = rtpmap.GetEntry(fmt);
|
||||
|
||||
if (mType == remoteMsection.GetMediaType()
|
||||
&& (mName == entry.name)
|
||||
&& (mClock == entry.clock)
|
||||
&& (mChannels == entry.channels)) {
|
||||
return ParametersMatch(FindParameters(entry.pt, remoteMsection));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ParametersMatch(const SdpFmtpAttributeList::Parameters* fmtp) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static const SdpFmtpAttributeList::Parameters*
|
||||
FindParameters(const std::string& pt,
|
||||
const mozilla::SdpMediaSection& remoteMsection)
|
||||
{
|
||||
const SdpAttributeList& attrs = remoteMsection.GetAttributeList();
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
const SdpFmtpAttributeList& fmtps = attrs.GetFmtp();
|
||||
for (auto i = fmtps.mFmtps.begin(); i != fmtps.mFmtps.end(); ++i) {
|
||||
if (i->format == pt && i->parameters) {
|
||||
return i->parameters.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual JsepCodecDescription*
|
||||
MakeNegotiatedCodec(const mozilla::SdpMediaSection& remoteMsection,
|
||||
const std::string& pt,
|
||||
bool sending) const
|
||||
{
|
||||
UniquePtr<JsepCodecDescription> negotiated(Clone());
|
||||
negotiated->mDefaultPt = pt;
|
||||
|
||||
const SdpAttributeList& attrs = remoteMsection.GetAttributeList();
|
||||
|
||||
if (sending) {
|
||||
auto* parameters = FindParameters(negotiated->mDefaultPt, remoteMsection);
|
||||
if (parameters) {
|
||||
if (!negotiated->LoadFmtps(*parameters)) {
|
||||
// Remote parameters were invalid
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If a receive track, we need to pay attention to remote end's rtcp-fb
|
||||
if (attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
auto& rtcpfbs = attrs.GetRtcpFb().mFeedbacks;
|
||||
for (auto i = rtcpfbs.begin(); i != rtcpfbs.end(); ++i) {
|
||||
if (i->pt == negotiated->mDefaultPt) {
|
||||
if (!negotiated->LoadRtcpFbs(*i)) {
|
||||
// Remote parameters were invalid
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return negotiated.release();
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddToMediaSection(SdpMediaSection& msection) const
|
||||
{
|
||||
if (mEnabled && msection.GetMediaType() == mType) {
|
||||
if (mType == SdpMediaSection::kApplication) {
|
||||
// Hack: using mChannels for number of streams
|
||||
msection.AddDataChannel(mDefaultPt, mName, mChannels);
|
||||
} else {
|
||||
msection.AddCodec(mDefaultPt, mName, mClock, mChannels);
|
||||
}
|
||||
AddFmtpsToMSection(msection);
|
||||
AddRtcpFbsToMSection(msection);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtpsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
SdpAttributeList& attrs = msection.GetAttributeList();
|
||||
|
||||
UniquePtr<SdpFmtpAttributeList> fmtps;
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kFmtpAttribute)) {
|
||||
fmtps.reset(new SdpFmtpAttributeList(attrs.GetFmtp()));
|
||||
} else {
|
||||
fmtps.reset(new SdpFmtpAttributeList);
|
||||
}
|
||||
|
||||
AddFmtps(*fmtps);
|
||||
|
||||
if (!fmtps->mFmtps.empty()) {
|
||||
attrs.SetAttribute(fmtps.release());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbsToMSection(SdpMediaSection& msection) const
|
||||
{
|
||||
SdpAttributeList& attrs = msection.GetAttributeList();
|
||||
|
||||
UniquePtr<SdpRtcpFbAttributeList> rtcpfbs;
|
||||
|
||||
if (attrs.HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
|
||||
rtcpfbs.reset(new SdpRtcpFbAttributeList(attrs.GetRtcpFb()));
|
||||
} else {
|
||||
rtcpfbs.reset(new SdpRtcpFbAttributeList);
|
||||
}
|
||||
|
||||
AddRtcpFbs(*rtcpfbs);
|
||||
|
||||
if (!rtcpfbs->mFeedbacks.empty()) {
|
||||
attrs.SetAttribute(rtcpfbs.release());
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::SdpMediaSection::MediaType mType;
|
||||
std::string mDefaultPt;
|
||||
std::string mName;
|
||||
uint32_t mClock;
|
||||
uint32_t mChannels;
|
||||
bool mEnabled;
|
||||
};
|
||||
|
||||
struct JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
JsepAudioCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint32_t clock,
|
||||
uint32_t channels,
|
||||
uint32_t packetSize,
|
||||
uint32_t bitRate,
|
||||
bool enabled = true)
|
||||
: JsepCodecDescription(mozilla::SdpMediaSection::kAudio, defaultPt, name,
|
||||
clock, channels, enabled),
|
||||
mPacketSize(packetSize),
|
||||
mBitrate(bitRate)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const MOZ_OVERRIDE
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const MOZ_OVERRIDE
|
||||
{
|
||||
// TODO: Do we want to add anything?
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadFmtps(const SdpFmtpAttributeList::Parameters& params) MOZ_OVERRIDE
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadRtcpFbs(const SdpRtcpFbAttributeList::Feedback& feedback) MOZ_OVERRIDE
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
JSEP_CODEC_CLONE(JsepAudioCodecDescription)
|
||||
|
||||
uint32_t mPacketSize;
|
||||
uint32_t mBitrate;
|
||||
};
|
||||
|
||||
struct JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
JsepVideoCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint32_t clock,
|
||||
bool enabled = true)
|
||||
: JsepCodecDescription(mozilla::SdpMediaSection::kVideo, defaultPt, name,
|
||||
clock, 0, enabled),
|
||||
mMaxFs(0),
|
||||
mMaxFr(0),
|
||||
mPacketizationMode(0),
|
||||
mMaxMbps(0),
|
||||
mMaxCpb(0),
|
||||
mMaxDpb(0),
|
||||
mMaxBr(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const MOZ_OVERRIDE
|
||||
{
|
||||
if (mName == "H264") {
|
||||
UniquePtr<SdpFmtpAttributeList::H264Parameters> params =
|
||||
MakeUnique<SdpFmtpAttributeList::H264Parameters>();
|
||||
|
||||
params->packetization_mode = mPacketizationMode;
|
||||
// Hard-coded, may need to change someday?
|
||||
params->level_asymmetry_allowed = true;
|
||||
params->profile_level_id = mProfileLevelId;
|
||||
params->max_mbps = mMaxMbps;
|
||||
params->max_fs = mMaxFs;
|
||||
params->max_cpb = mMaxCpb;
|
||||
params->max_dpb = mMaxDpb;
|
||||
params->max_br = mMaxBr;
|
||||
strncpy(params->sprop_parameter_sets,
|
||||
mSpropParameterSets.c_str(),
|
||||
sizeof(params->sprop_parameter_sets) - 1);
|
||||
fmtp.PushEntry(mDefaultPt, "", mozilla::Move(params));
|
||||
} else if (mName == "VP8") {
|
||||
UniquePtr<SdpFmtpAttributeList::VP8Parameters> params =
|
||||
MakeUnique<SdpFmtpAttributeList::VP8Parameters>();
|
||||
|
||||
params->max_fs = mMaxFs;
|
||||
params->max_fr = mMaxFr;
|
||||
fmtp.PushEntry(mDefaultPt, "", mozilla::Move(params));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const MOZ_OVERRIDE
|
||||
{
|
||||
// Just hard code for now
|
||||
rtcpfb.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kNack);
|
||||
rtcpfb.PushEntry(
|
||||
mDefaultPt, SdpRtcpFbAttributeList::kNack, SdpRtcpFbAttributeList::pli);
|
||||
rtcpfb.PushEntry(
|
||||
mDefaultPt, SdpRtcpFbAttributeList::kCcm, SdpRtcpFbAttributeList::fir);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadFmtps(const SdpFmtpAttributeList::Parameters& params) MOZ_OVERRIDE
|
||||
{
|
||||
switch (params.codec_type) {
|
||||
case SdpRtpmapAttributeList::kH264:
|
||||
LoadH264Parameters(params);
|
||||
break;
|
||||
case SdpRtpmapAttributeList::kVP8:
|
||||
LoadVP8Parameters(params);
|
||||
break;
|
||||
case SdpRtpmapAttributeList::kVP9:
|
||||
case SdpRtpmapAttributeList::kiLBC:
|
||||
case SdpRtpmapAttributeList::kiSAC:
|
||||
case SdpRtpmapAttributeList::kOpus:
|
||||
case SdpRtpmapAttributeList::kG722:
|
||||
case SdpRtpmapAttributeList::kPCMU:
|
||||
case SdpRtpmapAttributeList::kPCMA:
|
||||
case SdpRtpmapAttributeList::kOtherCodec:
|
||||
MOZ_ASSERT(false, "Invalid codec type for video");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadRtcpFbs(const SdpRtcpFbAttributeList::Feedback& feedback) MOZ_OVERRIDE
|
||||
{
|
||||
switch (feedback.type) {
|
||||
case SdpRtcpFbAttributeList::kAck:
|
||||
mAckFbTypes.push_back(feedback.parameter);
|
||||
break;
|
||||
case SdpRtcpFbAttributeList::kCcm:
|
||||
mCcmFbTypes.push_back(feedback.parameter);
|
||||
break;
|
||||
case SdpRtcpFbAttributeList::kNack:
|
||||
mNackFbTypes.push_back(feedback.parameter);
|
||||
break;
|
||||
case SdpRtcpFbAttributeList::kApp:
|
||||
case SdpRtcpFbAttributeList::kTrrInt:
|
||||
// We don't support these, ignore.
|
||||
{}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
enum Subprofile {
|
||||
kH264ConstrainedBaseline,
|
||||
kH264Baseline,
|
||||
kH264Main,
|
||||
kH264Extended,
|
||||
kH264High,
|
||||
kH264High10,
|
||||
kH264High42,
|
||||
kH264High44,
|
||||
kH264High10I,
|
||||
kH264High42I,
|
||||
kH264High44I,
|
||||
kH264CALVC44,
|
||||
kH264UnknownSubprofile
|
||||
};
|
||||
|
||||
static Subprofile
|
||||
GetSubprofile(uint32_t profileLevelId)
|
||||
{
|
||||
// Based on Table 5 from RFC 6184:
|
||||
// Profile profile_idc profile-iop
|
||||
// (hexadecimal) (binary)
|
||||
|
||||
// CB 42 (B) x1xx0000
|
||||
// same as: 4D (M) 1xxx0000
|
||||
// same as: 58 (E) 11xx0000
|
||||
// B 42 (B) x0xx0000
|
||||
// same as: 58 (E) 10xx0000
|
||||
// M 4D (M) 0x0x0000
|
||||
// E 58 00xx0000
|
||||
// H 64 00000000
|
||||
// H10 6E 00000000
|
||||
// H42 7A 00000000
|
||||
// H44 F4 00000000
|
||||
// H10I 6E 00010000
|
||||
// H42I 7A 00010000
|
||||
// H44I F4 00010000
|
||||
// C44I 2C 00010000
|
||||
|
||||
if ((profileLevelId & 0xFF4F00) == 0x424000) {
|
||||
// 01001111 (mask, 0x4F)
|
||||
// x1xx0000 (from table)
|
||||
// 01000000 (expected value, 0x40)
|
||||
return kH264ConstrainedBaseline;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFF8F00) == 0x4D8000) {
|
||||
// 10001111 (mask, 0x8F)
|
||||
// 1xxx0000 (from table)
|
||||
// 10000000 (expected value, 0x80)
|
||||
return kH264ConstrainedBaseline;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFCF00) == 0x58C000) {
|
||||
// 11001111 (mask, 0xCF)
|
||||
// 11xx0000 (from table)
|
||||
// 11000000 (expected value, 0xC0)
|
||||
return kH264ConstrainedBaseline;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFF4F00) == 0x420000) {
|
||||
// 01001111 (mask, 0x4F)
|
||||
// x0xx0000 (from table)
|
||||
// 00000000 (expected value)
|
||||
return kH264Baseline;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFCF00) == 0x588000) {
|
||||
// 11001111 (mask, 0xCF)
|
||||
// 10xx0000 (from table)
|
||||
// 10000000 (expected value, 0x80)
|
||||
return kH264Baseline;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFAF00) == 0x4D0000) {
|
||||
// 10101111 (mask, 0xAF)
|
||||
// 0x0x0000 (from table)
|
||||
// 00000000 (expected value)
|
||||
return kH264Main;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFF0000) == 0x580000) {
|
||||
// 11001111 (mask, 0xCF)
|
||||
// 00xx0000 (from table)
|
||||
// 00000000 (expected value)
|
||||
return kH264Extended;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x640000) {
|
||||
return kH264High;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x6E0000) {
|
||||
return kH264High10;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x7A0000) {
|
||||
return kH264High42;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0xF40000) {
|
||||
return kH264High44;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x6E1000) {
|
||||
return kH264High10I;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x7A1000) {
|
||||
return kH264High42I;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0xF41000) {
|
||||
return kH264High44I;
|
||||
}
|
||||
|
||||
if ((profileLevelId & 0xFFFF00) == 0x2C1000) {
|
||||
return kH264CALVC44;
|
||||
}
|
||||
|
||||
return kH264UnknownSubprofile;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ParametersMatch(const SdpFmtpAttributeList::Parameters* fmtp) const
|
||||
MOZ_OVERRIDE
|
||||
{
|
||||
if (mName == "H264") {
|
||||
if (!fmtp) {
|
||||
// No fmtp means that we cannot assume level asymmetry is allowed,
|
||||
// and since we have no way of knowing the profile-level-id, we can't
|
||||
// say that we match.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* h264Params =
|
||||
static_cast<const SdpFmtpAttributeList::H264Parameters*>(fmtp);
|
||||
|
||||
if (!h264Params->level_asymmetry_allowed) {
|
||||
if (GetSubprofile(h264Params->profile_level_id) !=
|
||||
GetSubprofile(mProfileLevelId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (h264Params->packetization_mode != mPacketizationMode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LoadH264Parameters(const SdpFmtpAttributeList::Parameters& params)
|
||||
{
|
||||
const SdpFmtpAttributeList::H264Parameters& h264Params =
|
||||
static_cast<const SdpFmtpAttributeList::H264Parameters&>(params);
|
||||
|
||||
mMaxFs = h264Params.max_fs;
|
||||
mProfileLevelId = h264Params.profile_level_id;
|
||||
mPacketizationMode = h264Params.packetization_mode;
|
||||
mMaxMbps = h264Params.max_mbps;
|
||||
mMaxCpb = h264Params.max_cpb;
|
||||
mMaxDpb = h264Params.max_dpb;
|
||||
mMaxBr = h264Params.max_br;
|
||||
mSpropParameterSets = h264Params.sprop_parameter_sets;
|
||||
}
|
||||
|
||||
void
|
||||
LoadVP8Parameters(const SdpFmtpAttributeList::Parameters& params)
|
||||
{
|
||||
const SdpFmtpAttributeList::VP8Parameters& vp8Params =
|
||||
static_cast<const SdpFmtpAttributeList::VP8Parameters&>(params);
|
||||
|
||||
mMaxFs = vp8Params.max_fs;
|
||||
mMaxFr = vp8Params.max_fr;
|
||||
}
|
||||
|
||||
JSEP_CODEC_CLONE(JsepVideoCodecDescription)
|
||||
|
||||
std::vector<std::string> mAckFbTypes;
|
||||
std::vector<std::string> mNackFbTypes;
|
||||
std::vector<std::string> mCcmFbTypes;
|
||||
|
||||
uint32_t mMaxFs;
|
||||
|
||||
// H264-specific stuff
|
||||
uint32_t mProfileLevelId;
|
||||
uint32_t mMaxFr;
|
||||
uint32_t mPacketizationMode;
|
||||
uint32_t mMaxMbps;
|
||||
uint32_t mMaxCpb;
|
||||
uint32_t mMaxDpb;
|
||||
uint32_t mMaxBr;
|
||||
std::string mSpropParameterSets;
|
||||
};
|
||||
|
||||
struct JsepApplicationCodecDescription : public JsepCodecDescription {
|
||||
JsepApplicationCodecDescription(const std::string& defaultPt,
|
||||
const std::string& name,
|
||||
uint16_t channels,
|
||||
bool enabled = true)
|
||||
: JsepCodecDescription(mozilla::SdpMediaSection::kApplication, defaultPt,
|
||||
name, 0, channels, enabled)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddFmtps(SdpFmtpAttributeList& fmtp) const MOZ_OVERRIDE
|
||||
{
|
||||
// TODO: Is there anything to do here?
|
||||
}
|
||||
|
||||
virtual void
|
||||
AddRtcpFbs(SdpRtcpFbAttributeList& rtcpfb) const MOZ_OVERRIDE
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadFmtps(const SdpFmtpAttributeList::Parameters& params) MOZ_OVERRIDE
|
||||
{
|
||||
// TODO: Is there anything to do here?
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
LoadRtcpFbs(const SdpRtcpFbAttributeList::Feedback& feedback) MOZ_OVERRIDE
|
||||
{
|
||||
// Nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
JSEP_CODEC_CLONE(JsepApplicationCodecDescription)
|
||||
|
||||
// Override, uses sctpmap instead of rtpmap
|
||||
virtual bool
|
||||
Matches(const std::string& fmt,
|
||||
const SdpMediaSection& remoteMsection) const MOZ_OVERRIDE
|
||||
{
|
||||
auto& attrs = remoteMsection.GetAttributeList();
|
||||
if (!attrs.HasAttribute(SdpAttribute::kSctpmapAttribute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList& sctpmap = attrs.GetSctpmap();
|
||||
if (!sctpmap.HasEntry(fmt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SdpSctpmapAttributeList::Sctpmap& entry = sctpmap.GetEntry(fmt);
|
||||
|
||||
if (mType == remoteMsection.GetMediaType() && (mName == entry.name)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
164
media/webrtc/signaling/src/jsep/JsepSession.h
Normal file
164
media/webrtc/signaling/src/jsep/JsepSession.h
Normal file
@ -0,0 +1,164 @@
|
||||
/* 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 _JSEPSESSION_H_
|
||||
#define _JSEPSESSION_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsError.h"
|
||||
|
||||
#include "signaling/src/jsep/JsepTransport.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Forward declarations
|
||||
struct JsepCodecDescription;
|
||||
class JsepTrack;
|
||||
struct JsepTrackPair;
|
||||
|
||||
enum JsepSignalingState {
|
||||
kJsepStateStable,
|
||||
kJsepStateHaveLocalOffer,
|
||||
kJsepStateHaveRemoteOffer,
|
||||
kJsepStateHaveLocalPranswer,
|
||||
kJsepStateHaveRemotePranswer,
|
||||
kJsepStateClosed
|
||||
};
|
||||
|
||||
enum JsepSdpType {
|
||||
kJsepSdpOffer,
|
||||
kJsepSdpAnswer,
|
||||
kJsepSdpPranswer,
|
||||
};
|
||||
|
||||
struct JsepOAOptions {};
|
||||
struct JsepOfferOptions : public JsepOAOptions {
|
||||
Maybe<size_t> mOfferToReceiveAudio;
|
||||
Maybe<size_t> mOfferToReceiveVideo;
|
||||
Maybe<bool> mDontOfferDataChannel;
|
||||
};
|
||||
struct JsepAnswerOptions : public JsepOAOptions {};
|
||||
|
||||
class JsepSession
|
||||
{
|
||||
public:
|
||||
explicit JsepSession(const std::string& name)
|
||||
: mName(name), mState(kJsepStateStable)
|
||||
{
|
||||
}
|
||||
virtual ~JsepSession() {}
|
||||
|
||||
virtual nsresult Init() = 0;
|
||||
|
||||
// Accessors for basic properties.
|
||||
virtual const std::string&
|
||||
GetName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
virtual JsepSignalingState
|
||||
GetState() const
|
||||
{
|
||||
return mState;
|
||||
}
|
||||
|
||||
// Set up the ICE And DTLS data.
|
||||
virtual nsresult SetIceCredentials(const std::string& ufrag,
|
||||
const std::string& pwd) = 0;
|
||||
virtual bool RemoteIsIceLite() const = 0;
|
||||
virtual std::vector<std::string> GetIceOptions() const = 0;
|
||||
|
||||
virtual nsresult AddDtlsFingerprint(const std::string& algorithm,
|
||||
const std::vector<uint8_t>& value) = 0;
|
||||
|
||||
virtual nsresult AddAudioRtpExtension(const std::string& extensionName) = 0;
|
||||
virtual nsresult AddVideoRtpExtension(const std::string& extensionName) = 0;
|
||||
|
||||
// Kinda gross to be locking down the data structure type like this, but
|
||||
// returning by value is problematic due to the lack of stl move semantics in
|
||||
// our build config, since we can't use UniquePtr in the container. The
|
||||
// alternative is writing a raft of accessor functions that allow arbitrary
|
||||
// manipulation (which will be unwieldy), or allowing functors to be injected
|
||||
// that manipulate the data structure (still pretty unwieldy).
|
||||
virtual std::vector<JsepCodecDescription*>& Codecs() = 0;
|
||||
|
||||
// Manage tracks. We take shared ownership of any track.
|
||||
virtual nsresult AddTrack(const RefPtr<JsepTrack>& track) = 0;
|
||||
virtual nsresult RemoveTrack(size_t track_index) = 0;
|
||||
virtual nsresult ReplaceTrack(size_t track_index,
|
||||
const RefPtr<JsepTrack>& track) = 0;
|
||||
|
||||
virtual size_t GetLocalTrackCount() const = 0;
|
||||
virtual nsresult GetLocalTrack(size_t index,
|
||||
RefPtr<JsepTrack>* track) const = 0;
|
||||
|
||||
virtual size_t GetRemoteTrackCount() const = 0;
|
||||
virtual nsresult GetRemoteTrack(size_t index,
|
||||
RefPtr<JsepTrack>* track) const = 0;
|
||||
|
||||
// Access the negotiated track pairs.
|
||||
virtual size_t GetNegotiatedTrackPairCount() const = 0;
|
||||
virtual nsresult GetNegotiatedTrackPair(size_t index,
|
||||
const JsepTrackPair** pair) const = 0;
|
||||
|
||||
// Access transports.
|
||||
virtual size_t GetTransportCount() const = 0;
|
||||
virtual nsresult GetTransport(size_t index,
|
||||
RefPtr<JsepTransport>* transport) const = 0;
|
||||
|
||||
// Basic JSEP operations.
|
||||
virtual nsresult CreateOffer(const JsepOfferOptions& options,
|
||||
std::string* offer) = 0;
|
||||
virtual nsresult CreateAnswer(const JsepAnswerOptions& options,
|
||||
std::string* answer) = 0;
|
||||
virtual std::string GetLocalDescription() const = 0;
|
||||
virtual std::string GetRemoteDescription() const = 0;
|
||||
virtual nsresult SetLocalDescription(JsepSdpType type,
|
||||
const std::string& sdp) = 0;
|
||||
virtual nsresult SetRemoteDescription(JsepSdpType type,
|
||||
const std::string& sdp) = 0;
|
||||
virtual nsresult AddRemoteIceCandidate(const std::string& candidate,
|
||||
const std::string& mid,
|
||||
uint16_t level) = 0;
|
||||
virtual nsresult AddLocalIceCandidate(const std::string& candidate,
|
||||
const std::string& mid,
|
||||
uint16_t level) = 0;
|
||||
virtual nsresult EndOfLocalCandidates(const std::string& defaultCandidateAddr,
|
||||
uint16_t defaultCandidatePort,
|
||||
uint16_t level) = 0;
|
||||
virtual nsresult Close() = 0;
|
||||
|
||||
// ICE controlling or controlled
|
||||
virtual bool IsIceControlling() const = 0;
|
||||
|
||||
virtual const std::string
|
||||
GetLastError() const
|
||||
{
|
||||
return "Error";
|
||||
}
|
||||
|
||||
static const char*
|
||||
GetStateStr(JsepSignalingState state)
|
||||
{
|
||||
static const char* states[] = { "stable", "have-local-offer",
|
||||
"have-remote-offer", "have-local-pranswer",
|
||||
"have-remote-pranswer", "closed" };
|
||||
|
||||
return states[state];
|
||||
}
|
||||
|
||||
protected:
|
||||
const std::string mName;
|
||||
JsepSignalingState mState;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
1655
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
Normal file
1655
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
302
media/webrtc/signaling/src/jsep/JsepSessionImpl.h
Normal file
302
media/webrtc/signaling/src/jsep/JsepSessionImpl.h
Normal file
@ -0,0 +1,302 @@
|
||||
/* 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 _JSEPSESSIONIMPL_H_
|
||||
#define _JSEPSESSIONIMPL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "signaling/src/jsep/JsepCodecDescription.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepSession.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/jsep/JsepTrackImpl.h"
|
||||
#include "signaling/src/sdp/SipccSdpParser.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class JsepUuidGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~JsepUuidGenerator() {}
|
||||
virtual bool Generate(std::string* id) = 0;
|
||||
};
|
||||
|
||||
class JsepSessionImpl : public JsepSession
|
||||
{
|
||||
public:
|
||||
JsepSessionImpl(const std::string& name, UniquePtr<JsepUuidGenerator> uuidgen)
|
||||
: JsepSession(name),
|
||||
mIsOfferer(false),
|
||||
mIceControlling(false),
|
||||
mRemoteIsIceLite(false),
|
||||
mSessionId(0),
|
||||
mSessionVersion(0),
|
||||
mUuidGen(Move(uuidgen))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~JsepSessionImpl();
|
||||
|
||||
// Implement JsepSession methods.
|
||||
virtual nsresult Init() MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AddTrack(const RefPtr<JsepTrack>& track) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult
|
||||
RemoveTrack(size_t trackIndex) MOZ_OVERRIDE
|
||||
{
|
||||
mLastError.clear();
|
||||
MOZ_CRASH(); // Stub
|
||||
}
|
||||
|
||||
virtual nsresult SetIceCredentials(const std::string& ufrag,
|
||||
const std::string& pwd) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RemoteIsIceLite() const MOZ_OVERRIDE
|
||||
{
|
||||
return mRemoteIsIceLite;
|
||||
}
|
||||
|
||||
virtual std::vector<std::string>
|
||||
GetIceOptions() const MOZ_OVERRIDE
|
||||
{
|
||||
return mIceOptions;
|
||||
}
|
||||
|
||||
virtual nsresult AddDtlsFingerprint(const std::string& algorithm,
|
||||
const std::vector<uint8_t>& value) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AddAudioRtpExtension(
|
||||
const std::string& extensionName) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AddVideoRtpExtension(
|
||||
const std::string& extensionName) MOZ_OVERRIDE;
|
||||
|
||||
virtual std::vector<JsepCodecDescription*>&
|
||||
Codecs() MOZ_OVERRIDE
|
||||
{
|
||||
return mCodecs;
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
ReplaceTrack(size_t trackIndex, const RefPtr<JsepTrack>& track) MOZ_OVERRIDE
|
||||
{
|
||||
mLastError.clear();
|
||||
MOZ_CRASH(); // Stub
|
||||
}
|
||||
|
||||
virtual size_t
|
||||
GetLocalTrackCount() const MOZ_OVERRIDE
|
||||
{
|
||||
return mLocalTracks.size();
|
||||
}
|
||||
|
||||
virtual nsresult GetLocalTrack(size_t index,
|
||||
RefPtr<JsepTrack>* track) const MOZ_OVERRIDE;
|
||||
|
||||
virtual size_t
|
||||
GetRemoteTrackCount() const MOZ_OVERRIDE
|
||||
{
|
||||
return mRemoteTracks.size();
|
||||
}
|
||||
|
||||
virtual nsresult GetRemoteTrack(size_t index,
|
||||
RefPtr<JsepTrack>* track) const MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult CreateOffer(const JsepOfferOptions& options,
|
||||
std::string* offer) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult CreateAnswer(const JsepAnswerOptions& options,
|
||||
std::string* answer) MOZ_OVERRIDE;
|
||||
|
||||
virtual std::string GetLocalDescription() const MOZ_OVERRIDE;
|
||||
|
||||
virtual std::string GetRemoteDescription() const MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult SetLocalDescription(JsepSdpType type,
|
||||
const std::string& sdp) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult SetRemoteDescription(JsepSdpType type,
|
||||
const std::string& sdp) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AddRemoteIceCandidate(const std::string& candidate,
|
||||
const std::string& mid,
|
||||
uint16_t level) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult AddLocalIceCandidate(const std::string& candidate,
|
||||
const std::string& mid,
|
||||
uint16_t level) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult EndOfLocalCandidates(const std::string& defaultCandidateAddr,
|
||||
uint16_t defaultCandidatePort,
|
||||
uint16_t level) MOZ_OVERRIDE;
|
||||
|
||||
virtual nsresult Close() MOZ_OVERRIDE;
|
||||
|
||||
virtual const std::string GetLastError() const MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
IsIceControlling() const
|
||||
{
|
||||
return mIceControlling;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
IsOfferer() const
|
||||
{
|
||||
return mIsOfferer;
|
||||
}
|
||||
|
||||
// Access transports.
|
||||
virtual size_t
|
||||
GetTransportCount() const MOZ_OVERRIDE
|
||||
{
|
||||
return mTransports.size();
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
GetTransport(size_t index,
|
||||
RefPtr<JsepTransport>* transport) const MOZ_OVERRIDE
|
||||
{
|
||||
if (index >= mTransports.size())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*transport = mTransports[index];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Access the negotiated track pairs.
|
||||
virtual size_t
|
||||
GetNegotiatedTrackPairCount() const MOZ_OVERRIDE
|
||||
{
|
||||
return mNegotiatedTrackPairs.size();
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
GetNegotiatedTrackPair(size_t index, const JsepTrackPair** pair) const
|
||||
{
|
||||
if (index >= mNegotiatedTrackPairs.size())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*pair = &mNegotiatedTrackPairs[index];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
struct JsepDtlsFingerprint {
|
||||
std::string mAlgorithm;
|
||||
std::vector<uint8_t> mValue;
|
||||
};
|
||||
|
||||
struct JsepSendingTrack {
|
||||
RefPtr<JsepTrack> mTrack;
|
||||
Maybe<size_t> mAssignedMLine;
|
||||
};
|
||||
|
||||
struct JsepReceivingTrack {
|
||||
RefPtr<JsepTrack> mTrack;
|
||||
Maybe<size_t> mAssignedMLine;
|
||||
};
|
||||
|
||||
// Non-const so it can set mLastError
|
||||
nsresult CreateGenericSDP(UniquePtr<Sdp>* sdp);
|
||||
void AddCodecs(SdpMediaSection* msection) const;
|
||||
void AddExtmap(SdpMediaSection* msection) const;
|
||||
JsepCodecDescription* FindMatchingCodec(
|
||||
const std::string& pt,
|
||||
const SdpMediaSection& msection) const;
|
||||
const std::vector<SdpExtmapAttributeList::Extmap>* GetRtpExtensions(
|
||||
SdpMediaSection::MediaType type) const;
|
||||
void AddCommonCodecs(const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection);
|
||||
void AddCommonExtmaps(const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection);
|
||||
void SetupDefaultCodecs();
|
||||
void SetupDefaultRtpExtensions();
|
||||
void SetState(JsepSignalingState state);
|
||||
// Non-const so it can set mLastError
|
||||
nsresult ParseSdp(const std::string& sdp, UniquePtr<Sdp>* parsedp);
|
||||
nsresult SetLocalDescriptionOffer(UniquePtr<Sdp> offer);
|
||||
nsresult SetLocalDescriptionAnswer(JsepSdpType type, UniquePtr<Sdp> answer);
|
||||
nsresult SetRemoteDescriptionOffer(UniquePtr<Sdp> offer);
|
||||
nsresult SetRemoteDescriptionAnswer(JsepSdpType type, UniquePtr<Sdp> answer);
|
||||
nsresult ValidateLocalDescription(const Sdp& description);
|
||||
nsresult SetRemoteTracksFromDescription(const Sdp& remoteDescription);
|
||||
// Non-const because we use our Uuid generator
|
||||
nsresult CreateReceivingTrack(size_t mline, const SdpMediaSection& msection);
|
||||
nsresult HandleNegotiatedSession(const UniquePtr<Sdp>& local,
|
||||
const UniquePtr<Sdp>& remote);
|
||||
nsresult DetermineSendingDirection(SdpDirectionAttribute::Direction offer,
|
||||
SdpDirectionAttribute::Direction answer,
|
||||
bool* sending, bool* receiving);
|
||||
nsresult AddTransportAttributes(SdpMediaSection* msection,
|
||||
SdpSetupAttribute::Role dtlsRole);
|
||||
// Non-const so it can assign m-line index to tracks
|
||||
nsresult AddOfferMSectionsByType(SdpMediaSection::MediaType type,
|
||||
Maybe<size_t> offerToReceive,
|
||||
Sdp* sdp);
|
||||
nsresult CreateOfferMSection(SdpMediaSection::MediaType type,
|
||||
SdpDirectionAttribute::Direction direction,
|
||||
SdpMediaSection::Protocol proto,
|
||||
Sdp* sdp);
|
||||
nsresult CreateAnswerMSection(const JsepAnswerOptions& options,
|
||||
size_t mlineIndex,
|
||||
const SdpMediaSection& remoteMsection,
|
||||
SdpMediaSection* msection,
|
||||
Sdp* sdp);
|
||||
nsresult DetermineAnswererSetupRole(const SdpMediaSection& remoteMsection,
|
||||
SdpSetupAttribute::Role* rolep);
|
||||
nsresult NegotiateTrack(const SdpMediaSection& remoteMsection,
|
||||
const SdpMediaSection& localMsection,
|
||||
JsepTrack::Direction,
|
||||
RefPtr<JsepTrack>* track);
|
||||
|
||||
nsresult CreateTransport(const SdpMediaSection& msection,
|
||||
RefPtr<JsepTransport>* transport);
|
||||
|
||||
nsresult SetupTransport(const SdpAttributeList& remote,
|
||||
const SdpAttributeList& answer,
|
||||
const RefPtr<JsepTransport>& transport);
|
||||
|
||||
nsresult AddCandidateToSdp(Sdp* sdp,
|
||||
const std::string& candidate,
|
||||
const std::string& mid,
|
||||
uint16_t level);
|
||||
|
||||
std::vector<JsepSendingTrack> mLocalTracks;
|
||||
std::vector<JsepReceivingTrack> mRemoteTracks;
|
||||
std::vector<RefPtr<JsepTransport> > mTransports;
|
||||
std::vector<JsepTrackPair> mNegotiatedTrackPairs;
|
||||
|
||||
bool mIsOfferer;
|
||||
bool mIceControlling;
|
||||
std::string mIceUfrag;
|
||||
std::string mIcePwd;
|
||||
bool mRemoteIsIceLite;
|
||||
std::vector<std::string> mIceOptions;
|
||||
std::vector<JsepDtlsFingerprint> mDtlsFingerprints;
|
||||
uint64_t mSessionId;
|
||||
uint64_t mSessionVersion;
|
||||
std::vector<SdpExtmapAttributeList::Extmap> mAudioRtpExtensions;
|
||||
std::vector<SdpExtmapAttributeList::Extmap> mVideoRtpExtensions;
|
||||
UniquePtr<JsepUuidGenerator> mUuidGen;
|
||||
std::string mDefaultRemoteStreamId;
|
||||
UniquePtr<Sdp> mGeneratedLocalDescription; // Created but not set.
|
||||
UniquePtr<Sdp> mCurrentLocalDescription;
|
||||
UniquePtr<Sdp> mCurrentRemoteDescription;
|
||||
UniquePtr<Sdp> mPendingLocalDescription;
|
||||
UniquePtr<Sdp> mPendingRemoteDescription;
|
||||
std::vector<JsepCodecDescription*> mCodecs;
|
||||
std::string mLastError;
|
||||
SipccSdpParser mParser;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
120
media/webrtc/signaling/src/jsep/JsepTrack.h
Normal file
120
media/webrtc/signaling/src/jsep/JsepTrack.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* 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 _JSEPTRACK_H_
|
||||
#define _JSEPTRACK_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/UniquePtr.h>
|
||||
#include <mozilla/Maybe.h>
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsError.h"
|
||||
|
||||
#include "signaling/src/jsep/JsepTransport.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Forward reference.
|
||||
struct JsepCodecDescription;
|
||||
|
||||
class JsepTrackNegotiatedDetails
|
||||
{
|
||||
public:
|
||||
virtual ~JsepTrackNegotiatedDetails() {}
|
||||
|
||||
virtual mozilla::SdpMediaSection::Protocol GetProtocol() const = 0;
|
||||
virtual Maybe<std::string> GetBandwidth(const std::string& type) const = 0;
|
||||
virtual size_t GetCodecCount() const = 0;
|
||||
virtual nsresult GetCodec(size_t index,
|
||||
const JsepCodecDescription** config) const = 0;
|
||||
virtual const SdpExtmapAttributeList::Extmap* GetExt(
|
||||
const std::string& ext_name) const = 0;
|
||||
};
|
||||
|
||||
class JsepTrack
|
||||
{
|
||||
public:
|
||||
enum Direction { kJsepTrackSending, kJsepTrackReceiving };
|
||||
|
||||
JsepTrack(mozilla::SdpMediaSection::MediaType type,
|
||||
const std::string& streamid,
|
||||
const std::string& trackid,
|
||||
Direction direction = kJsepTrackSending)
|
||||
: mType(type),
|
||||
mStreamId(streamid),
|
||||
mTrackId(trackid),
|
||||
mDirection(direction)
|
||||
{
|
||||
}
|
||||
|
||||
virtual mozilla::SdpMediaSection::MediaType
|
||||
GetMediaType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
virtual const std::string&
|
||||
GetStreamId() const
|
||||
{
|
||||
return mStreamId;
|
||||
}
|
||||
|
||||
virtual const std::string&
|
||||
GetTrackId() const
|
||||
{
|
||||
return mTrackId;
|
||||
}
|
||||
|
||||
virtual Direction
|
||||
GetDirection() const
|
||||
{
|
||||
return mDirection;
|
||||
}
|
||||
|
||||
// This will be set when negotiation is carried out.
|
||||
virtual const JsepTrackNegotiatedDetails*
|
||||
GetNegotiatedDetails() const
|
||||
{
|
||||
if (mNegotiatedDetails) {
|
||||
return mNegotiatedDetails.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is for JsepSession's use.
|
||||
virtual void
|
||||
SetNegotiatedDetails(UniquePtr<JsepTrackNegotiatedDetails> details)
|
||||
{
|
||||
mNegotiatedDetails = Move(details);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTrack);
|
||||
|
||||
protected:
|
||||
virtual ~JsepTrack() {}
|
||||
|
||||
private:
|
||||
const mozilla::SdpMediaSection::MediaType mType;
|
||||
const std::string mStreamId;
|
||||
const std::string mTrackId;
|
||||
const Direction mDirection;
|
||||
UniquePtr<JsepTrackNegotiatedDetails> mNegotiatedDetails;
|
||||
};
|
||||
|
||||
// Need a better name for this.
|
||||
struct JsepTrackPair {
|
||||
size_t mLevel;
|
||||
RefPtr<JsepTrack> mSending;
|
||||
RefPtr<JsepTrack> mReceiving;
|
||||
RefPtr<JsepTransport> mRtpTransport;
|
||||
RefPtr<JsepTransport> mRtcpTransport;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
79
media/webrtc/signaling/src/jsep/JsepTrackImpl.h
Normal file
79
media/webrtc/signaling/src/jsep/JsepTrackImpl.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* 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 _JSEPTRACKIMPL_H_
|
||||
#define _JSEPTRACKIMPL_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/UniquePtr.h>
|
||||
|
||||
#include "signaling/src/jsep/JsepCodecDescription.h"
|
||||
#include "signaling/src/jsep/JsepTrack.h"
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/SdpMediaSection.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class JsepTrackNegotiatedDetailsImpl : public JsepTrackNegotiatedDetails
|
||||
{
|
||||
public:
|
||||
virtual ~JsepTrackNegotiatedDetailsImpl()
|
||||
{
|
||||
for (auto c = mCodecs.begin(); c != mCodecs.end(); ++c) {
|
||||
delete *c;
|
||||
}
|
||||
}
|
||||
|
||||
// Implement JsepTrackNegotiatedDetails.
|
||||
virtual mozilla::SdpMediaSection::Protocol
|
||||
GetProtocol() const MOZ_OVERRIDE
|
||||
{
|
||||
return mProtocol;
|
||||
}
|
||||
virtual Maybe<std::string>
|
||||
GetBandwidth(const std::string& type) const MOZ_OVERRIDE
|
||||
{
|
||||
return mBandwidth;
|
||||
}
|
||||
virtual size_t
|
||||
GetCodecCount() const MOZ_OVERRIDE
|
||||
{
|
||||
return mCodecs.size();
|
||||
}
|
||||
virtual nsresult
|
||||
GetCodec(size_t index, const JsepCodecDescription** config) const MOZ_OVERRIDE
|
||||
{
|
||||
if (index >= mCodecs.size()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
*config = mCodecs[index];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual const SdpExtmapAttributeList::Extmap*
|
||||
GetExt(const std::string& ext_name) const MOZ_OVERRIDE
|
||||
{
|
||||
auto it = mExtmap.find(ext_name);
|
||||
if (it != mExtmap.end()) {
|
||||
return &it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Make these friends to JsepSessionImpl to avoid having to
|
||||
// write setters.
|
||||
friend class JsepSessionImpl;
|
||||
|
||||
mozilla::SdpMediaSection::Protocol mProtocol;
|
||||
Maybe<std::string> mBandwidth;
|
||||
std::vector<JsepCodecDescription*> mCodecs;
|
||||
std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
117
media/webrtc/signaling/src/jsep/JsepTransport.h
Normal file
117
media/webrtc/signaling/src/jsep/JsepTransport.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* 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 _JSEPTRANSPORT_H_
|
||||
#define _JSEPTRANSPORT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/UniquePtr.h>
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "signaling/src/sdp/SdpAttribute.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class JsepDtlsTransport
|
||||
{
|
||||
public:
|
||||
JsepDtlsTransport() : mRole(kJsepDtlsInvalidRole) {}
|
||||
|
||||
virtual ~JsepDtlsTransport() {}
|
||||
|
||||
enum Role {
|
||||
kJsepDtlsClient,
|
||||
kJsepDtlsServer,
|
||||
kJsepDtlsInvalidRole
|
||||
};
|
||||
|
||||
virtual const SdpFingerprintAttributeList&
|
||||
GetFingerprints() const
|
||||
{
|
||||
return mFingerprints;
|
||||
}
|
||||
|
||||
virtual Role
|
||||
GetRole() const
|
||||
{
|
||||
return mRole;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class JsepSessionImpl;
|
||||
|
||||
SdpFingerprintAttributeList mFingerprints;
|
||||
Role mRole;
|
||||
};
|
||||
|
||||
class JsepIceTransport
|
||||
{
|
||||
public:
|
||||
JsepIceTransport() {}
|
||||
|
||||
virtual ~JsepIceTransport() {}
|
||||
|
||||
const std::string&
|
||||
GetUfrag() const
|
||||
{
|
||||
return mUfrag;
|
||||
}
|
||||
const std::string&
|
||||
GetPassword() const
|
||||
{
|
||||
return mPwd;
|
||||
}
|
||||
const std::vector<std::string>&
|
||||
GetCandidates() const
|
||||
{
|
||||
return mCandidates;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class JsepSessionImpl;
|
||||
|
||||
std::string mUfrag;
|
||||
std::string mPwd;
|
||||
std::vector<std::string> mCandidates;
|
||||
};
|
||||
|
||||
class JsepTransport
|
||||
{
|
||||
public:
|
||||
JsepTransport(const std::string& id, size_t components)
|
||||
: mTransportId(id), mState(kJsepTransportOffered), mComponents(components)
|
||||
{
|
||||
}
|
||||
|
||||
enum State {
|
||||
kJsepTransportOffered,
|
||||
kJsepTransportAccepted,
|
||||
kJsepTransportClosed
|
||||
};
|
||||
|
||||
// Unique identifier for this transport within this call. Group?
|
||||
std::string mTransportId;
|
||||
|
||||
// State.
|
||||
State mState;
|
||||
|
||||
// ICE stuff.
|
||||
UniquePtr<JsepIceTransport> mIce;
|
||||
UniquePtr<JsepDtlsTransport> mDtls;
|
||||
|
||||
// Number of required components.
|
||||
size_t mComponents;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(JsepTransport);
|
||||
|
||||
protected:
|
||||
~JsepTransport() {}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
1130
media/webrtc/signaling/test/jsep_session_unittest.cpp
Normal file
1130
media/webrtc/signaling/test/jsep_session_unittest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user