LCOV - code coverage report
Current view: top level - media/webrtc/signaling/src/jsep - JsepCodecDescription.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 333 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 51 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #ifndef _JSEPCODECDESCRIPTION_H_
       6             : #define _JSEPCODECDESCRIPTION_H_
       7             : 
       8             : #include <string>
       9             : #include "signaling/src/sdp/SdpMediaSection.h"
      10             : #include "signaling/src/sdp/SdpHelper.h"
      11             : #include "nsCRT.h"
      12             : #include "mozilla/net/DataChannelProtocol.h"
      13             : 
      14             : namespace mozilla {
      15             : 
      16             : #define JSEP_CODEC_CLONE(T)                                                    \
      17             :   virtual JsepCodecDescription* Clone() const override                         \
      18             :   {                                                                            \
      19             :     return new T(*this);                                                       \
      20             :   }
      21             : 
      22             : // A single entry in our list of known codecs.
      23           0 : class JsepCodecDescription {
      24             :  public:
      25           0 :   JsepCodecDescription(mozilla::SdpMediaSection::MediaType type,
      26             :                        const std::string& defaultPt,
      27             :                        const std::string& name,
      28             :                        uint32_t clock,
      29             :                        uint32_t channels,
      30             :                        bool enabled)
      31           0 :       : mType(type),
      32             :         mDefaultPt(defaultPt),
      33             :         mName(name),
      34             :         mClock(clock),
      35             :         mChannels(channels),
      36             :         mEnabled(enabled),
      37             :         mStronglyPreferred(false),
      38           0 :         mDirection(sdp::kSend)
      39             :   {
      40           0 :   }
      41           0 :   virtual ~JsepCodecDescription() {}
      42             : 
      43             :   virtual JsepCodecDescription* Clone() const = 0;
      44             : 
      45             :   bool
      46           0 :   GetPtAsInt(uint16_t* ptOutparam) const
      47             :   {
      48           0 :     return SdpHelper::GetPtAsInt(mDefaultPt, ptOutparam);
      49             :   }
      50             : 
      51             :   virtual bool
      52           0 :   Matches(const std::string& fmt, const SdpMediaSection& remoteMsection) const
      53             :   {
      54             :     // note: fmt here is remote fmt (to go with remoteMsection)
      55           0 :     if (mType != remoteMsection.GetMediaType()) {
      56           0 :       return false;
      57             :     }
      58             : 
      59           0 :     const SdpRtpmapAttributeList::Rtpmap* entry(remoteMsection.FindRtpmap(fmt));
      60             : 
      61           0 :     if (entry) {
      62           0 :       if (!nsCRT::strcasecmp(mName.c_str(), entry->name.c_str())
      63           0 :           && (mClock == entry->clock)
      64           0 :           && (mChannels == entry->channels)) {
      65           0 :         return ParametersMatch(fmt, remoteMsection);
      66             :       }
      67           0 :     } else if (!fmt.compare("9") && mName == "G722") {
      68           0 :       return true;
      69           0 :     } else if (!fmt.compare("0") && mName == "PCMU") {
      70           0 :       return true;
      71           0 :     } else if (!fmt.compare("8") && mName == "PCMA") {
      72           0 :       return true;
      73             :     }
      74           0 :     return false;
      75             :   }
      76             : 
      77             :   virtual bool
      78           0 :   ParametersMatch(const std::string& fmt,
      79             :                   const SdpMediaSection& remoteMsection) const
      80             :   {
      81           0 :     return true;
      82             :   }
      83             : 
      84             :   virtual bool
      85           0 :   Negotiate(const std::string& pt, const SdpMediaSection& remoteMsection)
      86             :   {
      87           0 :     mDefaultPt = pt;
      88           0 :     return true;
      89             :   }
      90             : 
      91             :   virtual void
      92           0 :   AddToMediaSection(SdpMediaSection& msection) const
      93             :   {
      94           0 :     if (mEnabled && msection.GetMediaType() == mType) {
      95             :       // Both send and recv codec will have the same pt, so don't add twice
      96           0 :       if (!msection.HasFormat(mDefaultPt)) {
      97           0 :         msection.AddCodec(mDefaultPt, mName, mClock, mChannels);
      98             :       }
      99             : 
     100           0 :       AddParametersToMSection(msection);
     101             :     }
     102           0 :   }
     103             : 
     104           0 :   virtual void AddParametersToMSection(SdpMediaSection& msection) const {}
     105             : 
     106             :   mozilla::SdpMediaSection::MediaType mType;
     107             :   std::string mDefaultPt;
     108             :   std::string mName;
     109             :   uint32_t mClock;
     110             :   uint32_t mChannels;
     111             :   bool mEnabled;
     112             :   bool mStronglyPreferred;
     113             :   sdp::Direction mDirection;
     114             :   // Will hold constraints from both fmtp and rid
     115             :   EncodingConstraints mConstraints;
     116             : };
     117             : 
     118           0 : class JsepAudioCodecDescription : public JsepCodecDescription {
     119             :  public:
     120           0 :   JsepAudioCodecDescription(const std::string& defaultPt,
     121             :                             const std::string& name,
     122             :                             uint32_t clock,
     123             :                             uint32_t channels,
     124             :                             uint32_t packetSize,
     125             :                             uint32_t bitRate,
     126             :                             bool enabled = true)
     127           0 :       : JsepCodecDescription(mozilla::SdpMediaSection::kAudio, defaultPt, name,
     128             :                              clock, channels, enabled),
     129             :         mPacketSize(packetSize),
     130             :         mBitrate(bitRate),
     131             :         mMaxPlaybackRate(0),
     132             :         mForceMono(false),
     133             :         mFECEnabled(false),
     134           0 :         mDtmfEnabled(false)
     135             :   {
     136           0 :   }
     137             : 
     138           0 :   JSEP_CODEC_CLONE(JsepAudioCodecDescription)
     139             : 
     140             :   SdpFmtpAttributeList::OpusParameters
     141           0 :   GetOpusParameters(const std::string& pt,
     142             :                     const SdpMediaSection& msection) const
     143             :   {
     144             :     // Will contain defaults if nothing else
     145           0 :     SdpFmtpAttributeList::OpusParameters result;
     146           0 :     auto* params = msection.FindFmtp(pt);
     147             : 
     148           0 :     if (params && params->codec_type == SdpRtpmapAttributeList::kOpus) {
     149             :       result =
     150           0 :         static_cast<const SdpFmtpAttributeList::OpusParameters&>(*params);
     151             :     }
     152             : 
     153           0 :     return result;
     154             :   }
     155             : 
     156             :   SdpFmtpAttributeList::TelephoneEventParameters
     157           0 :   GetTelephoneEventParameters(const std::string& pt,
     158             :                               const SdpMediaSection& msection) const
     159             :   {
     160             :     // Will contain defaults if nothing else
     161           0 :     SdpFmtpAttributeList::TelephoneEventParameters result;
     162           0 :     auto* params = msection.FindFmtp(pt);
     163             : 
     164           0 :     if (params && params->codec_type == SdpRtpmapAttributeList::kTelephoneEvent) {
     165             :       result =
     166             :         static_cast<const SdpFmtpAttributeList::TelephoneEventParameters&>
     167           0 :             (*params);
     168             :     }
     169             : 
     170           0 :     return result;
     171             :   }
     172             : 
     173             :   void
     174           0 :   AddParametersToMSection(SdpMediaSection& msection) const override
     175             :   {
     176           0 :     if (mDirection == sdp::kSend) {
     177           0 :       return;
     178             :     }
     179             : 
     180           0 :     if (mName == "opus") {
     181             :       SdpFmtpAttributeList::OpusParameters opusParams(
     182           0 :           GetOpusParameters(mDefaultPt, msection));
     183           0 :       if (mMaxPlaybackRate) {
     184           0 :         opusParams.maxplaybackrate = mMaxPlaybackRate;
     185             :       }
     186           0 :       if (mChannels == 2 && !mForceMono) {
     187             :         // We prefer to receive stereo, if available.
     188           0 :         opusParams.stereo = 1;
     189             :       }
     190           0 :       opusParams.useInBandFec = mFECEnabled ? 1 : 0;
     191           0 :       msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, opusParams));
     192           0 :     } else if (mName == "telephone-event") {
     193             :       // add the default dtmf tones
     194             :       SdpFmtpAttributeList::TelephoneEventParameters teParams(
     195           0 :           GetTelephoneEventParameters(mDefaultPt, msection));
     196           0 :       msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, teParams));
     197             :     }
     198             :   }
     199             : 
     200             :   bool
     201           0 :   Negotiate(const std::string& pt,
     202             :             const SdpMediaSection& remoteMsection) override
     203             :   {
     204           0 :     JsepCodecDescription::Negotiate(pt, remoteMsection);
     205           0 :     if (mName == "opus" && mDirection == sdp::kSend) {
     206             :       SdpFmtpAttributeList::OpusParameters opusParams(
     207           0 :           GetOpusParameters(mDefaultPt, remoteMsection));
     208             : 
     209           0 :       mMaxPlaybackRate = opusParams.maxplaybackrate;
     210           0 :       mForceMono = !opusParams.stereo;
     211             :       // draft-ietf-rtcweb-fec-03.txt section 4.2 says support for FEC
     212             :       // at the received side is declarative and can be negotiated
     213             :       // separately for either media direction.
     214           0 :       mFECEnabled = opusParams.useInBandFec;
     215             :     }
     216             : 
     217           0 :     return true;
     218             :   }
     219             : 
     220             :   uint32_t mPacketSize;
     221             :   uint32_t mBitrate;
     222             :   uint32_t mMaxPlaybackRate;
     223             :   bool mForceMono;
     224             :   bool mFECEnabled;
     225             :   bool mDtmfEnabled;
     226             : };
     227             : 
     228           0 : class JsepVideoCodecDescription : public JsepCodecDescription {
     229             :  public:
     230           0 :   JsepVideoCodecDescription(const std::string& defaultPt,
     231             :                             const std::string& name,
     232             :                             uint32_t clock,
     233             :                             bool enabled = true)
     234           0 :       : JsepCodecDescription(mozilla::SdpMediaSection::kVideo, defaultPt, name,
     235             :                              clock, 0, enabled),
     236             :         mTmmbrEnabled(false),
     237             :         mRembEnabled(false),
     238             :         mFECEnabled(false),
     239           0 :         mPacketizationMode(0)
     240             :   {
     241             :     // Add supported rtcp-fb types
     242           0 :     mNackFbTypes.push_back("");
     243           0 :     mNackFbTypes.push_back(SdpRtcpFbAttributeList::pli);
     244           0 :     mCcmFbTypes.push_back(SdpRtcpFbAttributeList::fir);
     245           0 :   }
     246             : 
     247             :   virtual void
     248           0 :   EnableTmmbr() {
     249             :     // EnableTmmbr can be called multiple times due to multiple calls to
     250             :     // PeerConnectionImpl::ConfigureJsepSessionCodecs
     251           0 :     if (!mTmmbrEnabled) {
     252           0 :       mTmmbrEnabled = true;
     253           0 :       mCcmFbTypes.push_back(SdpRtcpFbAttributeList::tmmbr);
     254             :     }
     255           0 :   }
     256             : 
     257             :   virtual void
     258           0 :   EnableRemb() {
     259             :     // EnableRemb can be called multiple times due to multiple calls to
     260             :     // PeerConnectionImpl::ConfigureJsepSessionCodecs
     261           0 :     if (!mRembEnabled) {
     262           0 :       mRembEnabled = true;
     263           0 :       mOtherFbTypes.push_back({ "", SdpRtcpFbAttributeList::kRemb, "", ""});
     264             :     }
     265           0 :   }
     266             : 
     267             :   virtual void
     268           0 :   EnableFec(std::string redPayloadType, std::string ulpfecPayloadType) {
     269             :     // Enabling FEC for video works a little differently than enabling
     270             :     // REMB or TMMBR.  Support for FEC is indicated by the presence of
     271             :     // particular codes (red and ulpfec) instead of using rtcpfb
     272             :     // attributes on a given codec.  There is no rtcpfb to push for FEC
     273             :     // as can be seen above when REMB or TMMBR are enabled.
     274             : 
     275             :     // Ensure we have valid payload types. This returns zero on failure, which
     276             :     // is a valid payload type.
     277             :     uint16_t redPt, ulpfecPt;
     278           0 :     if (!SdpHelper::GetPtAsInt(redPayloadType, &redPt) ||
     279           0 :         !SdpHelper::GetPtAsInt(ulpfecPayloadType, &ulpfecPt)) {
     280           0 :       return;
     281             :     }
     282             : 
     283           0 :     mFECEnabled = true;
     284           0 :     mREDPayloadType = redPt;
     285           0 :     mULPFECPayloadType = ulpfecPt;
     286             :   }
     287             : 
     288             :   void
     289           0 :   AddParametersToMSection(SdpMediaSection& msection) const override
     290             :   {
     291           0 :     AddFmtpsToMSection(msection);
     292           0 :     AddRtcpFbsToMSection(msection);
     293           0 :   }
     294             : 
     295             :   void
     296           0 :   AddFmtpsToMSection(SdpMediaSection& msection) const
     297             :   {
     298           0 :     if (mName == "H264") {
     299             :       SdpFmtpAttributeList::H264Parameters h264Params(
     300           0 :           GetH264Parameters(mDefaultPt, msection));
     301             : 
     302           0 :       if (mDirection == sdp::kSend) {
     303           0 :         if (!h264Params.level_asymmetry_allowed) {
     304             :           // First time the fmtp has been set; set just in case this is for a
     305             :           // sendonly m-line, since even though we aren't receiving the level
     306             :           // negotiation still needs to happen (sigh).
     307           0 :           h264Params.profile_level_id = mProfileLevelId;
     308             :         }
     309             :       } else {
     310             :         // Parameters that only apply to what we receive
     311           0 :         h264Params.max_mbps = mConstraints.maxMbps;
     312           0 :         h264Params.max_fs = mConstraints.maxFs;
     313           0 :         h264Params.max_cpb = mConstraints.maxCpb;
     314           0 :         h264Params.max_dpb = mConstraints.maxDpb;
     315           0 :         h264Params.max_br = mConstraints.maxBr;
     316           0 :         strncpy(h264Params.sprop_parameter_sets,
     317             :                 mSpropParameterSets.c_str(),
     318           0 :                 sizeof(h264Params.sprop_parameter_sets) - 1);
     319           0 :         h264Params.profile_level_id = mProfileLevelId;
     320             :       }
     321             : 
     322             :       // Parameters that apply to both the send and recv directions
     323           0 :       h264Params.packetization_mode = mPacketizationMode;
     324             :       // Hard-coded, may need to change someday?
     325           0 :       h264Params.level_asymmetry_allowed = true;
     326             : 
     327           0 :       msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, h264Params));
     328           0 :     } else if (mName == "red" && mRedundantEncodings.size()) {
     329             :       SdpFmtpAttributeList::RedParameters redParams(
     330           0 :           GetRedParameters(mDefaultPt, msection));
     331           0 :       redParams.encodings = mRedundantEncodings;
     332           0 :       msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, redParams));
     333           0 :     } else if (mName == "VP8" || mName == "VP9") {
     334           0 :       if (mDirection == sdp::kRecv) {
     335             :         // VP8 and VP9 share the same SDP parameters thus far
     336             :         SdpFmtpAttributeList::VP8Parameters vp8Params(
     337           0 :             GetVP8Parameters(mDefaultPt, msection));
     338             : 
     339           0 :         vp8Params.max_fs = mConstraints.maxFs;
     340           0 :         vp8Params.max_fr = mConstraints.maxFps;
     341           0 :         msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, vp8Params));
     342             :       }
     343             :     }
     344           0 :   }
     345             : 
     346             :   void
     347           0 :   AddRtcpFbsToMSection(SdpMediaSection& msection) const
     348             :   {
     349           0 :     SdpRtcpFbAttributeList rtcpfbs(msection.GetRtcpFbs());
     350           0 :     for (const auto& rtcpfb : rtcpfbs.mFeedbacks) {
     351           0 :       if (rtcpfb.pt == mDefaultPt) {
     352             :         // Already set by the codec for the other direction.
     353           0 :         return;
     354             :       }
     355             :     }
     356             : 
     357           0 :     for (const std::string& type : mAckFbTypes) {
     358           0 :       rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kAck, type);
     359             :     }
     360           0 :     for (const std::string& type : mNackFbTypes) {
     361           0 :       rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kNack, type);
     362             :     }
     363           0 :     for (const std::string& type : mCcmFbTypes) {
     364           0 :       rtcpfbs.PushEntry(mDefaultPt, SdpRtcpFbAttributeList::kCcm, type);
     365             :     }
     366           0 :     for (const auto& fb : mOtherFbTypes) {
     367           0 :       rtcpfbs.PushEntry(mDefaultPt, fb.type, fb.parameter, fb.extra);
     368             :     }
     369             : 
     370           0 :     msection.SetRtcpFbs(rtcpfbs);
     371             :   }
     372             : 
     373             :   SdpFmtpAttributeList::H264Parameters
     374           0 :   GetH264Parameters(const std::string& pt,
     375             :                     const SdpMediaSection& msection) const
     376             :   {
     377             :     // Will contain defaults if nothing else
     378           0 :     SdpFmtpAttributeList::H264Parameters result;
     379           0 :     auto* params = msection.FindFmtp(pt);
     380             : 
     381           0 :     if (params && params->codec_type == SdpRtpmapAttributeList::kH264) {
     382             :       result =
     383           0 :         static_cast<const SdpFmtpAttributeList::H264Parameters&>(*params);
     384             :     }
     385             : 
     386           0 :     return result;
     387             :   }
     388             : 
     389             :   SdpFmtpAttributeList::RedParameters
     390           0 :   GetRedParameters(const std::string& pt,
     391             :                    const SdpMediaSection& msection) const
     392             :   {
     393           0 :     SdpFmtpAttributeList::RedParameters result;
     394           0 :     auto* params = msection.FindFmtp(pt);
     395             : 
     396           0 :     if (params && params->codec_type == SdpRtpmapAttributeList::kRed) {
     397             :       result =
     398           0 :         static_cast<const SdpFmtpAttributeList::RedParameters&>(*params);
     399             :     }
     400             : 
     401           0 :     return result;
     402             :   }
     403             : 
     404             :   SdpFmtpAttributeList::VP8Parameters
     405           0 :   GetVP8Parameters(const std::string& pt,
     406             :                    const SdpMediaSection& msection) const
     407             :   {
     408             :     SdpRtpmapAttributeList::CodecType expectedType(
     409           0 :         mName == "VP8" ?
     410             :         SdpRtpmapAttributeList::kVP8 :
     411           0 :         SdpRtpmapAttributeList::kVP9);
     412             : 
     413             :     // Will contain defaults if nothing else
     414           0 :     SdpFmtpAttributeList::VP8Parameters result(expectedType);
     415           0 :     auto* params = msection.FindFmtp(pt);
     416             : 
     417           0 :     if (params && params->codec_type == expectedType) {
     418             :       result =
     419           0 :         static_cast<const SdpFmtpAttributeList::VP8Parameters&>(*params);
     420             :     }
     421             : 
     422           0 :     return result;
     423             :   }
     424             : 
     425             :   void
     426           0 :   NegotiateRtcpFb(const SdpMediaSection& remoteMsection,
     427             :                   SdpRtcpFbAttributeList::Type type,
     428             :                   std::vector<std::string>* supportedTypes)
     429             :   {
     430           0 :     std::vector<std::string> temp;
     431           0 :     for (auto& subType : *supportedTypes) {
     432           0 :       if (remoteMsection.HasRtcpFb(mDefaultPt, type, subType)) {
     433           0 :         temp.push_back(subType);
     434             :       }
     435             :     }
     436           0 :     *supportedTypes = temp;
     437           0 :   }
     438             : 
     439             :   void
     440           0 :   NegotiateRtcpFb(const SdpMediaSection& remoteMsection,
     441             :                   std::vector<SdpRtcpFbAttributeList::Feedback>* supportedFbs) {
     442           0 :     std::vector<SdpRtcpFbAttributeList::Feedback> temp;
     443           0 :     for (auto& fb : *supportedFbs) {
     444           0 :       if (remoteMsection.HasRtcpFb(mDefaultPt, fb.type, fb.parameter)) {
     445           0 :         temp.push_back(fb);
     446             :       }
     447             :     }
     448           0 :     *supportedFbs = temp;
     449           0 :   }
     450             : 
     451             :   void
     452           0 :   NegotiateRtcpFb(const SdpMediaSection& remote)
     453             :   {
     454             :     // Removes rtcp-fb types that the other side doesn't support
     455           0 :     NegotiateRtcpFb(remote, SdpRtcpFbAttributeList::kAck, &mAckFbTypes);
     456           0 :     NegotiateRtcpFb(remote, SdpRtcpFbAttributeList::kNack, &mNackFbTypes);
     457           0 :     NegotiateRtcpFb(remote, SdpRtcpFbAttributeList::kCcm, &mCcmFbTypes);
     458           0 :     NegotiateRtcpFb(remote, &mOtherFbTypes);
     459           0 :   }
     460             : 
     461             :   virtual bool
     462           0 :   Negotiate(const std::string& pt,
     463             :             const SdpMediaSection& remoteMsection) override
     464             :   {
     465           0 :     JsepCodecDescription::Negotiate(pt, remoteMsection);
     466           0 :     if (mName == "H264") {
     467             :       SdpFmtpAttributeList::H264Parameters h264Params(
     468           0 :           GetH264Parameters(mDefaultPt, remoteMsection));
     469             : 
     470             :       // Level is negotiated symmetrically if level asymmetry is disallowed
     471           0 :       if (!h264Params.level_asymmetry_allowed) {
     472           0 :         SetSaneH264Level(std::min(GetSaneH264Level(h264Params.profile_level_id),
     473           0 :                                   GetSaneH264Level(mProfileLevelId)),
     474           0 :                          &mProfileLevelId);
     475             :       }
     476             : 
     477           0 :       if (mDirection == sdp::kSend) {
     478             :         // Remote values of these apply only to the send codec.
     479           0 :         mConstraints.maxFs = h264Params.max_fs;
     480           0 :         mConstraints.maxMbps = h264Params.max_mbps;
     481           0 :         mConstraints.maxCpb = h264Params.max_cpb;
     482           0 :         mConstraints.maxDpb = h264Params.max_dpb;
     483           0 :         mConstraints.maxBr = h264Params.max_br;
     484           0 :         mSpropParameterSets = h264Params.sprop_parameter_sets;
     485             :         // Only do this if we didn't symmetrically negotiate above
     486           0 :         if (h264Params.level_asymmetry_allowed) {
     487           0 :           SetSaneH264Level(GetSaneH264Level(h264Params.profile_level_id),
     488           0 :                            &mProfileLevelId);
     489             :         }
     490             :       } else {
     491             :         // TODO(bug 1143709): max-recv-level support
     492             :       }
     493           0 :     } else if (mName == "red") {
     494             :       SdpFmtpAttributeList::RedParameters redParams(
     495           0 :           GetRedParameters(mDefaultPt, remoteMsection));
     496           0 :       mRedundantEncodings = redParams.encodings;
     497           0 :     } else if (mName == "VP8" || mName == "VP9") {
     498           0 :       if (mDirection == sdp::kSend) {
     499             :         SdpFmtpAttributeList::VP8Parameters vp8Params(
     500           0 :             GetVP8Parameters(mDefaultPt, remoteMsection));
     501             : 
     502           0 :         mConstraints.maxFs = vp8Params.max_fs;
     503           0 :         mConstraints.maxFps = vp8Params.max_fr;
     504             :       }
     505             :     }
     506             : 
     507           0 :     NegotiateRtcpFb(remoteMsection);
     508           0 :     return true;
     509             :   }
     510             : 
     511             :   // Maps the not-so-sane encoding of H264 level into something that is
     512             :   // ordered in the way one would expect
     513             :   // 1b is 0xAB, everything else is the level left-shifted one half-byte
     514             :   // (eg; 1.0 is 0xA0, 1.1 is 0xB0, 3.1 is 0x1F0)
     515             :   static uint32_t
     516           0 :   GetSaneH264Level(uint32_t profileLevelId)
     517             :   {
     518           0 :     uint32_t profileIdc = (profileLevelId >> 16);
     519             : 
     520           0 :     if (profileIdc == 0x42 || profileIdc == 0x4D || profileIdc == 0x58) {
     521           0 :       if ((profileLevelId & 0x10FF) == 0x100B) {
     522             :         // Level 1b
     523           0 :         return 0xAB;
     524             :       }
     525             :     }
     526             : 
     527           0 :     uint32_t level = profileLevelId & 0xFF;
     528             : 
     529           0 :     if (level == 0x09) {
     530             :       // Another way to encode level 1b
     531           0 :       return 0xAB;
     532             :     }
     533             : 
     534           0 :     return level << 4;
     535             :   }
     536             : 
     537             :   static void
     538           0 :   SetSaneH264Level(uint32_t level, uint32_t* profileLevelId)
     539             :   {
     540           0 :     uint32_t profileIdc = (*profileLevelId >> 16);
     541           0 :     uint32_t levelMask = 0xFF;
     542             : 
     543           0 :     if (profileIdc == 0x42 || profileIdc == 0x4d || profileIdc == 0x58) {
     544           0 :       levelMask = 0x10FF;
     545           0 :       if (level == 0xAB) {
     546             :         // Level 1b
     547           0 :         level = 0x100B;
     548             :       } else {
     549             :         // Not 1b, just shift
     550           0 :         level = level >> 4;
     551             :       }
     552           0 :     } else if (level == 0xAB) {
     553             :       // Another way to encode 1b
     554           0 :       level = 0x09;
     555             :     } else {
     556             :       // Not 1b, just shift
     557           0 :       level = level >> 4;
     558             :     }
     559             : 
     560           0 :     *profileLevelId = (*profileLevelId & ~levelMask) | level;
     561           0 :   }
     562             : 
     563             :   enum Subprofile {
     564             :     kH264ConstrainedBaseline,
     565             :     kH264Baseline,
     566             :     kH264Main,
     567             :     kH264Extended,
     568             :     kH264High,
     569             :     kH264High10,
     570             :     kH264High42,
     571             :     kH264High44,
     572             :     kH264High10I,
     573             :     kH264High42I,
     574             :     kH264High44I,
     575             :     kH264CALVC44,
     576             :     kH264UnknownSubprofile
     577             :   };
     578             : 
     579             :   static Subprofile
     580           0 :   GetSubprofile(uint32_t profileLevelId)
     581             :   {
     582             :     // Based on Table 5 from RFC 6184:
     583             :     //        Profile     profile_idc        profile-iop
     584             :     //                    (hexadecimal)      (binary)
     585             : 
     586             :     //        CB          42 (B)             x1xx0000
     587             :     //           same as: 4D (M)             1xxx0000
     588             :     //           same as: 58 (E)             11xx0000
     589             :     //        B           42 (B)             x0xx0000
     590             :     //           same as: 58 (E)             10xx0000
     591             :     //        M           4D (M)             0x0x0000
     592             :     //        E           58                 00xx0000
     593             :     //        H           64                 00000000
     594             :     //        H10         6E                 00000000
     595             :     //        H42         7A                 00000000
     596             :     //        H44         F4                 00000000
     597             :     //        H10I        6E                 00010000
     598             :     //        H42I        7A                 00010000
     599             :     //        H44I        F4                 00010000
     600             :     //        C44I        2C                 00010000
     601             : 
     602           0 :     if ((profileLevelId & 0xFF4F00) == 0x424000) {
     603             :       // 01001111 (mask, 0x4F)
     604             :       // x1xx0000 (from table)
     605             :       // 01000000 (expected value, 0x40)
     606           0 :       return kH264ConstrainedBaseline;
     607             :     }
     608             : 
     609           0 :     if ((profileLevelId & 0xFF8F00) == 0x4D8000) {
     610             :       // 10001111 (mask, 0x8F)
     611             :       // 1xxx0000 (from table)
     612             :       // 10000000 (expected value, 0x80)
     613           0 :       return kH264ConstrainedBaseline;
     614             :     }
     615             : 
     616           0 :     if ((profileLevelId & 0xFFCF00) == 0x58C000) {
     617             :       // 11001111 (mask, 0xCF)
     618             :       // 11xx0000 (from table)
     619             :       // 11000000 (expected value, 0xC0)
     620           0 :       return kH264ConstrainedBaseline;
     621             :     }
     622             : 
     623           0 :     if ((profileLevelId & 0xFF4F00) == 0x420000) {
     624             :       // 01001111 (mask, 0x4F)
     625             :       // x0xx0000 (from table)
     626             :       // 00000000 (expected value)
     627           0 :       return kH264Baseline;
     628             :     }
     629             : 
     630           0 :     if ((profileLevelId & 0xFFCF00) == 0x588000) {
     631             :       // 11001111 (mask, 0xCF)
     632             :       // 10xx0000 (from table)
     633             :       // 10000000 (expected value, 0x80)
     634           0 :       return kH264Baseline;
     635             :     }
     636             : 
     637           0 :     if ((profileLevelId & 0xFFAF00) == 0x4D0000) {
     638             :       // 10101111 (mask, 0xAF)
     639             :       // 0x0x0000 (from table)
     640             :       // 00000000 (expected value)
     641           0 :       return kH264Main;
     642             :     }
     643             : 
     644           0 :     if ((profileLevelId & 0xFF0000) == 0x580000) {
     645             :       // 11001111 (mask, 0xCF)
     646             :       // 00xx0000 (from table)
     647             :       // 00000000 (expected value)
     648           0 :       return kH264Extended;
     649             :     }
     650             : 
     651           0 :     if ((profileLevelId & 0xFFFF00) == 0x640000) {
     652           0 :       return kH264High;
     653             :     }
     654             : 
     655           0 :     if ((profileLevelId & 0xFFFF00) == 0x6E0000) {
     656           0 :       return kH264High10;
     657             :     }
     658             : 
     659           0 :     if ((profileLevelId & 0xFFFF00) == 0x7A0000) {
     660           0 :       return kH264High42;
     661             :     }
     662             : 
     663           0 :     if ((profileLevelId & 0xFFFF00) == 0xF40000) {
     664           0 :       return kH264High44;
     665             :     }
     666             : 
     667           0 :     if ((profileLevelId & 0xFFFF00) == 0x6E1000) {
     668           0 :       return kH264High10I;
     669             :     }
     670             : 
     671           0 :     if ((profileLevelId & 0xFFFF00) == 0x7A1000) {
     672           0 :       return kH264High42I;
     673             :     }
     674             : 
     675           0 :     if ((profileLevelId & 0xFFFF00) == 0xF41000) {
     676           0 :       return kH264High44I;
     677             :     }
     678             : 
     679           0 :     if ((profileLevelId & 0xFFFF00) == 0x2C1000) {
     680           0 :       return kH264CALVC44;
     681             :     }
     682             : 
     683           0 :     return kH264UnknownSubprofile;
     684             :   }
     685             : 
     686             :   virtual bool
     687           0 :   ParametersMatch(const std::string& fmt,
     688             :                   const SdpMediaSection& remoteMsection) const override
     689             :   {
     690           0 :     if (mName == "H264") {
     691             :       SdpFmtpAttributeList::H264Parameters h264Params(
     692           0 :           GetH264Parameters(fmt, remoteMsection));
     693             : 
     694           0 :       if (h264Params.packetization_mode != mPacketizationMode) {
     695           0 :         return false;
     696             :       }
     697             : 
     698           0 :       if (GetSubprofile(h264Params.profile_level_id) !=
     699           0 :           GetSubprofile(mProfileLevelId)) {
     700           0 :         return false;
     701             :       }
     702             :     }
     703             : 
     704           0 :     return true;
     705             :   }
     706             : 
     707             :   virtual bool
     708           0 :   RtcpFbRembIsSet() const
     709             :   {
     710           0 :     for (const auto& fb : mOtherFbTypes) {
     711           0 :       if (fb.type == SdpRtcpFbAttributeList::kRemb) {
     712           0 :         return true;
     713             :       }
     714             :     }
     715           0 :     return false;
     716             :   }
     717             : 
     718             :   virtual void
     719           0 :   UpdateRedundantEncodings(std::vector<JsepCodecDescription*> codecs)
     720             :   {
     721           0 :     for (const auto codec : codecs) {
     722           0 :       if (codec->mType == SdpMediaSection::kVideo &&
     723           0 :           codec->mEnabled &&
     724           0 :           codec->mName != "red") {
     725             :         uint16_t pt;
     726           0 :         if (!SdpHelper::GetPtAsInt(codec->mDefaultPt, &pt)) {
     727           0 :           continue;
     728             :         }
     729           0 :         mRedundantEncodings.push_back(pt);
     730             :       }
     731             :     }
     732           0 :   }
     733             : 
     734           0 :   JSEP_CODEC_CLONE(JsepVideoCodecDescription)
     735             : 
     736             :   std::vector<std::string> mAckFbTypes;
     737             :   std::vector<std::string> mNackFbTypes;
     738             :   std::vector<std::string> mCcmFbTypes;
     739             :   std::vector<SdpRtcpFbAttributeList::Feedback> mOtherFbTypes;
     740             :   bool mTmmbrEnabled;
     741             :   bool mRembEnabled;
     742             :   bool mFECEnabled;
     743             :   uint8_t mREDPayloadType;
     744             :   uint8_t mULPFECPayloadType;
     745             :   std::vector<uint8_t> mRedundantEncodings;
     746             : 
     747             :   // H264-specific stuff
     748             :   uint32_t mProfileLevelId;
     749             :   uint32_t mPacketizationMode;
     750             :   std::string mSpropParameterSets;
     751             : };
     752             : 
     753           0 : class JsepApplicationCodecDescription : public JsepCodecDescription {
     754             :   // This is the new draft-21 implementation
     755             :  public:
     756           0 :   JsepApplicationCodecDescription(const std::string& name,
     757             :                                   uint16_t channels,
     758             :                                   uint16_t localPort,
     759             :                                   uint32_t localMaxMessageSize,
     760             :                                   bool enabled = true)
     761           0 :       : JsepCodecDescription(mozilla::SdpMediaSection::kApplication, "",
     762             :                              name, 0, channels, enabled),
     763             :         mLocalPort(localPort),
     764             :         mLocalMaxMessageSize(localMaxMessageSize),
     765             :         mRemotePort(0),
     766           0 :         mRemoteMaxMessageSize(0)
     767             :   {
     768           0 :   }
     769             : 
     770           0 :   JSEP_CODEC_CLONE(JsepApplicationCodecDescription)
     771             : 
     772             :   // Override, uses sctpport or sctpmap instead of rtpmap
     773             :   virtual bool
     774           0 :   Matches(const std::string& fmt,
     775             :           const SdpMediaSection& remoteMsection) const override
     776             :   {
     777           0 :     if (mType != remoteMsection.GetMediaType()) {
     778           0 :       return false;
     779             :     }
     780             : 
     781           0 :     int sctp_port = remoteMsection.GetSctpPort();
     782           0 :     bool fmt_matches = nsCRT::strcasecmp(mName.c_str(),
     783           0 :                           remoteMsection.GetFormats()[0].c_str()) == 0;
     784           0 :     if (sctp_port && fmt_matches) {
     785             :       // New sctp draft 21 format
     786           0 :       return true;
     787             :     }
     788             : 
     789             :     const SdpSctpmapAttributeList::Sctpmap* sctp_map(
     790           0 :         remoteMsection.GetSctpmap());
     791           0 :     if (sctp_map) {
     792             :       // Old sctp draft 05 format
     793           0 :       return nsCRT::strcasecmp(mName.c_str(), sctp_map->name.c_str()) == 0;
     794             :     }
     795             : 
     796           0 :     return false;
     797             :   }
     798             : 
     799             :   virtual void
     800           0 :   AddToMediaSection(SdpMediaSection& msection) const override
     801             :   {
     802           0 :     if (mEnabled && msection.GetMediaType() == mType) {
     803           0 :       if (msection.GetFormats().empty()) {
     804           0 :         msection.AddDataChannel(mName, mLocalPort, mChannels,
     805           0 :                                 mLocalMaxMessageSize);
     806             :       }
     807             : 
     808           0 :       AddParametersToMSection(msection);
     809             :     }
     810           0 :   }
     811             : 
     812             :   bool
     813           0 :   Negotiate(const std::string& pt, const SdpMediaSection& remoteMsection) override
     814             :   {
     815           0 :     JsepCodecDescription::Negotiate(pt, remoteMsection);
     816             : 
     817             :     uint32_t message_size;
     818           0 :     mRemoteMMSSet = remoteMsection.GetMaxMessageSize(&message_size);
     819           0 :     if (mRemoteMMSSet) {
     820           0 :       mRemoteMaxMessageSize = message_size;
     821             :     } else {
     822           0 :       mRemoteMaxMessageSize = WEBRTC_DATACHANELL_MAX_MESSAGE_SIZE_DEFAULT;
     823             :     }
     824             : 
     825           0 :     int sctp_port = remoteMsection.GetSctpPort();
     826           0 :     if (sctp_port) {
     827           0 :       mRemotePort = sctp_port;
     828           0 :       return true;
     829             :     }
     830             : 
     831             :     const SdpSctpmapAttributeList::Sctpmap* sctp_map(
     832           0 :         remoteMsection.GetSctpmap());
     833           0 :     if (sctp_map) {
     834           0 :       mRemotePort = std::stoi(sctp_map->pt);
     835           0 :       return true;
     836             :     }
     837             : 
     838           0 :     return false;
     839             :   }
     840             : 
     841             : 
     842             :   uint16_t mLocalPort;
     843             :   uint32_t mLocalMaxMessageSize;
     844             :   uint16_t mRemotePort;
     845             :   uint32_t mRemoteMaxMessageSize;
     846             :   bool mRemoteMMSSet;
     847             : };
     848             : 
     849             : } // namespace mozilla
     850             : 
     851             : #endif

Generated by: LCOV version 1.13