15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/codec_test.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_decoder.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_encoder.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing webrtc::BasicDesktopFrame; 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing webrtc::DesktopFrame; 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using webrtc::DesktopRect; 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using webrtc::DesktopRegion; 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using webrtc::DesktopSize; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBytesPerPixel = 4; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some sample rects for testing. 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<std::vector<DesktopRect> > MakeTestRectLists(DesktopSize size) { 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::vector<DesktopRect> > rect_lists; 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<DesktopRect> rects; 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rects.push_back(DesktopRect::MakeXYWH(0, 0, size.width(), size.height())); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect_lists.push_back(rects); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rects.clear(); 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rects.push_back(DesktopRect::MakeXYWH( 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 0, 0, size.width() / 2, size.height() / 2)); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect_lists.push_back(rects); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rects.clear(); 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rects.push_back(DesktopRect::MakeXYWH( 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size.width() / 2, size.height() / 2, 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size.width() / 2, size.height() / 2)); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect_lists.push_back(rects); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rects.clear(); 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rects.push_back(DesktopRect::MakeXYWH(16, 16, 16, 16)); 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rects.push_back(DesktopRect::MakeXYWH(128, 64, 32, 32)); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rect_lists.push_back(rects); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rect_lists; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDecoderTester { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VideoDecoderTester(VideoDecoder* decoder, 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopSize& screen_size, 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopSize& view_size) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : screen_size_(screen_size), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_size_(view_size), 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strict_(false), 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) decoder_(decoder), 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) frame_(NULL) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_data_.reset(new uint8[ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_size_.width() * view_size_.height() * kBytesPerPixel]); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(image_data_.get()); 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_->Initialize( 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopSize(screen_size_.width(), screen_size_.height())); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset() { 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_region_.Clear(); 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) update_region_.Clear(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResetRenderedData() { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(image_data_.get(), 0, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_size_.width() * view_size_.height() * kBytesPerPixel); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReceivedPacket(VideoPacket* packet) { 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ASSERT_TRUE(decoder_->DecodePacket(*packet)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) RenderFrame(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RenderFrame() { 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_->RenderFrame( 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopSize(view_size_.width(), view_size_.height()), 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopRect::MakeWH(view_size_.width(), view_size_.height()), 92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) image_data_.get(), view_size_.width() * kBytesPerPixel, 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &update_region_); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReceivedPacket(packet.get()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_strict(bool strict) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strict_ = strict; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void set_frame(DesktopFrame* frame) { 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame_ = frame; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void AddRects(const DesktopRect* rects, int count) { 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int i = 0; i < count; ++i) { 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_region_.AddRect(rects[i]); 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void AddRegion(const DesktopRegion& region) { 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_region_.AddRegion(region); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VerifyResults() { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!strict_) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_TRUE(frame_); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test the content of the update region. 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) EXPECT_TRUE(expected_region_.Equals(update_region_)); 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (DesktopRegion::Iterator i(update_region_); !i.IsAtEnd(); 128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) i.Advance()) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int stride = view_size_.width() * kBytesPerPixel; 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_EQ(stride, frame_->stride()); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int offset = stride * i.rect().top() + 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBytesPerPixel * i.rect().left(); 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const uint8* original = frame_->data() + offset; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* decoded = image_data_.get() + offset; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int row_size = kBytesPerPixel * i.rect().width(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < i.rect().height(); ++y) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, memcmp(original, decoded, row_size)) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Row " << y << " is different"; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original += stride; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded += stride; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The error at each pixel is the root mean square of the errors in 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the R, G, and B components, each normalized to [0, 1]. This routine 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checks that the maximum and mean pixel errors do not exceed given limits. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void VerifyResultsApprox(const uint8* expected_view_data, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max_error_limit, double mean_error_limit) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max_error = 0.0; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double sum_error = 0.0; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error_num = 0; 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (DesktopRegion::Iterator i(update_region_); !i.IsAtEnd(); 154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) i.Advance()) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int stride = view_size_.width() * kBytesPerPixel; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int offset = stride * i.rect().top() + 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBytesPerPixel * i.rect().left(); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* expected = expected_view_data + offset; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* actual = image_data_.get() + offset; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < i.rect().height(); ++y) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = 0; x < i.rect().width(); ++x) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double error = CalculateError(expected, actual); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_error = std::max(max_error, error); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum_error += error; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++error_num; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected += 4; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) actual += 4; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LE(max_error, max_error_limit); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double mean_error = sum_error / error_num; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LE(mean_error, mean_error_limit); 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Max error: " << max_error; 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Mean error: " << mean_error; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double CalculateError(const uint8* original, const uint8* decoded) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double error_sum_squares = 0.0; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < 3; i++) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double error = static_cast<double>(*original++) - 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<double>(*decoded++); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error /= 255.0; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_sum_squares += error * error; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original++; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded++; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sqrt(error_sum_squares / 3.0); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DesktopSize screen_size_; 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DesktopSize view_size_; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool strict_; 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopRegion expected_region_; 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopRegion update_region_; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoder* decoder_; 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<uint8[]> image_data_; 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopFrame* frame_; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoDecoderTester); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The VideoEncoderTester provides a hook for retrieving the data, and passing 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the message to other subprograms for validaton. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoEncoderTester { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoEncoderTester() 209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) : decoder_tester_(NULL), 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_available_(0) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~VideoEncoderTester() { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(data_available_, 0); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DataAvailable(scoped_ptr<VideoPacket> packet) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++data_available_; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send the message to the VideoDecoderTester. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_tester_) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester_->ReceivedPacket(packet.get()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_decoder_tester(VideoDecoderTester* decoder_tester) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester_ = decoder_tester; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoderTester* decoder_tester_; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_available_; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(VideoEncoderTester); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_ptr<DesktopFrame> PrepareFrame(const DesktopSize& size) { 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<DesktopFrame> frame(new BasicDesktopFrame(size)); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srand(0); 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int memory_size = size.width() * size.height() * kBytesPerPixel; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < memory_size; ++i) { 24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->data()[i] = rand() % 256; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return frame.Pass(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestEncodingRects(VideoEncoder* encoder, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoEncoderTester* tester, 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) webrtc::DesktopFrame* frame, 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopRect* rects, 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int count) { 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->mutable_updated_region()->Clear(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < count; ++i) { 25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->mutable_updated_region()->AddRect(rects[i]); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoPacket> packet = encoder->Encode(*frame); 259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tester->DataAvailable(packet.Pass()); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoder(VideoEncoder* encoder, bool strict) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kSizes[] = {320, 319, 317, 150}; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoEncoderTester tester; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t xi = 0; xi < arraysize(kSizes); ++xi) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t yi = 0; yi < arraysize(kSizes); ++yi) { 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DesktopSize size = DesktopSize(kSizes[xi], kSizes[yi]); 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<webrtc::DesktopFrame> frame = PrepareFrame(size); 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::vector<DesktopRect> > test_rect_lists = 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTestRectLists(size); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < test_rect_lists.size(); ++i) { 27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<DesktopRect>& test_rects = test_rect_lists[i]; 27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TestEncodingRects(encoder, &tester, frame.get(), 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &test_rects[0], test_rects.size()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestEncodeDecodeRects(VideoEncoder* encoder, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoEncoderTester* encoder_tester, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoderTester* decoder_tester, 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopFrame* frame, 28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopRect* rects, int count) { 28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->mutable_updated_region()->Clear(); 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int i = 0; i < count; ++i) { 28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->mutable_updated_region()->AddRect(rects[i]); 29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester->AddRects(rects, count); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate random data for the updated region. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) srand(0); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < count; ++i) { 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int row_size = 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopFrame::kBytesPerPixel * rects[i].width(); 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uint8* memory = frame->data() + 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->stride() * rects[i].top() + 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopFrame::kBytesPerPixel * rects[i].left(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < rects[i].height(); ++y) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int x = 0; x < row_size; ++x) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memory[x] = rand() % 256; 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) memory += frame->stride(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoPacket> packet = encoder->Encode(*frame); 309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) encoder_tester->DataAvailable(packet.Pass()); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester->VerifyResults(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester->Reset(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoderDecoder( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoEncoder* encoder, VideoDecoder* decoder, bool strict) { 31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DesktopSize kSize = DesktopSize(320, 240); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) VideoEncoderTester encoder_tester; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<DesktopFrame> frame = PrepareFrame(kSize); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoderTester decoder_tester(decoder, kSize, kSize); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester.set_strict(strict); 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_tester.set_frame(frame.get()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoder_tester.set_decoder_tester(&decoder_tester); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::vector<std::vector<DesktopRect> > test_rect_lists = 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MakeTestRectLists(kSize); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < test_rect_lists.size(); ++i) { 33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::vector<DesktopRect> test_rects = test_rect_lists[i]; 33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester, 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame.get(), &test_rects[0], test_rects.size()); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic void FillWithGradient(DesktopFrame* frame) { 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int j = 0; j < frame->size().height(); ++j) { 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uint8* p = frame->data() + j * frame->stride(); 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (int i = 0; i < frame->size().width(); ++i) { 34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *p++ = (255.0 * i) / frame->size().width(); 34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *p++ = (164.0 * j) / frame->size().height(); 34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *p++ = (82.0 * (i + j)) / 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (frame->size().width() + frame->size().height()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p++ = 0; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoderDecoderGradient(VideoEncoder* encoder, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoder* decoder, 35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopSize& screen_size, 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const DesktopSize& view_size, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double max_error_limit, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double mean_error_limit) { 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<BasicDesktopFrame> frame( 356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BasicDesktopFrame(screen_size)); 35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FillWithGradient(frame.get()); 35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(screen_size)); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<BasicDesktopFrame> expected_result( 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BasicDesktopFrame(view_size)); 36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FillWithGradient(expected_result.get()); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoDecoderTester decoder_tester(decoder, screen_size, view_size); 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_tester.set_frame(frame.get()); 36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_tester.AddRegion(frame->updated_region()); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scoped_ptr<VideoPacket> packet = encoder->Encode(*frame); 369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) decoder_tester.ReceivedScopedPacket(packet.Pass()); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_tester.VerifyResultsApprox(expected_result->data(), 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_error_limit, mean_error_limit); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check that the decoder correctly re-renders the frame if its client 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalidates the frame. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester.ResetRenderedData(); 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder->Invalidate( 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopSize(view_size.width(), view_size.height()), 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopRegion( 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DesktopRect::MakeWH(view_size.width(), view_size.height()))); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_tester.RenderFrame(); 38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) decoder_tester.VerifyResultsApprox(expected_result->data(), 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_error_limit, mean_error_limit); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfloat MeasureVideoEncoderFpsWithSize(VideoEncoder* encoder, 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const DesktopSize& size) { 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<DesktopFrame> frame(PrepareFrame(size)); 389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(size)); 390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::list<DesktopFrame*> frames; 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frames.push_back(frame.get()); 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return MeasureVideoEncoderFpsWithFrames(encoder, frames); 393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfloat MeasureVideoEncoderFpsWithFrames(VideoEncoder* encoder, 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::list<DesktopFrame*>& frames) { 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(1); 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 399116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Encode some frames to "warm up" the encoder (i.e. to let it set up initial 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // structures, establish a stable working set, etc), then encode at least 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // kMinimumFrameCount frames to measure the encoder's performance. 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int kWarmUpFrameCount = 10; 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int kMinimumFrameCount = 10; 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeTicks start_time; 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta elapsed; 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::list<DesktopFrame*> test_frames; 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int frame_count; 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (frame_count = 0; 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (frame_count < kMinimumFrameCount + kWarmUpFrameCount || 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch elapsed < kTestTime); 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++frame_count) { 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (frame_count == kWarmUpFrameCount) { 413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch start_time = base::TimeTicks::Now(); 414116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (test_frames.empty()) { 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch test_frames = frames; 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 419116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<VideoPacket> packet = encoder->Encode(*test_frames.front()); 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch test_frames.pop_front(); 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (frame_count >= kWarmUpFrameCount) { 423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch elapsed = base::TimeTicks::Now() - start_time; 424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (frame_count * base::TimeDelta::FromSeconds(1)) / elapsed; 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 431