Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / main / test / vcm_payload_sink_factory.cc
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/main/test/vcm_payload_sink_factory.h"
12
13 #include <assert.h>
14
15 #include <algorithm>
16
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"
21
22 namespace webrtc {
23 namespace rtpplayer {
24
25 class VcmPayloadSinkFactory::VcmPayloadSink
26     : public PayloadSinkInterface,
27       public VCMPacketRequestCallback {
28  public:
29   VcmPayloadSink(VcmPayloadSinkFactory* factory,
30                  RtpStreamInterface* stream,
31                  scoped_ptr<VideoCodingModule>* vcm,
32                  scoped_ptr<FileOutputFrameReceiver>* frame_receiver)
33       : factory_(factory),
34         stream_(stream),
35         vcm_(),
36         frame_receiver_() {
37     assert(factory);
38     assert(stream);
39     assert(vcm);
40     assert(vcm->get());
41     assert(frame_receiver);
42     assert(frame_receiver->get());
43     vcm_.swap(*vcm);
44     frame_receiver_.swap(*frame_receiver);
45     vcm_->RegisterPacketRequestCallback(this);
46     vcm_->RegisterReceiveCallback(frame_receiver_.get());
47   }
48
49   virtual ~VcmPayloadSink() {
50     factory_->Remove(this);
51   }
52
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);
59   }
60
61   virtual bool OnRecoveredPacket(const uint8_t* packet,
62                                  int packet_length) OVERRIDE {
63     // We currently don't handle FEC.
64     return true;
65   }
66
67   // VCMPacketRequestCallback
68   virtual int32_t ResendPackets(const uint16_t* sequence_numbers,
69                                 uint16_t length) OVERRIDE {
70     stream_->ResendPackets(sequence_numbers, length);
71     return 0;
72   }
73
74   int DecodeAndProcess(bool should_decode, bool decode_dual_frame) {
75     if (should_decode) {
76       if (vcm_->Decode() < 0) {
77         return -1;
78       }
79     }
80     while (decode_dual_frame && vcm_->DecodeDualFrame(0) == 1) {
81     }
82     return Process() ? 0 : -1;
83   }
84
85   bool Process() {
86     if (vcm_->TimeUntilNextProcess() <= 0) {
87       if (vcm_->Process() < 0) {
88         return false;
89       }
90     }
91     return true;
92   }
93
94   bool Decode() {
95     vcm_->Decode(10000);
96     while (vcm_->DecodeDualFrame(0) == 1) {
97     }
98     return true;
99   }
100
101  private:
102   VcmPayloadSinkFactory* factory_;
103   RtpStreamInterface* stream_;
104   scoped_ptr<VideoCodingModule> vcm_;
105   scoped_ptr<FileOutputFrameReceiver> frame_receiver_;
106
107   DISALLOW_IMPLICIT_CONSTRUCTORS(VcmPayloadSink);
108 };
109
110 VcmPayloadSinkFactory::VcmPayloadSinkFactory(
111     const std::string& base_out_filename,
112     Clock* clock,
113     bool protection_enabled,
114     VCMVideoProtection protection_method,
115     uint32_t rtt_ms,
116     uint32_t render_delay_ms,
117     uint32_t min_playout_delay_ms)
118     : base_out_filename_(base_out_filename),
119       clock_(clock),
120       protection_enabled_(protection_enabled),
121       protection_method_(protection_method),
122       rtt_ms_(rtt_ms),
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()),
127       sinks_() {
128   assert(clock);
129   assert(crit_sect_.get());
130 }
131
132 VcmPayloadSinkFactory::~VcmPayloadSinkFactory() {
133   assert(sinks_.empty());
134 }
135
136 PayloadSinkInterface* VcmPayloadSinkFactory::Create(
137     RtpStreamInterface* stream) {
138   assert(stream);
139   CriticalSectionScoped cs(crit_sect_.get());
140
141   scoped_ptr<VideoCodingModule> vcm(
142       VideoCodingModule::Create(clock_, null_event_factory_.get()));
143   if (vcm.get() == NULL) {
144     return NULL;
145   }
146   if (vcm->InitializeReceiver() < 0) {
147     return NULL;
148   }
149
150   const PayloadTypes& plt = stream->payload_types();
151   for (PayloadTypesIterator it = plt.begin(); it != plt.end();
152       ++it) {
153     if (it->codec_type() != kVideoCodecULPFEC &&
154         it->codec_type() != kVideoCodecRED) {
155       VideoCodec codec;
156       if (VideoCodingModule::Codec(it->codec_type(), &codec) < 0) {
157         return NULL;
158       }
159       codec.plType = it->payload_type();
160       if (vcm->RegisterReceiveCodec(&codec, 1) < 0) {
161         return NULL;
162       }
163     }
164   }
165
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);
171
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));
176
177   sinks_.push_back(sink.get());
178   return sink.release();
179 }
180
181 int VcmPayloadSinkFactory::DecodeAndProcessAll(bool decode_dual_frame) {
182   CriticalSectionScoped cs(crit_sect_.get());
183   assert(clock_);
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) {
187       return -1;
188     }
189   }
190   return 0;
191 }
192
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()) {
197       return false;
198     }
199   }
200   return true;
201 }
202
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()) {
207       return false;
208     }
209   }
210   return true;
211 }
212
213 void VcmPayloadSinkFactory::Remove(VcmPayloadSink* sink) {
214   assert(sink);
215   CriticalSectionScoped cs(crit_sect_.get());
216   Sinks::iterator it = std::find(sinks_.begin(), sinks_.end(), sink);
217   assert(it != sinks_.end());
218   sinks_.erase(it);
219 }
220
221 }  // namespace rtpplayer
222 }  // namespace webrtc