summaryrefslogtreecommitdiff
path: root/media/webrtc/webrtcvideoengine2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/webrtc/webrtcvideoengine2.cc')
-rw-r--r--media/webrtc/webrtcvideoengine2.cc164
1 files changed, 105 insertions, 59 deletions
diff --git a/media/webrtc/webrtcvideoengine2.cc b/media/webrtc/webrtcvideoengine2.cc
index d902718..a877921 100644
--- a/media/webrtc/webrtcvideoengine2.cc
+++ b/media/webrtc/webrtcvideoengine2.cc
@@ -57,10 +57,18 @@ static bool CodecNameMatches(const std::string& name1,
return _stricmp(name1.c_str(), name2.c_str()) == 0;
}
+const char* kInternallySupportedCodecs[] = {
+ kVp8CodecName,
+};
+
// True if codec is supported by a software implementation that's always
// available.
static bool CodecIsInternallySupported(const std::string& codec_name) {
- return CodecNameMatches(codec_name, kVp8CodecName);
+ for (size_t i = 0; i < ARRAY_SIZE(kInternallySupportedCodecs); ++i) {
+ if (CodecNameMatches(codec_name, kInternallySupportedCodecs[i]))
+ return true;
+ }
+ return false;
}
static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
@@ -807,6 +815,37 @@ WebRtcVideoChannel2::~WebRtcVideoChannel2() {
bool WebRtcVideoChannel2::Init() { return true; }
+bool WebRtcVideoChannel2::CodecIsExternallySupported(
+ const std::string& name) const {
+ if (external_encoder_factory_ == NULL) {
+ return false;
+ }
+
+ const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
+ external_encoder_factory_->codecs();
+ for (size_t c = 0; c < external_codecs.size(); ++c) {
+ if (CodecNameMatches(name, external_codecs[c].name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::vector<WebRtcVideoChannel2::VideoCodecSettings>
+WebRtcVideoChannel2::FilterSupportedCodecs(
+ const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs)
+ const {
+ std::vector<VideoCodecSettings> supported_codecs;
+ for (size_t i = 0; i < mapped_codecs.size(); ++i) {
+ const VideoCodecSettings& codec = mapped_codecs[i];
+ if (CodecIsInternallySupported(codec.codec.name) ||
+ CodecIsExternallySupported(codec.codec.name)) {
+ supported_codecs.push_back(codec);
+ }
+ }
+ return supported_codecs;
+}
+
bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
if (!ValidateCodecFormats(codecs)) {
@@ -815,21 +854,19 @@ bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
if (mapped_codecs.empty()) {
- LOG(LS_ERROR) << "SetRecvCodecs called without video codec payloads.";
+ LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs.";
return false;
}
- // TODO(pbos): Add a decoder factory which controls supported codecs.
- // Blocked on webrtc:2854.
- for (size_t i = 0; i < mapped_codecs.size(); ++i) {
- if (!CodecNameMatches(mapped_codecs[i].codec.name, kVp8CodecName)) {
- LOG(LS_ERROR) << "SetRecvCodecs called with unsupported codec: '"
- << mapped_codecs[i].codec.name << "'";
- return false;
- }
+ const std::vector<VideoCodecSettings> supported_codecs =
+ FilterSupportedCodecs(mapped_codecs);
+
+ if (mapped_codecs.size() != supported_codecs.size()) {
+ LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs.";
+ return false;
}
- recv_codecs_ = mapped_codecs;
+ recv_codecs_ = supported_codecs;
rtc::CritScope stream_lock(&stream_crit_);
for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
@@ -1899,34 +1936,67 @@ WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
call_->DestroyVideoReceiveStream(stream_);
- ClearDecoders();
+ ClearDecoders(&allocated_decoders_);
}
-void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
- const std::vector<VideoCodecSettings>& recv_codecs) {
- // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
- // TODO(pbos): Base receive codecs off recv_codecs_ and set up using a
- // DecoderFactory similar to send side. Pending webrtc:2854.
- // Also set up default codecs if there's nothing in recv_codecs_.
- ClearDecoders();
+WebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder
+WebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder(
+ std::vector<AllocatedDecoder>* old_decoders,
+ const VideoCodec& codec) {
+ webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
- AllocatedDecoder allocated_decoder(
- webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), false);
- allocated_decoders_.push_back(allocated_decoder);
+ for (size_t i = 0; i < old_decoders->size(); ++i) {
+ if ((*old_decoders)[i].type == type) {
+ AllocatedDecoder decoder = (*old_decoders)[i];
+ (*old_decoders)[i] = old_decoders->back();
+ old_decoders->pop_back();
+ return decoder;
+ }
+ }
- webrtc::VideoReceiveStream::Decoder decoder;
- decoder.decoder = allocated_decoder.decoder;
- decoder.payload_type = kDefaultVideoCodecPref.payload_type;
- decoder.payload_name = "VP8";
+ if (external_decoder_factory_ != NULL) {
+ webrtc::VideoDecoder* decoder =
+ external_decoder_factory_->CreateVideoDecoder(type);
+ if (decoder != NULL) {
+ return AllocatedDecoder(decoder, type, true);
+ }
+ }
- config_.decoders.push_back(decoder);
+ if (type == webrtc::kVideoCodecVP8) {
+ return AllocatedDecoder(
+ webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false);
+ }
- config_.rtp.fec = recv_codecs.front().fec;
+ // This shouldn't happen, we should not be trying to create something we don't
+ // support.
+ assert(false);
+ return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false);
+}
+
+void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
+ const std::vector<VideoCodecSettings>& recv_codecs) {
+ std::vector<AllocatedDecoder> old_decoders = allocated_decoders_;
+ allocated_decoders_.clear();
+ config_.decoders.clear();
+ for (size_t i = 0; i < recv_codecs.size(); ++i) {
+ AllocatedDecoder allocated_decoder =
+ CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec);
+ allocated_decoders_.push_back(allocated_decoder);
+ webrtc::VideoReceiveStream::Decoder decoder;
+ decoder.decoder = allocated_decoder.decoder;
+ decoder.payload_type = recv_codecs[i].codec.id;
+ decoder.payload_name = recv_codecs[i].codec.name;
+ config_.decoders.push_back(decoder);
+ }
+
+ // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
+ config_.rtp.fec = recv_codecs.front().fec;
config_.rtp.nack.rtp_history_ms =
IsNackEnabled(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
config_.rtp.remb = IsRembEnabled(recv_codecs.begin()->codec);
+ ClearDecoders(&old_decoders);
RecreateWebRtcStream();
}
@@ -1944,16 +2014,17 @@ void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
stream_->Start();
}
-void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders() {
- for (size_t i = 0; i < allocated_decoders_.size(); ++i) {
- if (allocated_decoders_[i].external) {
+void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders(
+ std::vector<AllocatedDecoder>* allocated_decoders) {
+ for (size_t i = 0; i < allocated_decoders->size(); ++i) {
+ if ((*allocated_decoders)[i].external) {
external_decoder_factory_->DestroyVideoDecoder(
- allocated_decoders_[i].decoder);
+ (*allocated_decoders)[i].decoder);
} else {
- delete allocated_decoders_[i].decoder;
+ delete (*allocated_decoders)[i].decoder;
}
}
- allocated_decoders_.clear();
+ allocated_decoders->clear();
}
void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
@@ -2115,31 +2186,6 @@ WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
return video_codecs;
}
-std::vector<WebRtcVideoChannel2::VideoCodecSettings>
-WebRtcVideoChannel2::FilterSupportedCodecs(
- const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) {
- std::vector<VideoCodecSettings> supported_codecs;
- for (size_t i = 0; i < mapped_codecs.size(); ++i) {
- const VideoCodecSettings& codec = mapped_codecs[i];
- if (CodecIsInternallySupported(codec.codec.name)) {
- supported_codecs.push_back(codec);
- }
-
- if (external_encoder_factory_ == NULL) {
- continue;
- }
- const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
- external_encoder_factory_->codecs();
- for (size_t c = 0; c < external_codecs.size(); ++c) {
- if (CodecNameMatches(codec.codec.name, external_codecs[c].name)) {
- supported_codecs.push_back(codec);
- break;
- }
- }
- }
- return supported_codecs;
-}
-
} // namespace cricket
#endif // HAVE_WEBRTC_VIDEO