Home | History | Annotate | Download | only in test
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <algorithm>
      6 #include <climits>
      7 #include <cstdarg>
      8 #include <cstdio>
      9 #include <string>
     10 
     11 #include "base/at_exit.h"
     12 #include "base/logging.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/message_loop/message_loop.h"
     16 #include "base/threading/thread.h"
     17 #include "base/time/default_tick_clock.h"
     18 #include "media/base/video_frame.h"
     19 #include "media/cast/cast_config.h"
     20 #include "media/cast/cast_environment.h"
     21 #include "media/cast/cast_receiver.h"
     22 #include "media/cast/logging/logging_defines.h"
     23 #include "media/cast/test/transport/transport.h"
     24 #include "media/cast/test/utility/input_helper.h"
     25 
     26 #if defined(OS_LINUX)
     27 #include "media/cast/test/linux_output_window.h"
     28 #endif  // OS_LINUX
     29 
     30 namespace media {
     31 namespace cast {
     32 // Settings chosen to match default sender settings.
     33 #define DEFAULT_SEND_PORT "2346"
     34 #define DEFAULT_RECEIVE_PORT "2344"
     35 #define DEFAULT_SEND_IP "127.0.0.1"
     36 #define DEFAULT_RESTART "0"
     37 #define DEFAULT_AUDIO_FEEDBACK_SSRC "1"
     38 #define DEFAULT_AUDIO_INCOMING_SSRC "2"
     39 #define DEFAULT_AUDIO_PAYLOAD_TYPE "127"
     40 #define DEFAULT_VIDEO_FEEDBACK_SSRC "12"
     41 #define DEFAULT_VIDEO_INCOMING_SSRC "11"
     42 #define DEFAULT_VIDEO_PAYLOAD_TYPE "96"
     43 #define DEFAULT_VIDEO_CODEC_WIDTH "640"
     44 #define DEFAULT_VIDEO_CODEC_HEIGHT "480"
     45 #define DEFAULT_VIDEO_CODEC_BITRATE "2000"
     46 
     47 static const int kAudioSamplingFrequency = 48000;
     48 #if defined(OS_LINUX)
     49 const int kVideoWindowWidth = 1280;
     50 const int kVideoWindowHeight = 720;
     51 #endif  // OS_LINUX
     52 static const int kFrameTimerMs = 33;
     53 
     54 
     55 void GetPorts(int* tx_port, int* rx_port) {
     56   test::InputBuilder tx_input("Enter send port.",
     57       DEFAULT_SEND_PORT, 1, INT_MAX);
     58   *tx_port = tx_input.GetIntInput();
     59 
     60   test::InputBuilder rx_input("Enter receive port.",
     61       DEFAULT_RECEIVE_PORT, 1, INT_MAX);
     62   *rx_port = rx_input.GetIntInput();
     63 }
     64 
     65 std::string GetIpAddress(const std::string display_text) {
     66  test::InputBuilder input(display_text, DEFAULT_SEND_IP,
     67       INT_MIN, INT_MAX);
     68   std::string ip_address = input.GetStringInput();
     69   // Ensure correct form:
     70   while (std::count(ip_address.begin(), ip_address.end(), '.') != 3) {
     71     ip_address = input.GetStringInput();
     72   }
     73   return ip_address;
     74 }
     75 
     76 void GetSsrcs(AudioReceiverConfig* audio_config) {
     77   test::InputBuilder input_tx("Choose audio sender SSRC.",
     78       DEFAULT_AUDIO_FEEDBACK_SSRC, 1, INT_MAX);
     79   audio_config->feedback_ssrc = input_tx.GetIntInput();
     80 
     81   test::InputBuilder input_rx("Choose audio receiver SSRC.",
     82       DEFAULT_AUDIO_INCOMING_SSRC, 1, INT_MAX);
     83   audio_config->incoming_ssrc = input_tx.GetIntInput();
     84 }
     85 
     86 void GetSsrcs(VideoReceiverConfig* video_config) {
     87   test::InputBuilder input_tx("Choose video sender SSRC.",
     88       DEFAULT_VIDEO_FEEDBACK_SSRC, 1, INT_MAX);
     89   video_config->feedback_ssrc = input_tx.GetIntInput();
     90 
     91   test::InputBuilder input_rx("Choose video receiver SSRC.",
     92       DEFAULT_VIDEO_INCOMING_SSRC, 1, INT_MAX);
     93   video_config->incoming_ssrc = input_rx.GetIntInput();
     94 }
     95 
     96 void GetPayloadtype(AudioReceiverConfig* audio_config) {
     97   test::InputBuilder input("Choose audio receiver payload type.",
     98       DEFAULT_AUDIO_PAYLOAD_TYPE, 96, 127);
     99   audio_config->rtp_payload_type = input.GetIntInput();
    100 }
    101 
    102 AudioReceiverConfig GetAudioReceiverConfig() {
    103   AudioReceiverConfig audio_config;
    104 
    105   GetSsrcs(&audio_config);
    106   GetPayloadtype(&audio_config);
    107 
    108   audio_config.rtcp_c_name = "audio_receiver (at) a.b.c.d";
    109 
    110   VLOG(1) << "Using OPUS 48Khz stereo";
    111   audio_config.use_external_decoder = false;
    112   audio_config.frequency = 48000;
    113   audio_config.channels = 2;
    114   audio_config.codec = kOpus;
    115   return audio_config;
    116 }
    117 
    118 void GetPayloadtype(VideoReceiverConfig* video_config) {
    119   test::InputBuilder input("Choose video receiver payload type.",
    120       DEFAULT_VIDEO_PAYLOAD_TYPE, 96, 127);
    121   video_config->rtp_payload_type = input.GetIntInput();
    122 }
    123 
    124 VideoReceiverConfig GetVideoReceiverConfig() {
    125   VideoReceiverConfig video_config;
    126 
    127   GetSsrcs(&video_config);
    128   GetPayloadtype(&video_config);
    129 
    130   video_config.rtcp_c_name = "video_receiver (at) a.b.c.d";
    131 
    132   video_config.use_external_decoder = false;
    133 
    134   VLOG(1) << "Using VP8";
    135   video_config.codec = kVp8;
    136   return video_config;
    137 }
    138 
    139 
    140 class ReceiveProcess : public base::RefCountedThreadSafe<ReceiveProcess> {
    141  public:
    142   explicit ReceiveProcess(scoped_refptr<FrameReceiver> frame_receiver)
    143     : frame_receiver_(frame_receiver),
    144 #if defined(OS_LINUX)
    145       render_(0, 0, kVideoWindowWidth, kVideoWindowHeight, "Cast_receiver"),
    146 #endif // OS_LINUX
    147       last_playout_time_(),
    148       last_render_time_() {}
    149 
    150   void Start() {
    151     GetAudioFrame(base::TimeDelta::FromMilliseconds(kFrameTimerMs));
    152     GetVideoFrame();
    153   }
    154 
    155  protected:
    156   virtual ~ReceiveProcess() {}
    157 
    158  private:
    159   friend class base::RefCountedThreadSafe<ReceiveProcess>;
    160 
    161   void DisplayFrame(const scoped_refptr<media::VideoFrame>& video_frame,
    162       const base::TimeTicks& render_time) {
    163 #ifdef OS_LINUX
    164     render_.RenderFrame(video_frame);
    165 #endif // OS_LINUX
    166     // Print out the delta between frames.
    167     if (!last_render_time_.is_null()){
    168         base::TimeDelta time_diff = render_time - last_render_time_;
    169         VLOG(0) << " RenderDelay[mS] =  " << time_diff.InMilliseconds();
    170     }
    171     last_render_time_ = render_time;
    172     GetVideoFrame();
    173   }
    174 
    175   void ReceiveAudioFrame(scoped_ptr<PcmAudioFrame> audio_frame,
    176                          const base::TimeTicks& playout_time) {
    177     // For audio just print the playout delta between audio frames.
    178     // Default diff time is kFrameTimerMs.
    179     base::TimeDelta time_diff =
    180         base::TimeDelta::FromMilliseconds(kFrameTimerMs);
    181     if (!last_playout_time_.is_null()){
    182         time_diff = playout_time - last_playout_time_;
    183         VLOG(0) << " ***PlayoutDelay[mS] =  " << time_diff.InMilliseconds();
    184     }
    185     last_playout_time_ = playout_time;
    186     GetAudioFrame(time_diff);
    187   }
    188 
    189   void GetAudioFrame(base::TimeDelta playout_diff) {
    190     int num_10ms_blocks = playout_diff.InMilliseconds() / 10;
    191     frame_receiver_->GetRawAudioFrame(num_10ms_blocks, kAudioSamplingFrequency,
    192         base::Bind(&ReceiveProcess::ReceiveAudioFrame, this));
    193   }
    194 
    195   void GetVideoFrame() {
    196     frame_receiver_->GetRawVideoFrame(
    197         base::Bind(&ReceiveProcess::DisplayFrame, this));
    198   }
    199 
    200   scoped_refptr<FrameReceiver> frame_receiver_;
    201 #ifdef OS_LINUX
    202   test::LinuxOutputWindow render_;
    203 #endif // OS_LINUX
    204   base::TimeTicks last_playout_time_;
    205   base::TimeTicks last_render_time_;
    206 };
    207 
    208 }  // namespace cast
    209 }  // namespace media
    210 
    211 int main(int argc, char** argv) {
    212   base::AtExitManager at_exit;
    213   base::MessageLoopForIO main_message_loop;
    214   VLOG(1) << "Cast Receiver";
    215   base::Thread main_thread("Cast main send thread");
    216   base::Thread audio_thread("Cast audio decoder thread");
    217   base::Thread video_thread("Cast video decoder thread");
    218   main_thread.Start();
    219   audio_thread.Start();
    220   video_thread.Start();
    221 
    222   base::DefaultTickClock clock;
    223   // Enable receiver side threads, and disable logging.
    224   scoped_refptr<media::cast::CastEnvironment> cast_environment(new
    225       media::cast::CastEnvironment(&clock,
    226                                    main_thread.message_loop_proxy(),
    227                                    NULL,
    228                                    audio_thread.message_loop_proxy(),
    229                                    NULL,
    230                                    video_thread.message_loop_proxy(),
    231                                    media::cast::GetDefaultCastLoggingConfig()));
    232 
    233   media::cast::AudioReceiverConfig audio_config =
    234       media::cast::GetAudioReceiverConfig();
    235   media::cast::VideoReceiverConfig video_config =
    236       media::cast::GetVideoReceiverConfig();
    237 
    238   scoped_ptr<media::cast::test::Transport> transport(
    239       new media::cast::test::Transport(main_message_loop.message_loop_proxy()));
    240   scoped_ptr<media::cast::CastReceiver> cast_receiver(
    241       media::cast::CastReceiver::CreateCastReceiver(
    242       cast_environment,
    243       audio_config,
    244       video_config,
    245       transport->packet_sender()));
    246 
    247   media::cast::PacketReceiver* packet_receiver =
    248       cast_receiver->packet_receiver();
    249 
    250   int send_to_port, receive_port;
    251   media::cast::GetPorts(&send_to_port, &receive_port);
    252   std::string ip_address = media::cast::GetIpAddress("Enter destination IP.");
    253   std::string local_ip_address = media::cast::GetIpAddress("Enter local IP.");
    254   transport->SetLocalReceiver(packet_receiver, ip_address, local_ip_address,
    255                               receive_port);
    256   transport->SetSendDestination(ip_address, send_to_port);
    257 
    258   scoped_refptr<media::cast::ReceiveProcess> receive_process(
    259       new media::cast::ReceiveProcess(cast_receiver->frame_receiver()));
    260   receive_process->Start();
    261   main_message_loop.Run();
    262   transport->StopReceiving();
    263   return 0;
    264 }
    265