summaryrefslogtreecommitdiff
path: root/media/cast/test/receiver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'media/cast/test/receiver.cc')
-rw-r--r--media/cast/test/receiver.cc263
1 files changed, 263 insertions, 0 deletions
diff --git a/media/cast/test/receiver.cc b/media/cast/test/receiver.cc
new file mode 100644
index 0000000000..54cff9a1c3
--- /dev/null
+++ b/media/cast/test/receiver.cc
@@ -0,0 +1,263 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <climits>
+#include <cstdarg>
+#include <cstdio>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/threading/thread.h"
+#include "base/time/default_tick_clock.h"
+#include "media/cast/cast_config.h"
+#include "media/cast/cast_environment.h"
+#include "media/cast/cast_receiver.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/test/transport/transport.h"
+#include "media/cast/test/utility/input_helper.h"
+
+#if defined(OS_LINUX)
+#include "media/cast/test/linux_output_window.h"
+#endif // OS_LINUX
+
+namespace media {
+namespace cast {
+
+#define DEFAULT_SEND_PORT "2346"
+#define DEFAULT_RECEIVE_PORT "2344"
+#define DEFAULT_SEND_IP "127.0.0.1"
+#define DEFAULT_RESTART "0"
+#define DEFAULT_AUDIO_FEEDBACK_SSRC "2"
+#define DEFAULT_AUDIO_INCOMING_SSRC "1"
+#define DEFAULT_AUDIO_PAYLOAD_TYPE "127"
+#define DEFAULT_VIDEO_FEEDBACK_SSRC "12"
+#define DEFAULT_VIDEO_INCOMING_SSRC "11"
+#define DEFAULT_VIDEO_PAYLOAD_TYPE "96"
+#define DEFAULT_VIDEO_CODEC_WIDTH "640"
+#define DEFAULT_VIDEO_CODEC_HEIGHT "480"
+#define DEFAULT_VIDEO_CODEC_BITRATE "2000"
+
+static const int kAudioSamplingFrequency = 48000;
+#if defined(OS_LINUX)
+const int kVideoWindowWidth = 1280;
+const int kVideoWindowHeight = 720;
+#endif // OS_LINUX
+static const int kFrameTimerMs = 33;
+
+
+void GetPorts(int* tx_port, int* rx_port) {
+ test::InputBuilder tx_input("Enter send port.",
+ DEFAULT_SEND_PORT, 1, INT_MAX);
+ *tx_port = tx_input.GetIntInput();
+
+ test::InputBuilder rx_input("Enter receive port.",
+ DEFAULT_RECEIVE_PORT, 1, INT_MAX);
+ *rx_port = rx_input.GetIntInput();
+}
+
+std::string GetIpAddress(const std::string display_text) {
+ test::InputBuilder input(display_text, DEFAULT_SEND_IP,
+ INT_MIN, INT_MAX);
+ std::string ip_address = input.GetStringInput();
+ // Ensure correct form:
+ while (std::count(ip_address.begin(), ip_address.end(), '.') != 3) {
+ ip_address = input.GetStringInput();
+ }
+ return ip_address;
+}
+
+void GetSsrcs(AudioReceiverConfig* audio_config) {
+ test::InputBuilder input_tx("Choose audio sender SSRC.",
+ DEFAULT_AUDIO_FEEDBACK_SSRC, 1, INT_MAX);
+ audio_config->feedback_ssrc = input_tx.GetIntInput();
+
+ test::InputBuilder input_rx("Choose audio receiver SSRC.",
+ DEFAULT_AUDIO_INCOMING_SSRC, 1, INT_MAX);
+ audio_config->incoming_ssrc = input_tx.GetIntInput();
+}
+
+void GetSsrcs(VideoReceiverConfig* video_config) {
+ test::InputBuilder input_tx("Choose video sender SSRC.",
+ DEFAULT_VIDEO_FEEDBACK_SSRC, 1, INT_MAX);
+ video_config->feedback_ssrc = input_tx.GetIntInput();
+
+ test::InputBuilder input_rx("Choose video receiver SSRC.",
+ DEFAULT_VIDEO_INCOMING_SSRC, 1, INT_MAX);
+ video_config->incoming_ssrc = input_rx.GetIntInput();
+}
+
+void GetPayloadtype(AudioReceiverConfig* audio_config) {
+ test::InputBuilder input("Choose audio receiver payload type.",
+ DEFAULT_AUDIO_PAYLOAD_TYPE, 96, 127);
+ audio_config->rtp_payload_type = input.GetIntInput();
+}
+
+AudioReceiverConfig GetAudioReceiverConfig() {
+ AudioReceiverConfig audio_config;
+
+ GetSsrcs(&audio_config);
+ GetPayloadtype(&audio_config);
+
+ audio_config.rtcp_c_name = "audio_receiver@a.b.c.d";
+
+ VLOG(1) << "Using OPUS 48Khz stereo";
+ audio_config.use_external_decoder = false;
+ audio_config.frequency = 48000;
+ audio_config.channels = 2;
+ audio_config.codec = kOpus;
+ return audio_config;
+}
+
+void GetPayloadtype(VideoReceiverConfig* video_config) {
+ test::InputBuilder input("Choose video receiver payload type.",
+ DEFAULT_VIDEO_PAYLOAD_TYPE, 96, 127);
+ video_config->rtp_payload_type = input.GetIntInput();
+}
+
+VideoReceiverConfig GetVideoReceiverConfig() {
+ VideoReceiverConfig video_config;
+
+ GetSsrcs(&video_config);
+ GetPayloadtype(&video_config);
+
+ video_config.rtcp_c_name = "video_receiver@a.b.c.d";
+
+ video_config.use_external_decoder = false;
+
+ VLOG(1) << "Using VP8";
+ video_config.codec = kVp8;
+ return video_config;
+}
+
+
+class ReceiveProcess : public base::RefCountedThreadSafe<ReceiveProcess> {
+ public:
+ explicit ReceiveProcess(scoped_refptr<FrameReceiver> frame_receiver)
+ : frame_receiver_(frame_receiver),
+#if defined(OS_LINUX)
+ render_(0, 0, kVideoWindowWidth, kVideoWindowHeight, "Cast_receiver"),
+#endif // OS_LINUX
+ last_playout_time_(),
+ last_render_time_() {}
+
+ void Start() {
+ GetAudioFrame(base::TimeDelta::FromMilliseconds(kFrameTimerMs));
+ GetVideoFrame();
+ }
+
+ protected:
+ virtual ~ReceiveProcess() {}
+
+ private:
+ friend class base::RefCountedThreadSafe<ReceiveProcess>;
+
+ void DisplayFrame(scoped_ptr<I420VideoFrame> frame,
+ const base::TimeTicks& render_time) {
+#ifdef OS_LINUX
+ render_.RenderFrame(*frame);
+#endif // OS_LINUX
+ // Print out the delta between frames.
+ if (!last_render_time_.is_null()){
+ base::TimeDelta time_diff = render_time - last_render_time_;
+ VLOG(0) << " RenderDelay[mS] = " << time_diff.InMilliseconds();
+ }
+ last_render_time_ = render_time;
+ GetVideoFrame();
+ }
+
+ void ReceiveAudioFrame(scoped_ptr<PcmAudioFrame> audio_frame,
+ const base::TimeTicks& playout_time) {
+ // For audio just print the playout delta between audio frames.
+ // Default diff time is kFrameTimerMs.
+ base::TimeDelta time_diff =
+ base::TimeDelta::FromMilliseconds(kFrameTimerMs);
+ if (!last_playout_time_.is_null()){
+ time_diff = playout_time - last_playout_time_;
+ VLOG(0) << " PlayoutDelay[mS] = " << time_diff.InMilliseconds();
+ }
+ last_playout_time_ = playout_time;
+ GetAudioFrame(time_diff);
+ }
+
+ void GetAudioFrame(base::TimeDelta playout_diff) {
+ int num_10ms_blocks = playout_diff.InMilliseconds() / 10;
+ frame_receiver_->GetRawAudioFrame(num_10ms_blocks, kAudioSamplingFrequency,
+ base::Bind(&ReceiveProcess::ReceiveAudioFrame, this));
+ }
+
+ void GetVideoFrame() {
+ frame_receiver_->GetRawVideoFrame(
+ base::Bind(&ReceiveProcess::DisplayFrame, this));
+ }
+
+ scoped_refptr<FrameReceiver> frame_receiver_;
+#ifdef OS_LINUX
+ test::LinuxOutputWindow render_;
+#endif // OS_LINUX
+ base::TimeTicks last_playout_time_;
+ base::TimeTicks last_render_time_;
+};
+
+} // namespace cast
+} // namespace media
+
+int main(int argc, char** argv) {
+ base::AtExitManager at_exit;
+ base::MessageLoopForIO main_message_loop;
+ VLOG(1) << "Cast Receiver";
+ base::Thread main_thread("Cast main send thread");
+ base::Thread audio_thread("Cast audio decoder thread");
+ base::Thread video_thread("Cast video decoder thread");
+ main_thread.Start();
+ audio_thread.Start();
+ video_thread.Start();
+
+ base::DefaultTickClock clock;
+ // Enable receiver side threads, and disable logging.
+ scoped_refptr<media::cast::CastEnvironment> cast_environment(new
+ media::cast::CastEnvironment(&clock,
+ main_thread.message_loop_proxy(),
+ NULL,
+ audio_thread.message_loop_proxy(),
+ NULL,
+ video_thread.message_loop_proxy(),
+ media::cast::GetDefaultCastLoggingConfig()));
+
+ media::cast::AudioReceiverConfig audio_config =
+ media::cast::GetAudioReceiverConfig();
+ media::cast::VideoReceiverConfig video_config =
+ media::cast::GetVideoReceiverConfig();
+
+ scoped_ptr<media::cast::test::Transport> transport(
+ new media::cast::test::Transport(main_message_loop.message_loop_proxy()));
+ scoped_ptr<media::cast::CastReceiver> cast_receiver(
+ media::cast::CastReceiver::CreateCastReceiver(
+ cast_environment,
+ audio_config,
+ video_config,
+ transport->packet_sender()));
+
+ media::cast::PacketReceiver* packet_receiver =
+ cast_receiver->packet_receiver();
+
+ int send_to_port, receive_port;
+ media::cast::GetPorts(&send_to_port, &receive_port);
+ std::string ip_address = media::cast::GetIpAddress("Enter destination IP.");
+ std::string local_ip_address = media::cast::GetIpAddress("Enter local IP.");
+ transport->SetLocalReceiver(packet_receiver, ip_address, local_ip_address,
+ receive_port);
+ transport->SetSendDestination(ip_address, send_to_port);
+
+ scoped_refptr<media::cast::ReceiveProcess> receive_process(
+ new media::cast::ReceiveProcess(cast_receiver->frame_receiver()));
+ receive_process->Start();
+ main_message_loop.Run();
+ transport->StopReceiving();
+ return 0;
+}