1/*
2 *  Copyright (c) 2012 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 <assert.h>
12
13#include "webrtc/modules/video_coding/main/test/receiver_tests.h"
14#include "webrtc/modules/video_coding/main/test/vcm_payload_sink_factory.h"
15#include "webrtc/system_wrappers/interface/event_wrapper.h"
16#include "webrtc/system_wrappers/interface/thread_wrapper.h"
17#include "webrtc/system_wrappers/interface/trace.h"
18#include "webrtc/test/testsupport/fileutils.h"
19
20using webrtc::rtpplayer::RtpPlayerInterface;
21using webrtc::rtpplayer::VcmPayloadSinkFactory;
22
23namespace {
24
25const bool kConfigProtectionEnabled = true;
26const webrtc::VCMVideoProtection kConfigProtectionMethod =
27    webrtc::kProtectionDualDecoder;
28const float kConfigLossRate = 0.05f;
29const uint32_t kConfigRttMs = 50;
30const bool kConfigReordering = false;
31const uint32_t kConfigRenderDelayMs = 0;
32const uint32_t kConfigMinPlayoutDelayMs = 0;
33const int64_t kConfigMaxRuntimeMs = 10000;
34
35}  // namespace
36
37bool PlayerThread(void* obj) {
38  assert(obj);
39  RtpPlayerInterface* rtp_player = static_cast<RtpPlayerInterface*>(obj);
40
41  webrtc::scoped_ptr<webrtc::EventWrapper> wait_event(
42      webrtc::EventWrapper::Create());
43  if (wait_event.get() == NULL) {
44    return false;
45  }
46
47  webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock();
48  if (rtp_player->NextPacket(clock->TimeInMilliseconds()) < 0) {
49    return false;
50  }
51  wait_event->Wait(rtp_player->TimeUntilNextPacket());
52
53  return true;
54}
55
56bool ProcessingThread(void* obj) {
57  assert(obj);
58  return static_cast<VcmPayloadSinkFactory*>(obj)->ProcessAll();
59}
60
61bool DecodeThread(void* obj) {
62  assert(obj);
63  return static_cast<VcmPayloadSinkFactory*>(obj)->DecodeAll();
64}
65
66int RtpPlayMT(const CmdArgs& args) {
67  std::string trace_file = webrtc::test::OutputPath() + "receiverTestTrace.txt";
68  webrtc::Trace::CreateTrace();
69  webrtc::Trace::SetTraceFile(trace_file.c_str());
70  webrtc::Trace::set_level_filter(webrtc::kTraceAll);
71
72  webrtc::rtpplayer::PayloadTypes payload_types;
73  payload_types.push_back(webrtc::rtpplayer::PayloadCodecTuple(
74      VCM_VP8_PAYLOAD_TYPE, "VP8", webrtc::kVideoCodecVP8));
75
76  std::string output_file = args.outputFile;
77  if (output_file == "") {
78    output_file = webrtc::test::OutputPath() + "RtpPlayMT_decoded.yuv";
79  }
80
81  webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock();
82  VcmPayloadSinkFactory factory(output_file, clock, kConfigProtectionEnabled,
83      kConfigProtectionMethod, kConfigRttMs, kConfigRenderDelayMs,
84      kConfigMinPlayoutDelayMs);
85  webrtc::scoped_ptr<RtpPlayerInterface> rtp_player(webrtc::rtpplayer::Create(
86      args.inputFile, &factory, clock, payload_types, kConfigLossRate,
87      kConfigRttMs, kConfigReordering));
88  if (rtp_player.get() == NULL) {
89    return -1;
90  }
91
92  {
93    webrtc::scoped_ptr<webrtc::ThreadWrapper> player_thread(
94        webrtc::ThreadWrapper::CreateThread(PlayerThread, rtp_player.get(),
95            webrtc::kNormalPriority, "PlayerThread"));
96    if (player_thread.get() == NULL) {
97      printf("Unable to start RTP reader thread\n");
98      return -1;
99    }
100
101    webrtc::scoped_ptr<webrtc::ThreadWrapper> processing_thread(
102        webrtc::ThreadWrapper::CreateThread(ProcessingThread, &factory,
103            webrtc::kNormalPriority, "ProcessingThread"));
104    if (processing_thread.get() == NULL) {
105      printf("Unable to start processing thread\n");
106      return -1;
107    }
108
109    webrtc::scoped_ptr<webrtc::ThreadWrapper> decode_thread(
110        webrtc::ThreadWrapper::CreateThread(DecodeThread, &factory,
111            webrtc::kNormalPriority, "DecodeThread"));
112    if (decode_thread.get() == NULL) {
113      printf("Unable to start decode thread\n");
114      return -1;
115    }
116
117    webrtc::scoped_ptr<webrtc::EventWrapper> wait_event(
118        webrtc::EventWrapper::Create());
119    if (wait_event.get() == NULL) {
120      printf("Unable to create wait event\n");
121      return -1;
122    }
123
124    unsigned int dummy_thread_id;
125    player_thread->Start(dummy_thread_id);
126    processing_thread->Start(dummy_thread_id);
127    decode_thread->Start(dummy_thread_id);
128
129    wait_event->Wait(kConfigMaxRuntimeMs);
130
131    while (!player_thread->Stop()) {
132    }
133    while (!processing_thread->Stop()) {
134    }
135    while (!decode_thread->Stop()) {
136    }
137  }
138
139  rtp_player->Print();
140
141  webrtc::Trace::ReturnTrace();
142  return 0;
143}
144