2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/video_coding/main/test/vcm_payload_sink_factory.h"
17 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
18 #include "webrtc/modules/video_coding/main/test/test_util.h"
19 #include "webrtc/system_wrappers/interface/clock.h"
20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
25 class VcmPayloadSinkFactory::VcmPayloadSink
26 : public PayloadSinkInterface,
27 public VCMPacketRequestCallback {
29 VcmPayloadSink(VcmPayloadSinkFactory* factory,
30 RtpStreamInterface* stream,
31 scoped_ptr<VideoCodingModule>* vcm,
32 scoped_ptr<FileOutputFrameReceiver>* frame_receiver)
41 assert(frame_receiver);
42 assert(frame_receiver->get());
44 frame_receiver_.swap(*frame_receiver);
45 vcm_->RegisterPacketRequestCallback(this);
46 vcm_->RegisterReceiveCallback(frame_receiver_.get());
49 virtual ~VcmPayloadSink() {
50 factory_->Remove(this);
53 // PayloadSinkInterface
54 virtual int32_t OnReceivedPayloadData(
55 const uint8_t* payload_data,
56 const uint16_t payload_size,
57 const WebRtcRTPHeader* rtp_header) OVERRIDE {
58 return vcm_->IncomingPacket(payload_data, payload_size, *rtp_header);
61 virtual bool OnRecoveredPacket(const uint8_t* packet,
62 int packet_length) OVERRIDE {
63 // We currently don't handle FEC.
67 // VCMPacketRequestCallback
68 virtual int32_t ResendPackets(const uint16_t* sequence_numbers,
69 uint16_t length) OVERRIDE {
70 stream_->ResendPackets(sequence_numbers, length);
74 int DecodeAndProcess(bool should_decode, bool decode_dual_frame) {
76 if (vcm_->Decode() < 0) {
80 while (decode_dual_frame && vcm_->DecodeDualFrame(0) == 1) {
82 return Process() ? 0 : -1;
86 if (vcm_->TimeUntilNextProcess() <= 0) {
87 if (vcm_->Process() < 0) {
96 while (vcm_->DecodeDualFrame(0) == 1) {
102 VcmPayloadSinkFactory* factory_;
103 RtpStreamInterface* stream_;
104 scoped_ptr<VideoCodingModule> vcm_;
105 scoped_ptr<FileOutputFrameReceiver> frame_receiver_;
107 DISALLOW_IMPLICIT_CONSTRUCTORS(VcmPayloadSink);
110 VcmPayloadSinkFactory::VcmPayloadSinkFactory(
111 const std::string& base_out_filename,
113 bool protection_enabled,
114 VCMVideoProtection protection_method,
116 uint32_t render_delay_ms,
117 uint32_t min_playout_delay_ms)
118 : base_out_filename_(base_out_filename),
120 protection_enabled_(protection_enabled),
121 protection_method_(protection_method),
123 render_delay_ms_(render_delay_ms),
124 min_playout_delay_ms_(min_playout_delay_ms),
125 null_event_factory_(new NullEventFactory()),
126 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
129 assert(crit_sect_.get());
132 VcmPayloadSinkFactory::~VcmPayloadSinkFactory() {
133 assert(sinks_.empty());
136 PayloadSinkInterface* VcmPayloadSinkFactory::Create(
137 RtpStreamInterface* stream) {
139 CriticalSectionScoped cs(crit_sect_.get());
141 scoped_ptr<VideoCodingModule> vcm(
142 VideoCodingModule::Create(clock_, null_event_factory_.get()));
143 if (vcm.get() == NULL) {
146 if (vcm->InitializeReceiver() < 0) {
150 const PayloadTypes& plt = stream->payload_types();
151 for (PayloadTypesIterator it = plt.begin(); it != plt.end();
153 if (it->codec_type() != kVideoCodecULPFEC &&
154 it->codec_type() != kVideoCodecRED) {
156 if (VideoCodingModule::Codec(it->codec_type(), &codec) < 0) {
159 codec.plType = it->payload_type();
160 if (vcm->RegisterReceiveCodec(&codec, 1) < 0) {
166 vcm->SetChannelParameters(0, 0, rtt_ms_);
167 vcm->SetVideoProtection(protection_method_, protection_enabled_);
168 vcm->SetRenderDelay(render_delay_ms_);
169 vcm->SetMinimumPlayoutDelay(min_playout_delay_ms_);
170 vcm->SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack, 0);
172 scoped_ptr<FileOutputFrameReceiver> frame_receiver(
173 new FileOutputFrameReceiver(base_out_filename_, stream->ssrc()));
174 scoped_ptr<VcmPayloadSink> sink(
175 new VcmPayloadSink(this, stream, &vcm, &frame_receiver));
177 sinks_.push_back(sink.get());
178 return sink.release();
181 int VcmPayloadSinkFactory::DecodeAndProcessAll(bool decode_dual_frame) {
182 CriticalSectionScoped cs(crit_sect_.get());
184 bool should_decode = (clock_->TimeInMilliseconds() % 5) == 0;
185 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
186 if ((*it)->DecodeAndProcess(should_decode, decode_dual_frame) < 0) {
193 bool VcmPayloadSinkFactory::ProcessAll() {
194 CriticalSectionScoped cs(crit_sect_.get());
195 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
196 if (!(*it)->Process()) {
203 bool VcmPayloadSinkFactory::DecodeAll() {
204 CriticalSectionScoped cs(crit_sect_.get());
205 for (Sinks::iterator it = sinks_.begin(); it != sinks_.end(); ++it) {
206 if (!(*it)->Decode()) {
213 void VcmPayloadSinkFactory::Remove(VcmPayloadSink* sink) {
215 CriticalSectionScoped cs(crit_sect_.get());
216 Sinks::iterator it = std::find(sinks_.begin(), sinks_.end(), sink);
217 assert(it != sinks_.end());
221 } // namespace rtpplayer
222 } // namespace webrtc