1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>
123f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <math.h>
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org
14fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org#include <sstream>
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string>
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
175e8ee6f8a182dd36d0c9f273f180d015a056cef4andrew@webrtc.org#include "webrtc/modules/video_capture/include/video_capture_factory.h"
18281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/test/testsupport/fileutils.h"
20281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/test/testsupport/frame_reader.h"
21281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/test/testsupport/frame_writer.h"
22281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/test/testsupport/perf_test.h"
23281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
24281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
25281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.h"
26281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/auto_test/primitives/general_primitives.h"
27281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/tb_external_transport.h"
28281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
29281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h"
30281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/vie_to_file_renderer.h"
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
32e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.orgenum { kWaitTimeForFinalDecodeMs = 100 };
33e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org
34e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org// Writes the frames to be encoded to file and tracks which frames are sent in
35e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org// external transport on the local side and reports them to the
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// FrameDropDetector class.
375600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.orgclass LocalRendererEffectFilter : public webrtc::ExternalRendererEffectFilter {
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
395600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org  LocalRendererEffectFilter(webrtc::ExternalRenderer* renderer,
405600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org                            FrameDropDetector* frame_drop_detector)
415600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org      : ExternalRendererEffectFilter(renderer),
425600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org        frame_drop_detector_(frame_drop_detector) {}
439d10769e109601915022fea44ec392645c3b0704wu@webrtc.org  int Transform(int size,
449d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                unsigned char* frame_buffer,
459d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                int64_t ntp_time_ms,
469d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                unsigned int timestamp,
479d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                unsigned int width,
485600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org                unsigned int height) {
495dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    frame_drop_detector_->ReportFrameState(
505dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        FrameDropDetector::kCreated,
519d10769e109601915022fea44ec392645c3b0704wu@webrtc.org        timestamp,
525dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        webrtc::TickTime::MicrosecondTimestamp());
535600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org    return webrtc::ExternalRendererEffectFilter::Transform(
549d10769e109601915022fea44ec392645c3b0704wu@webrtc.org        size, frame_buffer, ntp_time_ms, timestamp, width, height);
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameDropDetector* frame_drop_detector_;
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Tracks which frames are sent in external transport on the local side
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// and reports them to the FrameDropDetector class.
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass FrameSentCallback : public SendFrameCallback {
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit FrameSentCallback(FrameDropDetector* frame_drop_detector)
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      : frame_drop_detector_(frame_drop_detector) {}
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual ~FrameSentCallback() {}
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual void FrameSent(unsigned int rtp_timestamp) {
685dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    frame_drop_detector_->ReportFrameState(
695dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        FrameDropDetector::kSent,
705dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        rtp_timestamp,
715dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        webrtc::TickTime::MicrosecondTimestamp());
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameDropDetector* frame_drop_detector_;
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Tracks which frames are received in external transport on the remote side
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// and reports them to the FrameDropDetector class.
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass FrameReceivedCallback : public ReceiveFrameCallback {
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit FrameReceivedCallback(FrameDropDetector* frame_drop_detector)
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      : frame_drop_detector_(frame_drop_detector) {}
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual ~FrameReceivedCallback() {}
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual void FrameReceived(unsigned int rtp_timestamp) {
865dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    frame_drop_detector_->ReportFrameState(
875dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        FrameDropDetector::kReceived,
885dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        rtp_timestamp,
895dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        webrtc::TickTime::MicrosecondTimestamp());
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameDropDetector* frame_drop_detector_;
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Tracks when frames are decoded on the remote side (received from the
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// jitter buffer) and reports them to the FrameDropDetector class.
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass DecodedTimestampEffectFilter : public webrtc::ViEEffectFilter {
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit DecodedTimestampEffectFilter(FrameDropDetector* frame_drop_detector)
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      : frame_drop_detector_(frame_drop_detector) {}
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual ~DecodedTimestampEffectFilter() {}
1039d10769e109601915022fea44ec392645c3b0704wu@webrtc.org  virtual int Transform(int size,
1049d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                        unsigned char* frame_buffer,
1059d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                        int64_t ntp_time_ms,
1069d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                        unsigned int timestamp,
1079d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                        unsigned int width,
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        unsigned int height) {
1095dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    frame_drop_detector_->ReportFrameState(
1105dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        FrameDropDetector::kDecoded,
1119d10769e109601915022fea44ec392645c3b0704wu@webrtc.org        timestamp,
1125dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org        webrtc::TickTime::MicrosecondTimestamp());
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameDropDetector* frame_drop_detector_;
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
120fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.orgclass Statistics {
121fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org public:
122fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  Statistics() : sum_(0.0f), sum_squared_(0.0f), count_(0) {};
123fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
124fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  void AddSample(float sample) {
125fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    sum_ += sample;
126fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    sum_squared_ += sample * sample;
127fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    ++count_;
128fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  }
129fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
130fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  float Mean() {
131fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    if (count_ == 0)
132fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org      return -1.0f;
133fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    return sum_ / count_;
134fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  }
135fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
136fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  float Variance() {
137fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    if (count_ == 0)
138fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org      return -1.0f;
139fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    return  sum_squared_ / count_ - Mean() * Mean();
140fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  }
141fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
142fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  std::string AsString() {
143fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    std::stringstream ss;
144fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    ss << (Mean() >= 0 ? Mean() : -1) << ", " <<
145fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org        (Variance() >= 0 ? sqrt(Variance()) : -1);
146fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    return ss.str();
147fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  }
148fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
149fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org private:
150fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  float sum_;
151fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  float sum_squared_;
152fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  int count_;
153fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org};
154fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid TestFullStack(const TbInterfaces& interfaces,
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   int capture_id,
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   int video_channel,
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   int width,
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   int height,
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   int bit_rate_kbps,
161137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org                   const NetworkParameters& network,
162e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org                   FrameDropDetector* frame_drop_detector,
163e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org                   ViEToFileRenderer* remote_file_renderer,
164e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org                   ViEToFileRenderer* local_file_renderer) {
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VideoEngine *video_engine_interface = interfaces.video_engine;
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViEBase *base_interface = interfaces.base;
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViECapture *capture_interface = interfaces.capture;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViERender *render_interface = interfaces.render;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViECodec *codec_interface = interfaces.codec;
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViENetwork *network_interface = interfaces.network;
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // ***************************************************************
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Engine ready. Begin testing class
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // ***************************************************************
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VideoCodec video_codec;
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memset(&video_codec, 0, sizeof (webrtc::VideoCodec));
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Set up all receive codecs. This basically setup the codec interface
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // to be able to recognize all receive codecs based on payload type.
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (int idx = 0; idx < codec_interface->NumberOfCodecs(); idx++) {
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    EXPECT_EQ(0, codec_interface->GetCodec(idx, video_codec));
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    SetSuitableResolution(&video_codec, width, height);
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    EXPECT_EQ(0, codec_interface->SetReceiveCodec(video_channel, video_codec));
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Configure External transport to simulate network interference:
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  TbExternalTransport external_transport(*interfaces.network, video_channel,
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         NULL);
190137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org  external_transport.SetNetworkParameters(network);
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameSentCallback frame_sent_callback(frame_drop_detector);
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameReceivedCallback frame_received_callback(frame_drop_detector);
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  external_transport.RegisterSendFrameCallback(&frame_sent_callback);
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  external_transport.RegisterReceiveFrameCallback(&frame_received_callback);
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, network_interface->RegisterSendTransport(video_channel,
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                        external_transport));
198e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  RenderToFile(interfaces.render, video_channel, remote_file_renderer);
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, base_interface->StartReceive(video_channel));
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Setup only the VP8 codec, which is what we'll use.
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VideoCodec codec;
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(FindSpecificCodec(webrtc::kVideoCodecVP8, codec_interface,
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                &codec));
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  codec.startBitrate = bit_rate_kbps;
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  codec.maxBitrate = bit_rate_kbps;
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  codec.width = width;
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  codec.height = height;
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, codec_interface->SetSendCodec(video_channel, codec));
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::ViEImageProcess *image_process =
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      webrtc::ViEImageProcess::GetInterface(video_engine_interface);
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_TRUE(image_process);
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
215e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Setup the effect filters.
216e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Local rendering at the send-side is done in an effect filter to avoid
217e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // synchronization issues with the remote renderer.
2185600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org  LocalRendererEffectFilter local_renderer_filter(local_file_renderer,
2195600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org                                                  frame_drop_detector);
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, image_process->RegisterSendEffectFilter(video_channel,
221e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org                                                       local_renderer_filter));
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  DecodedTimestampEffectFilter decode_filter(frame_drop_detector);
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, image_process->RegisterRenderEffectFilter(video_channel,
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                         decode_filter));
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Send video.
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, base_interface->StartSend(video_channel));
2273b7da1e4adc84f84f1896f91d697d43e7015fdf9asapersson@webrtc.org  AutoTestSleep(kAutoTestFullStackSleepTimeMs);
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Done!");
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // ***************************************************************
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Testing finished. Tear down Video Engine
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // ***************************************************************
234e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  EXPECT_EQ(0, capture_interface->DisconnectCaptureDevice(video_channel));
235e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org
236137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org  const int one_way_delay_99_percentile = network.mean_one_way_delay  +
237137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org        3 * network.std_dev_one_way_delay;
238137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org
239e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Wait for the last packet to arrive before we tear down the receiver.
240137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org  AutoTestSleep(2 * one_way_delay_99_percentile);
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, base_interface->StopSend(video_channel));
242e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  while (!external_transport.EmptyQueue()) {
243137ed6cceec64fbed8ac72fcbbf44b6e2bb15fa5stefan@webrtc.org    AutoTestSleep(one_way_delay_99_percentile);
244e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  }
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, base_interface->StopReceive(video_channel));
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, network_interface->DeregisterSendTransport(video_channel));
247e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Wait for the last frame to be decoded and rendered. There is no guarantee
248e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // this wait time will be long enough. Ideally we would wait for at least one
249e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // "receive-side delay", which is what the video coding module calculates
250e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // based on network statistics etc. We don't have access to that value here.
251e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  AutoTestSleep(kWaitTimeForFinalDecodeMs);
252e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Must stop the frame drop detectors in the right order to avoid getting
253e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // frames which for instance are rendered but not decoded.
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, render_interface->StopRender(video_channel));
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, render_interface->RemoveRenderer(video_channel));
256e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  EXPECT_EQ(0, image_process->DeregisterRenderEffectFilter(video_channel));
257e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  EXPECT_EQ(0, image_process->DeregisterSendEffectFilter(video_channel));
258e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  image_process->Release();
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  EXPECT_EQ(0, base_interface->DeleteChannel(video_channel));
260e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org
261e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  // Collect transport statistics.
26267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t num_rtp_packets = 0;
26367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t num_dropped_packets = 0;
26467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t num_rtcp_packets = 0;
265eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org  std::map<uint8_t, int> packet_counters;
266e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  external_transport.GetStats(num_rtp_packets, num_dropped_packets,
267eef4fd5c2263a5d9594c076c765abfe1e34b85f8stefan@webrtc.org                              num_rtcp_packets, &packet_counters);
268e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  ViETest::Log("RTP packets    : %5d", num_rtp_packets);
269e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  ViETest::Log("Dropped packets: %5d", num_dropped_packets);
270e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org  ViETest::Log("RTCP packets   : %5d", num_rtcp_packets);
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FixOutputFileForComparison(const std::string& output_file,
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int frame_length_in_bytes,
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                const std::vector<Frame*>& frames) {
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::test::FrameReaderImpl frame_reader(output_file,
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             frame_length_in_bytes);
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const std::string temp_file = output_file + ".fixed";
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::test::FrameWriterImpl frame_writer(temp_file, frame_length_in_bytes);
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_reader.Init();
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_writer.Init();
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ASSERT_FALSE(frames.front()->dropped_at_render) << "It should not be "
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "possible to drop the first frame. Both because we don't have anything "
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "useful to fill that gap with and it is impossible to detect it without "
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "any previous timestamps to compare with.";
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28867879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  uint8_t* last_frame_data = new uint8_t[frame_length_in_bytes];
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Process the file and write frame duplicates for all dropped frames.
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = frames.begin();
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != frames.end(); ++it) {
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((*it)->dropped_at_render) {
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Write the previous frame to the output file:
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      EXPECT_TRUE(frame_writer.WriteFrame(last_frame_data));
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      EXPECT_TRUE(frame_reader.ReadFrame(last_frame_data));
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      EXPECT_TRUE(frame_writer.WriteFrame(last_frame_data));
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete[] last_frame_data;
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_reader.Close();
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_writer.Close();
3043f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org  ASSERT_EQ(0, remove(output_file.c_str()));
3053f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org  ASSERT_EQ(0, rename(temp_file.c_str(), output_file.c_str()));
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3085dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.orgvoid FrameDropDetector::ReportFrameState(State state, unsigned int timestamp,
3095dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org                                         int64_t report_time_us) {
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dirty_ = true;
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (state) {
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kCreated: {
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      int number = created_frames_vector_.size();
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Frame* frame = new Frame(number, timestamp);
3155dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org      frame->created_timestamp_in_us_ = report_time_us;
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      created_frames_vector_.push_back(frame);
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      created_frames_[timestamp] = frame;
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_created_frames_++;
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kSent:
3225dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org      sent_frames_[timestamp] = report_time_us;
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (timestamp_diff_ == 0) {
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // When the first created frame arrives we calculate the fixed
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // difference between the timestamps of the frames entering and leaving
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // the encoder. This diff is used to identify the frames from the
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        // created_frames_ map.
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        timestamp_diff_ =
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org            timestamp - created_frames_vector_.front()->frame_timestamp_;
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_sent_frames_++;
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kReceived:
3345dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org      received_frames_[timestamp] = report_time_us;
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_received_frames_++;
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kDecoded:
3385dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org      decoded_frames_[timestamp] = report_time_us;
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_decoded_frames_++;
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRendered:
3425dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org      rendered_frames_[timestamp] = report_time_us;
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      num_rendered_frames_++;
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FrameDropDetector::CalculateResults() {
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Fill in all fields of the Frame objects in the created_frames_ map.
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Iterate over the maps from converted timestamps to the arrival timestamps.
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::map<unsigned int, int64_t>::const_iterator it;
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (it = sent_frames_.begin(); it != sent_frames_.end(); ++it) {
353e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org    unsigned int created_timestamp = it->first - timestamp_diff_;
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    created_frames_[created_timestamp]->sent_timestamp_in_us_ = it->second;
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (it = received_frames_.begin(); it != received_frames_.end(); ++it) {
357e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org    unsigned int created_timestamp = it->first - timestamp_diff_;
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    created_frames_[created_timestamp]->received_timestamp_in_us_ = it->second;
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (it = decoded_frames_.begin(); it != decoded_frames_.end(); ++it) {
361e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org    unsigned int created_timestamp = it->first - timestamp_diff_;
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    created_frames_[created_timestamp]->decoded_timestamp_in_us_ =it->second;
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (it = rendered_frames_.begin(); it != rendered_frames_.end(); ++it) {
365e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org    unsigned int created_timestamp = it->first - timestamp_diff_;
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    created_frames_[created_timestamp]->rendered_timestamp_in_us_ = it->second;
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Find out where the frames were not present in the different states.
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dropped_frames_at_send_ = 0;
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dropped_frames_at_receive_ = 0;
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dropped_frames_at_decode_ = 0;
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dropped_frames_at_render_ = 0;
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = created_frames_vector_.begin();
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != created_frames_vector_.end(); ++it) {
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int encoded_timestamp = (*it)->frame_timestamp_ + timestamp_diff_;
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (sent_frames_.find(encoded_timestamp) == sent_frames_.end()) {
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (*it)->dropped_at_send = true;
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      dropped_frames_at_send_++;
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (received_frames_.find(encoded_timestamp) == received_frames_.end()) {
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (*it)->dropped_at_receive = true;
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      dropped_frames_at_receive_++;
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (decoded_frames_.find(encoded_timestamp) == decoded_frames_.end()) {
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (*it)->dropped_at_decode = true;
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      dropped_frames_at_decode_++;
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (rendered_frames_.find(encoded_timestamp) == rendered_frames_.end()) {
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (*it)->dropped_at_render = true;
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      dropped_frames_at_render_++;
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  dirty_ = false;
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
396fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.orgvoid FrameDropDetector::PrintReport(const std::string& test_label) {
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(!dirty_);
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Frame Drop Detector report:");
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Created  frames: %ld", created_frames_.size());
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Sent     frames: %ld", sent_frames_.size());
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Received frames: %ld", received_frames_.size());
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Decoded  frames: %ld", decoded_frames_.size());
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Rendered frames: %ld", rendered_frames_.size());
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Display all frames and stats for them:
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  long last_created = 0;
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  long last_sent = 0;
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  long last_received = 0;
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  long last_decoded = 0;
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  long last_rendered = 0;
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("\nDeltas between sent frames and drop status:");
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Unit: Microseconds");
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Frame  Created    Sent    Received Decoded Rendered "
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "Dropped at  Dropped at  Dropped at  Dropped at");
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log(" nbr    delta     delta    delta    delta   delta   "
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      " Send?       Receive?    Decode?     Render?");
417eaa05c8e5401589db411b3e129c59dc976978472stefan@webrtc.org  Statistics rendering_stats;
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = created_frames_vector_.begin();
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != created_frames_vector_.end(); ++it) {
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int created_delta =
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->created_timestamp_in_us_ - last_created);
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int sent_delta = (*it)->dropped_at_send ? -1 :
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->sent_timestamp_in_us_ - last_sent);
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int received_delta = (*it)->dropped_at_receive ? -1 :
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->received_timestamp_in_us_ - last_received);
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int decoded_delta = (*it)->dropped_at_decode ? -1 :
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->decoded_timestamp_in_us_ - last_decoded);
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int rendered_delta = (*it)->dropped_at_render ? -1 :
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->rendered_timestamp_in_us_ - last_rendered);
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Set values to -1 for the first frame:
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((*it)->number_ == 0) {
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      created_delta = -1;
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sent_delta = -1;
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      received_delta = -1;
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      decoded_delta = -1;
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      rendered_delta = -1;
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ViETest::Log("%5d %8d %8d %8d %8d %8d %10s %10s %10s %10s",
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->number_,
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 created_delta,
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 sent_delta,
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 received_delta,
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 decoded_delta,
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 rendered_delta,
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->dropped_at_send ? "DROPPED" : "      ",
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->dropped_at_receive ? "DROPPED" : "      ",
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->dropped_at_decode ? "DROPPED" : "      ",
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->dropped_at_render ? "DROPPED" : "      ");
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    last_created = (*it)->created_timestamp_in_us_;
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!(*it)->dropped_at_send) {
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      last_sent = (*it)->sent_timestamp_in_us_;
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org     if (!(*it)->dropped_at_receive) {
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      last_received = (*it)->received_timestamp_in_us_;
456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!(*it)->dropped_at_decode) {
458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      last_decoded = (*it)->decoded_timestamp_in_us_;
459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (!(*it)->dropped_at_render) {
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      last_rendered = (*it)->rendered_timestamp_in_us_;
462eaa05c8e5401589db411b3e129c59dc976978472stefan@webrtc.org      rendering_stats.AddSample(rendered_delta / 1000.0f);
463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("\nLatency between states (-1 means N/A because of drop):");
466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Unit: Microseconds");
467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Frame  Created    Sent      Received   Decoded      Total    "
468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "   Total");
469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log(" nbr   ->Sent  ->Received  ->Decoded ->Rendered    latency   "
470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "  latency");
471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("                                               (incl network)"
472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "(excl network)");
473fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  Statistics latency_incl_network_stats;
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = created_frames_vector_.begin();
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != created_frames_vector_.end(); ++it) {
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int created_to_sent = (*it)->dropped_at_send ? -1 :
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->sent_timestamp_in_us_ -
478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->created_timestamp_in_us_);
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int sent_to_received = (*it)->dropped_at_receive ? -1 :
480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->received_timestamp_in_us_ -
481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->sent_timestamp_in_us_);
482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int received_to_decoded = (*it)->dropped_at_decode ? -1 :
483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->decoded_timestamp_in_us_ -
484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->received_timestamp_in_us_);
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int decoded_to_render = (*it)->dropped_at_render ? -1 :
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->rendered_timestamp_in_us_ -
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->decoded_timestamp_in_us_);
488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int total_latency_incl_network = (*it)->dropped_at_render ? -1 :
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->rendered_timestamp_in_us_ -
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->created_timestamp_in_us_);
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int total_latency_excl_network = (*it)->dropped_at_render ? -1 :
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        static_cast<int>((*it)->rendered_timestamp_in_us_ -
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         (*it)->created_timestamp_in_us_ - sent_to_received);
494fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org    if (total_latency_incl_network >= 0)
495fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org      latency_incl_network_stats.AddSample(total_latency_incl_network /
496fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org                                           1000.0f);
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ViETest::Log("%5d %9d %9d %9d %9d %12d %12d",
498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->number_,
499b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 created_to_sent,
500b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 sent_to_received,
501b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 received_to_decoded,
502b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 decoded_to_render,
503b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 total_latency_incl_network,
504b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 total_latency_excl_network);
505b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
506fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
5076b04e5488d1b46fe1e12b6443b5238bfa7a13161phoglund@webrtc.org  // Plot all measurements in the same graph since they share the same value
5086b04e5488d1b46fe1e12b6443b5238bfa7a13161phoglund@webrtc.org  // range.
509fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org  webrtc::test::PrintResultMeanAndError(
5106b04e5488d1b46fe1e12b6443b5238bfa7a13161phoglund@webrtc.org      "total_delay_incl_network", "", test_label,
511fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org      latency_incl_network_stats.AsString(), "ms", false);
512eaa05c8e5401589db411b3e129c59dc976978472stefan@webrtc.org  webrtc::test::PrintResultMeanAndError(
5136b04e5488d1b46fe1e12b6443b5238bfa7a13161phoglund@webrtc.org      "time_between_rendered_frames", "", test_label,
514eaa05c8e5401589db411b3e129c59dc976978472stefan@webrtc.org      rendering_stats.AsString(), "ms", false);
515eaa05c8e5401589db411b3e129c59dc976978472stefan@webrtc.org
516fb2953b8f5d77b0e0f85fe11f8ae249f3bbbeafbstefan@webrtc.org
517b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Find and print the dropped frames.
518b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("\nTotal # dropped frames at:");
519b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Send   : %d", dropped_frames_at_send_);
520b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Receive: %d", dropped_frames_at_receive_);
521b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Decode : %d", dropped_frames_at_decode_);
522b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Render : %d", dropped_frames_at_render_);
523b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
524b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
525b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid FrameDropDetector::PrintDebugDump() {
526b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(!dirty_);
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("\nPrintDebugDump: Frame objects:");
528b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("Frame FrTimeStamp Created       Sent      Received    Decoded"
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      "    Rendered ");
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = created_frames_vector_.begin();
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != created_frames_vector_.end(); ++it) {
532e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org    ViETest::Log("%5d %11u %11lld %11lld %11lld %11lld %11lld",
533b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->number_,
534b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->frame_timestamp_,
535b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->created_timestamp_in_us_,
536b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->sent_timestamp_in_us_,
537b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->received_timestamp_in_us_,
538b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->decoded_timestamp_in_us_,
539b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 (*it)->rendered_timestamp_in_us_);
540b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
541b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::vector<int> mismatch_frame_num_list;
542b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (std::vector<Frame*>::const_iterator it = created_frames_vector_.begin();
543b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != created_frames_vector_.end(); ++it) {
544b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((*it)->dropped_at_render != (*it)->dropped_at_decode) {
545b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      mismatch_frame_num_list.push_back((*it)->number_);
546b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
547b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
548b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mismatch_frame_num_list.size() > 0) {
549b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ViETest::Log("\nDecoded/Rendered mismatches:");
550b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ViETest::Log("Frame FrTimeStamp    Created       Sent      Received    "
551b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        "Decoded    Rendered ");
552b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (std::vector<int>::const_iterator it = mismatch_frame_num_list.begin();
553b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         it != mismatch_frame_num_list.end(); ++it) {
554b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Frame* frame = created_frames_vector_[*it];
555e3ada29f8b0ea194ccd6b56faa9fdc5fb26c8bc5stefan@webrtc.org      ViETest::Log("%5d %11u %11lld %11lld %11lld %11lld %11lld",
556b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->number_,
557b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->frame_timestamp_,
558b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->created_timestamp_in_us_,
559b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->sent_timestamp_in_us_,
560b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->received_timestamp_in_us_,
561b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->decoded_timestamp_in_us_,
562b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 frame->rendered_timestamp_in_us_);
563b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
564b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
565b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
566b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("\nReportFrameState method invocations:");
567b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Created : %d", num_created_frames_);
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Send    : %d", num_sent_frames_);
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Received: %d", num_received_frames_);
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Decoded : %d", num_decoded_frames_);
571b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViETest::Log("  Rendered: %d", num_rendered_frames_);
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst std::vector<Frame*>& FrameDropDetector::GetAllFrames() {
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(!dirty_);
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return created_frames_vector_;
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint FrameDropDetector::GetNumberOfFramesDroppedAt(State state) {
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(!dirty_);
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (state) {
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kSent:
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return dropped_frames_at_send_;
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kReceived:
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return dropped_frames_at_receive_;
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kDecoded:
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return dropped_frames_at_decode_;
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRendered:
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return dropped_frames_at_render_;
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return 0;
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
593b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
594b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint FrameDropMonitoringRemoteFileRenderer::DeliverFrame(
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    unsigned char *buffer, int buffer_size, uint32_t time_stamp,
5979d10769e109601915022fea44ec392645c3b0704wu@webrtc.org    int64_t ntp_time_ms, int64_t render_time, void* /*handle*/) {
5985dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  // |render_time| provides the ideal render time for this frame. If that time
5995dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  // has already passed we will render it immediately.
6005dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  int64_t report_render_time_us = render_time * 1000;
6015dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  int64_t time_now_us = webrtc::TickTime::MicrosecondTimestamp();
6025dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  if (render_time < (time_now_us + 500) / 1000) {
6035dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org    report_render_time_us = time_now_us;
6045dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  }
6055dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org  // Register that this frame has been rendered.
606b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_drop_detector_->ReportFrameState(FrameDropDetector::kRendered,
6075dee0551c0a2d86cf524e80c033936d3827a20c6stefan@webrtc.org                                         time_stamp, report_render_time_us);
608b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return ViEToFileRenderer::DeliverFrame(buffer, buffer_size,
6099d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                                         time_stamp, ntp_time_ms,
6109d10769e109601915022fea44ec392645c3b0704wu@webrtc.org                                         render_time, NULL);
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint FrameDropMonitoringRemoteFileRenderer::FrameSizeChange(
614b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    unsigned int width, unsigned int height, unsigned int number_of_streams) {
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return ViEToFileRenderer::FrameSizeChange(width, height, number_of_streams);
616b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
617