diff options
Diffstat (limited to 'webrtc/modules/video_coding/test/vcm_payload_sink_factory.cc')
-rw-r--r-- | webrtc/modules/video_coding/test/vcm_payload_sink_factory.cc | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/webrtc/modules/video_coding/test/vcm_payload_sink_factory.cc b/webrtc/modules/video_coding/test/vcm_payload_sink_factory.cc new file mode 100644 index 0000000000..c9ec372f41 --- /dev/null +++ b/webrtc/modules/video_coding/test/vcm_payload_sink_factory.cc @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "webrtc/modules/video_coding/test/vcm_payload_sink_factory.h" + +#include <assert.h> + +#include <algorithm> + +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" +#include "webrtc/modules/video_coding/test/test_util.h" +#include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/system_wrappers/include/critical_section_wrapper.h" + +namespace webrtc { +namespace rtpplayer { + +class VcmPayloadSinkFactory::VcmPayloadSink : public PayloadSinkInterface, + public VCMPacketRequestCallback { + public: + VcmPayloadSink(VcmPayloadSinkFactory* factory, + RtpStreamInterface* stream, + rtc::scoped_ptr<VideoCodingModule>* vcm, + rtc::scoped_ptr<FileOutputFrameReceiver>* frame_receiver) + : factory_(factory), stream_(stream), vcm_(), frame_receiver_() { + assert(factory); + assert(stream); + assert(vcm); + assert(vcm->get()); + assert(frame_receiver); + assert(frame_receiver->get()); + vcm_.swap(*vcm); + frame_receiver_.swap(*frame_receiver); + vcm_->RegisterPacketRequestCallback(this); + vcm_->RegisterReceiveCallback(frame_receiver_.get()); + } + + virtual ~VcmPayloadSink() { factory_->Remove(this); } + + // PayloadSinkInterface + int32_t OnReceivedPayloadData(const uint8_t* payload_data, + const size_t payload_size, + const WebRtcRTPHeader* rtp_header) override { + return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header); + } + + bool OnRecoveredPacket(const uint8_t* packet, size_t packet_length) override { + // We currently don't handle FEC. + return true; + } + + // VCMPacketRequestCallback + int32_t ResendPackets(const uint16_t* sequence_numbers, + uint16_t length) override { + stream_->ResendPackets(sequence_numbers, length); + return 0; + } + + int DecodeAndProcess(bool should_decode, bool decode_dual_frame) { + if (should_decode) { + if (vcm_->Decode() < 0) { + return -1; + } + } + return Process() ? 0 : -1; + } + + bool Process() { + if (vcm_->TimeUntilNextProcess() <= 0) { + if (vcm_->Process() < 0) { + return false; + } + } + return true; + } + + bool Decode() { + vcm_->Decode(10000); + return true; + } + + private: + VcmPayloadSinkFactory* factory_; + RtpStreamInterface* stream_; + rtc::scoped_ptr<VideoCodingModule> vcm_; + rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(VcmPayloadSink); +}; + +VcmPayloadSinkFactory::VcmPayloadSinkFactory( + const std::string& base_out_filename, + Clock* clock, + bool protection_enabled, + VCMVideoProtection protection_method, + int64_t rtt_ms, + uint32_t render_delay_ms, + uint32_t min_playout_delay_ms) + : base_out_filename_(base_out_filename), + clock_(clock), + protection_enabled_(protection_enabled), + protection_method_(protection_method), + rtt_ms_(rtt_ms), + render_delay_ms_(render_delay_ms), + min_playout_delay_ms_(min_playout_delay_ms), + null_event_factory_(new NullEventFactory()), + crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), + sinks_() { + assert(clock); + assert(crit_sect_.get()); +} + +VcmPayloadSinkFactory::~VcmPayloadSinkFactory() { + assert(sinks_.empty()); +} + +PayloadSinkInterface* VcmPayloadSinkFactory::Create( + RtpStreamInterface* stream) { + assert(stream); + CriticalSectionScoped cs(crit_sect_.get()); + + rtc::scoped_ptr<VideoCodingModule> vcm( + VideoCodingModule::Create(clock_, null_event_factory_.get())); + if (vcm.get() == NULL) { + return NULL; + } + + const PayloadTypes& plt = stream->payload_types(); + for (PayloadTypesIterator it = plt.begin(); it != plt.end(); ++it) { + if (it->codec_type() != kVideoCodecULPFEC && + it->codec_type() != kVideoCodecRED) { + VideoCodec codec; + VideoCodingModule::Codec(it->codec_type(), &codec); + codec.plType = it->payload_type(); + if (vcm->RegisterReceiveCodec(&codec, 1) < 0) { + return NULL; + } + } + } + + vcm->SetChannelParameters(0, 0, rtt_ms_); + vcm->SetVideoProtection(protection_method_, protection_enabled_); + vcm->SetRenderDelay(render_delay_ms_); + vcm->SetMinimumPlayoutDelay(min_playout_delay_ms_); + vcm->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0); + + rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver( + new FileOutputFrameReceiver(base_out_filename_, stream->ssrc())); + rtc::scoped_ptr<VcmPayloadSink> sink( + new VcmPayloadSink(this, stream, &vcm, &frame_receiver)); + + sinks_.push_back(sink.get()); + return sink.release(); +} + +int VcmPayloadSinkFactory::DecodeAndProcessAll(bool decode_dual_frame) { + CriticalSectionScoped cs(crit_sect_.get()); + assert(clock_); + bool should_decode = (clock_->TimeInMilliseconds() % 5) == 0; + for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { + if ((*it)->DecodeAndProcess(should_decode, decode_dual_frame) < 0) { + return -1; + } + } + return 0; +} + +bool VcmPayloadSinkFactory::ProcessAll() { + CriticalSectionScoped cs(crit_sect_.get()); + for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { + if (!(*it)->Process()) { + return false; + } + } + return true; +} + +bool VcmPayloadSinkFactory::DecodeAll() { + CriticalSectionScoped cs(crit_sect_.get()); + for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { + if (!(*it)->Decode()) { + return false; + } + } + return true; +} + +void VcmPayloadSinkFactory::Remove(VcmPayloadSink* sink) { + assert(sink); + CriticalSectionScoped cs(crit_sect_.get()); + Sinks::iterator it = std::find(sinks_.begin(), sinks_.end(), sink); + assert(it != sinks_.end()); + sinks_.erase(it); +} + +} // namespace rtpplayer +} // namespace webrtc |