Home | History | Annotate | Download | only in test
      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
    223