Index: webrtc/pc/mediasession.cc |
diff --git a/webrtc/pc/mediasession.cc b/webrtc/pc/mediasession.cc |
index 52abfe855f6aef47fa83d7e1ce51321f090a2417..328f67593bd434cb214abc74781b9994bbb942bc 100644 |
--- a/webrtc/pc/mediasession.cc |
+++ b/webrtc/pc/mediasession.cc |
@@ -1030,24 +1030,26 @@ static bool CreateMediaContentAnswer( |
// Make sure the answer media content direction is per default set as |
// described in RFC3264 section 6.1. |
+ const bool should_send = |
+ !IsRtpProtocol(answer->protocol()) || !answer->streams().empty(); |
pthatcher1
2016/05/31 21:52:36
This would be more clear as:
const bool is_data =
ossu
2016/06/02 13:28:02
Acknowledged.
|
+ const bool should_receive = |
+ answer->type() == cricket::MEDIA_TYPE_VIDEO ? options.recv_video : |
+ (answer->type() == cricket::MEDIA_TYPE_AUDIO ? options.recv_audio : true); |
ossu
2016/05/25 11:26:14
I expect that since there's no flag for data, we'l
|
+ |
switch (offer->direction()) { |
case MD_INACTIVE: |
answer->set_direction(MD_INACTIVE); |
break; |
case MD_SENDONLY: |
- answer->set_direction(MD_RECVONLY); |
+ answer->set_direction(should_receive ? MD_RECVONLY : MD_INACTIVE); |
break; |
case MD_RECVONLY: |
- answer->set_direction(IsRtpProtocol(answer->protocol()) && |
- answer->streams().empty() |
- ? MD_INACTIVE |
- : MD_SENDONLY); |
+ answer->set_direction(should_send ? MD_SENDONLY : MD_INACTIVE); |
break; |
case MD_SENDRECV: |
- answer->set_direction(IsRtpProtocol(answer->protocol()) && |
- answer->streams().empty() |
- ? MD_RECVONLY |
- : MD_SENDRECV); |
+ answer->set_direction(should_send |
+ ? (should_receive ? MD_SENDRECV : MD_SENDONLY) |
+ : (should_receive ? MD_RECVONLY : MD_INACTIVE)); |
break; |
pthatcher1
2016/05/31 21:52:36
I think this would be more clear if we made an Rtp
ossu
2016/06/02 13:28:02
I've put an RtpTranscieverDirection in and changed
|
default: |
RTC_DCHECK(false && "MediaContentDescription has unexpected direction."); |
@@ -1173,6 +1175,22 @@ std::string MediaTypeToString(MediaType type) { |
return type_str; |
} |
+std::string MediaContentDirectionToString(MediaContentDirection direction) { |
+ switch (direction) { |
+ case MD_INACTIVE: |
+ return "inactive"; |
+ case MD_SENDONLY: |
+ return "sendonly"; |
+ case MD_RECVONLY: |
+ return "recvonly"; |
+ case MD_SENDRECV: |
+ return "sendrecv"; |
+ default: |
+ ASSERT(false); |
+ break; |
+ } |
+} |
+ |
void MediaSessionOptions::AddSendStream(MediaType type, |
const std::string& id, |
const std::string& sync_label) { |
@@ -1234,11 +1252,64 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( |
: secure_(SEC_DISABLED), |
add_legacy_(true), |
transport_desc_factory_(transport_desc_factory) { |
- channel_manager->GetSupportedAudioCodecs(&audio_codecs_); |
+ channel_manager->GetSupportedAudioCodecs(&audio_sendrecv_codecs_); |
channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_); |
channel_manager->GetSupportedVideoCodecs(&video_codecs_); |
channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_); |
channel_manager->GetSupportedDataCodecs(&data_codecs_); |
+ audio_send_codecs_ = audio_sendrecv_codecs_; |
+ audio_recv_codecs_ = audio_sendrecv_codecs_; |
+} |
+ |
+const AudioCodecs& MediaSessionDescriptionFactory::audio_codecs() const { |
pthatcher1
2016/05/31 21:52:35
This could be renamed to audio_sendrecv_codecs().
|
+ return audio_sendrecv_codecs_; |
+} |
+ |
+const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const { |
+ return audio_send_codecs_; |
+} |
+ |
+const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const { |
+ return audio_recv_codecs_; |
+} |
+ |
+void MediaSessionDescriptionFactory::set_audio_codecs( |
+ const AudioCodecs& send_and_recv_codecs) { |
+ audio_send_codecs_ = send_and_recv_codecs; |
+ audio_recv_codecs_ = send_and_recv_codecs; |
+ audio_sendrecv_codecs_ = send_and_recv_codecs; |
+} |
+ |
+void MediaSessionDescriptionFactory::set_audio_codecs( |
+ const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) { |
+ audio_send_codecs_ = send_codecs; |
+ audio_recv_codecs_ = recv_codecs; |
+ audio_sendrecv_codecs_.clear(); |
+ |
+ // Intersect the two lists of codecs, preserving the order of the send codecs. |
+ // If there's any difference in priorities, chances are encoding is more |
+ // expensive than decoding, and high-priority send codecs are likely handled |
+ // better (e.g. through hardware encoder support) than low-priority ones. |
+ // TODO(ossu): This is O(n^2). However, each list should generally be small |
+ // enough for this to not be a problem. They are also nicely local in memory |
+ // like this. |
+ for (const auto& sc : audio_send_codecs_) { |
+ for (const auto& rc : audio_recv_codecs_) { |
+ const size_t send_channels = (sc.channels == 0) ? 1 : sc.channels; |
+ const size_t recv_channels = (rc.channels == 0) ? 1 : rc.channels; |
+ if (sc.clockrate == rc.clockrate && |
+ sc.bitrate == rc.bitrate && |
+ send_channels == recv_channels && |
+ (_stricmp(sc.name.c_str(), rc.name.c_str()) == 0) && |
+ sc.params == rc.params && |
+ sc.feedback_params == rc.feedback_params) { |
+ AudioCodec out_codec = sc; |
+ out_codec.channels = send_channels; |
+ audio_sendrecv_codecs_.push_back(out_codec); |
+ break; |
+ } |
+ } |
+ } |
} |
SessionDescription* MediaSessionDescriptionFactory::CreateOffer( |
@@ -1249,11 +1320,30 @@ SessionDescription* MediaSessionDescriptionFactory::CreateOffer( |
StreamParamsVec current_streams; |
GetCurrentStreamParams(current_description, ¤t_streams); |
+ const AudioCodecs *supported_audio_codecs; |
+ if (options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_) { |
+ if (options.recv_audio) { |
+ // sendrecv |
+ supported_audio_codecs = &audio_sendrecv_codecs_; |
+ } else { |
+ // sendonly |
+ supported_audio_codecs = &audio_send_codecs_; |
+ } |
+ } else if (options.recv_audio) { |
+ // recvonly |
+ supported_audio_codecs = &audio_recv_codecs_; |
+ } else { |
+ // Stream is inactive - generate list as if sendrecv. |
+ // See RFC 3264 Section 6.1. |
+ supported_audio_codecs = &audio_sendrecv_codecs_; |
+ } |
pthatcher1
2016/05/31 21:52:36
Would it make sense to make a method like this?
c
ossu
2016/06/02 13:28:02
Why not have it take an RtpTranscieverDirection di
pthatcher1
2016/06/02 22:29:17
Sounds like a great idea.
|
+ |
AudioCodecs audio_codecs; |
VideoCodecs video_codecs; |
DataCodecs data_codecs; |
- GetCodecsToOffer(current_description, &audio_codecs, &video_codecs, |
- &data_codecs); |
+ GetCodecsToOffer(current_description, *supported_audio_codecs, |
+ video_codecs_, data_codecs_, |
+ &audio_codecs, &video_codecs, &data_codecs); |
if (!options.vad_enabled) { |
// If application doesn't want CN codecs in offer. |
@@ -1414,6 +1504,9 @@ SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( |
void MediaSessionDescriptionFactory::GetCodecsToOffer( |
const SessionDescription* current_description, |
+ const AudioCodecs& supported_audio_codecs, |
+ const VideoCodecs& supported_video_codecs, |
+ const DataCodecs& supported_data_codecs, |
AudioCodecs* audio_codecs, |
VideoCodecs* video_codecs, |
DataCodecs* data_codecs) const { |
@@ -1449,9 +1542,12 @@ void MediaSessionDescriptionFactory::GetCodecsToOffer( |
} |
// Add our codecs that are not in |current_description|. |
- FindCodecsToOffer<AudioCodec>(audio_codecs_, audio_codecs, &used_pltypes); |
- FindCodecsToOffer<VideoCodec>(video_codecs_, video_codecs, &used_pltypes); |
- FindCodecsToOffer<DataCodec>(data_codecs_, data_codecs, &used_pltypes); |
+ FindCodecsToOffer<AudioCodec>(supported_audio_codecs, audio_codecs, |
+ &used_pltypes); |
+ FindCodecsToOffer<VideoCodec>(supported_video_codecs, video_codecs, |
+ &used_pltypes); |
+ FindCodecsToOffer<DataCodec>(supported_data_codecs, data_codecs, |
+ &used_pltypes); |
} |
void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( |
@@ -1733,6 +1829,8 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( |
StreamParamsVec* current_streams, |
SessionDescription* answer) const { |
const ContentInfo* audio_content = GetFirstAudioContent(offer); |
+ const AudioContentDescription* audio_content_description = |
pthatcher1
2016/05/31 21:52:36
A better name would be offer_audio.
|
+ static_cast<const AudioContentDescription*>(audio_content->description); |
std::unique_ptr<TransportDescription> audio_transport(CreateTransportAnswer( |
audio_content->name, offer, |
@@ -1741,7 +1839,39 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( |
return false; |
} |
- AudioCodecs audio_codecs = audio_codecs_; |
+ // Pick codecs based on the requested communications direction in the offer. |
+ // According to RFC 3264 Section 6.1, inactive is to be treated as sendrecv |
+ // when constructing the list of supported formats. |
+ AudioCodecs audio_codecs; |
+ switch (audio_content_description->direction()) { |
+ case MD_INACTIVE: |
+ audio_codecs = audio_sendrecv_codecs_; |
+ break; |
+ case MD_SENDRECV: |
+ if (options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_) { |
+ audio_codecs = options.recv_audio |
+ ? audio_sendrecv_codecs_ |
+ : audio_send_codecs_; |
+ } else { |
+ audio_codecs = options.recv_audio |
+ ? audio_recv_codecs_ |
+ : audio_sendrecv_codecs_; // inactive |
+ } |
+ break; |
+ case MD_RECVONLY: |
+ if (options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_) |
+ audio_codecs = audio_send_codecs_; |
+ else |
+ audio_codecs = audio_sendrecv_codecs_; // inactive |
+ break; |
+ case MD_SENDONLY: |
+ if (options.recv_audio) |
+ audio_codecs = audio_recv_codecs_; |
+ else |
+ audio_codecs = audio_sendrecv_codecs_; // inactive |
+ break; |
+ } |
pthatcher1
2016/05/31 21:52:36
This could be more simple also:
auto offer_rtd =
|
+ |
if (!options.vad_enabled) { |
StripCNCodecs(&audio_codecs); |
} |
@@ -1754,8 +1884,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( |
cricket::SecurePolicy sdes_policy = |
audio_transport->secure() ? cricket::SEC_DISABLED : secure(); |
if (!CreateMediaContentAnswer( |
- static_cast<const AudioContentDescription*>( |
- audio_content->description), |
+ audio_content_description, |
options, |
audio_codecs, |
sdes_policy, |