1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/video_coding/test/vcm_payload_sink_factory.h" 12 13 #include <assert.h> 14 15 #include <algorithm> 16 17 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h" 18 #include "webrtc/modules/video_coding/test/test_util.h" 19 #include "webrtc/system_wrappers/include/clock.h" 20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 21 22 namespace webrtc { 23 namespace rtpplayer { 24 25 class VcmPayloadSinkFactory::VcmPayloadSink : public PayloadSinkInterface, 26 public VCMPacketRequestCallback { 27 public: 28 VcmPayloadSink(VcmPayloadSinkFactory* factory, 29 RtpStreamInterface* stream, 30 rtc::scoped_ptr<VideoCodingModule>* vcm, 31 rtc::scoped_ptr<FileOutputFrameReceiver>* frame_receiver) 32 : factory_(factory), stream_(stream), vcm_(), frame_receiver_() { 33 assert(factory); 34 assert(stream); 35 assert(vcm); 36 assert(vcm->get()); 37 assert(frame_receiver); 38 assert(frame_receiver->get()); 39 vcm_.swap(*vcm); 40 frame_receiver_.swap(*frame_receiver); 41 vcm_->RegisterPacketRequestCallback(this); 42 vcm_->RegisterReceiveCallback(frame_receiver_.get()); 43 } 44 45 virtual ~VcmPayloadSink() { factory_->Remove(this); } 46 47 // PayloadSinkInterface 48 int32_t OnReceivedPayloadData(const uint8_t* payload_data, 49 const size_t payload_size, 50 const WebRtcRTPHeader* rtp_header) override { 51 return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header); 52 } 53 54 bool OnRecoveredPacket(const uint8_t* packet, size_t packet_length) override { 55 // We currently don't handle FEC. 56 return true; 57 } 58 59 // VCMPacketRequestCallback 60 int32_t ResendPackets(const uint16_t* sequence_numbers, 61 uint16_t length) override { 62 stream_->ResendPackets(sequence_numbers, length); 63 return 0; 64 } 65 66 int DecodeAndProcess(bool should_decode, bool decode_dual_frame) { 67 if (should_decode) { 68 if (vcm_->Decode() < 0) { 69 return -1; 70 } 71 } 72 return Process() ? 0 : -1; 73 } 74 75 bool Process() { 76 if (vcm_->TimeUntilNextProcess() <= 0) { 77 if (vcm_->Process() < 0) { 78 return false; 79 } 80 } 81 return true; 82 } 83 84 bool Decode() { 85 vcm_->Decode(10000); 86 return true; 87 } 88 89 private: 90 VcmPayloadSinkFactory* factory_; 91 RtpStreamInterface* stream_; 92 rtc::scoped_ptr<VideoCodingModule> vcm_; 93 rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver_; 94 95 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(VcmPayloadSink); 96 }; 97 98 VcmPayloadSinkFactory::VcmPayloadSinkFactory( 99 const std::string& base_out_filename, 100 Clock* clock, 101 bool protection_enabled, 102 VCMVideoProtection protection_method, 103 int64_t rtt_ms, 104 uint32_t render_delay_ms, 105 uint32_t min_playout_delay_ms) 106 : base_out_filename_(base_out_filename), 107 clock_(clock), 108 protection_enabled_(protection_enabled), 109 protection_method_(protection_method), 110 rtt_ms_(rtt_ms), 111 render_delay_ms_(render_delay_ms), 112 min_playout_delay_ms_(min_playout_delay_ms), 113 null_event_factory_(new NullEventFactory()), 114 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), 115 sinks_() { 116 assert(clock); 117 assert(crit_sect_.get()); 118 } 119 120 VcmPayloadSinkFactory::~VcmPayloadSinkFactory() { 121 assert(sinks_.empty()); 122 } 123 124 PayloadSinkInterface* VcmPayloadSinkFactory::Create( 125 RtpStreamInterface* stream) { 126 assert(stream); 127 CriticalSectionScoped cs(crit_sect_.get()); 128 129 rtc::scoped_ptr<VideoCodingModule> vcm( 130 VideoCodingModule::Create(clock_, null_event_factory_.get())); 131 if (vcm.get() == NULL) { 132 return NULL; 133 } 134 135 const PayloadTypes& plt = stream->payload_types(); 136 for (PayloadTypesIterator it = plt.begin(); it != plt.end(); ++it) { 137 if (it->codec_type() != kVideoCodecULPFEC && 138 it->codec_type() != kVideoCodecRED) { 139 VideoCodec codec; 140 VideoCodingModule::Codec(it->codec_type(), &codec); 141 codec.plType = it->payload_type(); 142 if (vcm->RegisterReceiveCodec(&codec, 1) < 0) { 143 return NULL; 144 } 145 } 146 } 147 148 vcm->SetChannelParameters(0, 0, rtt_ms_); 149 vcm->SetVideoProtection(protection_method_, protection_enabled_); 150 vcm->SetRenderDelay(render_delay_ms_); 151 vcm->SetMinimumPlayoutDelay(min_playout_delay_ms_); 152 vcm->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0); 153 154 rtc::scoped_ptr<FileOutputFrameReceiver> frame_receiver( 155 new FileOutputFrameReceiver(base_out_filename_, stream->ssrc())); 156 rtc::scoped_ptr<VcmPayloadSink> sink( 157 new VcmPayloadSink(this, stream, &vcm, &frame_receiver)); 158 159 sinks_.push_back(sink.get()); 160 return sink.release(); 161 } 162 163 int VcmPayloadSinkFactory::DecodeAndProcessAll(bool decode_dual_frame) { 164 CriticalSectionScoped cs(crit_sect_.get()); 165 assert(clock_); 166 bool should_decode = (clock_->TimeInMilliseconds() % 5) == 0; 167 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { 168 if ((*it)->DecodeAndProcess(should_decode, decode_dual_frame) < 0) { 169 return -1; 170 } 171 } 172 return 0; 173 } 174 175 bool VcmPayloadSinkFactory::ProcessAll() { 176 CriticalSectionScoped cs(crit_sect_.get()); 177 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { 178 if (!(*it)->Process()) { 179 return false; 180 } 181 } 182 return true; 183 } 184 185 bool VcmPayloadSinkFactory::DecodeAll() { 186 CriticalSectionScoped cs(crit_sect_.get()); 187 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) { 188 if (!(*it)->Decode()) { 189 return false; 190 } 191 } 192 return true; 193 } 194 195 void VcmPayloadSinkFactory::Remove(VcmPayloadSink* sink) { 196 assert(sink); 197 CriticalSectionScoped cs(crit_sect_.get()); 198 Sinks::iterator it = std::find(sinks_.begin(), sinks_.end(), sink); 199 assert(it != sinks_.end()); 200 sinks_.erase(it); 201 } 202 203 } // namespace rtpplayer 204 } // namespace webrtc 205