codec_test.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using webrtc::DesktopRect;
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using webrtc::DesktopSize;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBytesPerPixel = 4;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some sample rects for testing.
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::vector<std::vector<DesktopRect> > MakeTestRectLists(DesktopSize size) {
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::vector<DesktopRect> > rect_lists;
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<DesktopRect> rects;
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rects.push_back(DesktopRect::MakeXYWH(0, 0, size.width(), size.height()));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect_lists.push_back(rects);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rects.clear();
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rects.push_back(DesktopRect::MakeXYWH(
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      0, 0, size.width() / 2, size.height() / 2));
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect_lists.push_back(rects);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rects.clear();
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rects.push_back(DesktopRect::MakeXYWH(
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      size.width() / 2, size.height() / 2,
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      size.width() / 2, size.height() / 2));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect_lists.push_back(rects);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rects.clear();
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rects.push_back(DesktopRect::MakeXYWH(16, 16, 16, 16));
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  rects.push_back(DesktopRect::MakeXYWH(128, 64, 32, 32));
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rect_lists.push_back(rects);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rect_lists;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class to test the message output of the encoder.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoEncoderMessageTester {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderMessageTester()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : begin_rect_(0),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rect_data_(0),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        end_rect_(0),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        added_rects_(0),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        state_(kWaitingForBeginRect),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        strict_(false) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~VideoEncoderMessageTester() {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(begin_rect_, end_rect_);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(begin_rect_, 0);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kWaitingForBeginRect, state_);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (strict_) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(added_rects_, begin_rect_);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that we received the correct packet.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReceivedPacket(VideoPacket* packet) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state_ == kWaitingForBeginRect) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_TRUE((packet->flags() & VideoPacket::FIRST_PACKET) != 0);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = kWaitingForRectData;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++begin_rect_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (strict_) {
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        DesktopRect rect = rects_.front();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rects_.pop_front();
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        EXPECT_EQ(rect.left(), packet->format().x());
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        EXPECT_EQ(rect.top(), packet->format().y());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(rect.width(), packet->format().width());
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(rect.height(), packet->format().height());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_FALSE((packet->flags() & VideoPacket::FIRST_PACKET) != 0);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (state_ == kWaitingForRectData) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (packet->has_data()) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++rect_data_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((packet->flags() & VideoPacket::LAST_PACKET) != 0) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Expect that we have received some data.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_GT(rect_data_, 0);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rect_data_ = 0;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        state_ = kWaitingForBeginRect;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++end_rect_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // LAST_PARTITION must always be marked with LAST_PACKET.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_TRUE((packet->flags() & VideoPacket::LAST_PACKET) != 0);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_strict(bool strict) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strict_ = strict;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddRects(const DesktopRect* rects, int count) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rects_.insert(rects_.begin() + rects_.size(), rects, rects + count);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    added_rects_ += count;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kWaitingForBeginRect,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kWaitingForRectData,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int begin_rect_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rect_data_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int end_rect_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int added_rects_;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State state_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool strict_;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::deque<DesktopRect> rects_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VideoEncoderMessageTester);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDecoderTester {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VideoDecoderTester(VideoDecoder* decoder,
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     const DesktopSize& screen_size,
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     const DesktopSize& view_size)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : screen_size_(screen_size),
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view_size_(view_size),
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        strict_(false),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoder_(decoder) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_data_.reset(new uint8[
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view_size_.width() * view_size_.height() * kBytesPerPixel]);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(image_data_.get());
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    decoder_->Initialize(
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        SkISize::Make(screen_size_.width(), screen_size_.height()));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset() {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    expected_region_.Clear();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    update_region_.setEmpty();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ResetRenderedData() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(image_data_.get(), 0,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           view_size_.width() * view_size_.height() * kBytesPerPixel);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReceivedPacket(VideoPacket* packet) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoDecoder::DecodeResult result = decoder_->DecodePacket(packet);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(VideoDecoder::DECODE_ERROR, result);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == VideoDecoder::DECODE_DONE) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RenderFrame();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RenderFrame() {
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    decoder_->RenderFrame(
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        SkISize::Make(view_size_.width(), view_size_.height()),
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        SkIRect::MakeWH(view_size_.width(), view_size_.height()),
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        image_data_.get(),
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        view_size_.width() * kBytesPerPixel,
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        &update_region_);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReceivedScopedPacket(scoped_ptr<VideoPacket> packet) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReceivedPacket(packet.get());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_strict(bool strict) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strict_ = strict;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void set_frame(webrtc::DesktopFrame* frame) {
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    frame_ = frame;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddRects(const DesktopRect* rects, int count) {
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (int i = 0; i < count; ++i) {
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      expected_region_.AddRect(rects[i]);
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddRegion(const webrtc::DesktopRegion& region) {
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    expected_region_.AddRegion(region);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyResults() {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!strict_)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(frame_);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test the content of the update region.
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    //
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(sergeyu): Change this to use DesktopRegion when it's capable of
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // merging the rectangles.
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SkRegion expected_region;
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (webrtc::DesktopRegion::Iterator it(expected_region_);
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         !it.IsAtEnd(); it.Advance()) {
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      expected_region.op(
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          SkIRect::MakeXYWH(it.rect().top(), it.rect().left(),
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            it.rect().width(), it.rect().height()),
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SkRegion::kUnion_Op);
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EXPECT_EQ(expected_region, update_region_);
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int stride = view_size_.width() * kBytesPerPixel;
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      EXPECT_EQ(stride, frame_->stride());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int offset =  stride * i.rect().top() +
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kBytesPerPixel * i.rect().left();
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const uint8* original = frame_->data() + offset;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint8* decoded = image_data_.get() + offset;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int row_size = kBytesPerPixel * i.rect().width();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int y = 0; y < i.rect().height(); ++y) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(0, memcmp(original, decoded, row_size))
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "Row " << y << " is different";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        original += stride;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoded += stride;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The error at each pixel is the root mean square of the errors in
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the R, G, and B components, each normalized to [0, 1]. This routine
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // checks that the maximum and mean pixel errors do not exceed given limits.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyResultsApprox(const uint8* expected_view_data,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           double max_error_limit, double mean_error_limit) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double max_error = 0.0;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double sum_error = 0.0;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error_num = 0;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (SkRegion::Iterator i(update_region_); !i.done(); i.next()) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int stride = view_size_.width() * kBytesPerPixel;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int offset =  stride * i.rect().top() +
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kBytesPerPixel * i.rect().left();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint8* expected = expected_view_data + offset;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const uint8* actual = image_data_.get() + offset;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int y = 0; y < i.rect().height(); ++y) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int x = 0; x < i.rect().width(); ++x) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          double error = CalculateError(expected, actual);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          max_error = std::max(max_error, error);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sum_error += error;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++error_num;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          expected += 4;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          actual += 4;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(max_error, max_error_limit);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double mean_error = sum_error / error_num;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_LE(mean_error, mean_error_limit);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Max error: " << max_error;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << "Mean error: " << mean_error;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double CalculateError(const uint8* original, const uint8* decoded) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    double error_sum_squares = 0.0;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 3; i++) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      double error = static_cast<double>(*original++) -
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     static_cast<double>(*decoded++);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error /= 255.0;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error_sum_squares += error * error;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    original++;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoded++;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sqrt(error_sum_squares / 3.0);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DesktopSize screen_size_;
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DesktopSize view_size_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool strict_;
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  webrtc::DesktopRegion expected_region_;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkRegion update_region_;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecoder* decoder_;
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> image_data_;
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  webrtc::DesktopFrame* frame_;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VideoDecoderTester);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The VideoEncoderTester provides a hook for retrieving the data, and passing
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the message to other subprograms for validaton.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoEncoderTester {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderTester(VideoEncoderMessageTester* message_tester)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : message_tester_(message_tester),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        decoder_tester_(NULL),
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_available_(0) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~VideoEncoderTester() {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_GT(data_available_, 0);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DataAvailable(scoped_ptr<VideoPacket> packet) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++data_available_;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_tester_->ReceivedPacket(packet.get());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Send the message to the VideoDecoderTester.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (decoder_tester_) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      decoder_tester_->ReceivedPacket(packet.get());
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddRects(const DesktopRect* rects, int count) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_tester_->AddRects(rects, count);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_decoder_tester(VideoDecoderTester* decoder_tester) {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decoder_tester_ = decoder_tester;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderMessageTester* message_tester_;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecoderTester* decoder_tester_;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data_available_;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(VideoEncoderTester);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_ptr<webrtc::DesktopFrame> PrepareFrame(const DesktopSize& size) {
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<webrtc::DesktopFrame> frame(new webrtc::BasicDesktopFrame(size));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srand(0);
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int memory_size = size.width() * size.height() * kBytesPerPixel;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < memory_size; ++i) {
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    frame->data()[i] = rand() % 256;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return frame.Pass();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestEncodingRects(VideoEncoder* encoder,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              VideoEncoderTester* tester,
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              webrtc::DesktopFrame* frame,
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              const DesktopRect* rects,
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              int count) {
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  frame->mutable_updated_region()->Clear();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < count; ++i) {
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    frame->mutable_updated_region()->AddRect(rects[i]);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tester->AddRects(rects, count);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  encoder->Encode(frame, base::Bind(
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &VideoEncoderTester::DataAvailable, base::Unretained(tester)));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoder(VideoEncoder* encoder, bool strict) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSizes[] = {320, 319, 317, 150};
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderMessageTester message_tester;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_tester.set_strict(strict);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderTester tester(&message_tester);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t xi = 0; xi < arraysize(kSizes); ++xi) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t yi = 0; yi < arraysize(kSizes); ++yi) {
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      DesktopSize size = DesktopSize(kSizes[xi], kSizes[yi]);
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      scoped_ptr<webrtc::DesktopFrame> frame = PrepareFrame(size);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::vector<std::vector<DesktopRect> > test_rect_lists =
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          MakeTestRectLists(size);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < test_rect_lists.size(); ++i) {
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        const std::vector<DesktopRect>& test_rects = test_rect_lists[i];
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TestEncodingRects(encoder, &tester, frame.get(),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &test_rects[0], test_rects.size());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestEncodeDecodeRects(VideoEncoder* encoder,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  VideoEncoderTester* encoder_tester,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  VideoDecoderTester* decoder_tester,
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  webrtc::DesktopFrame* frame,
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                  const DesktopRect* rects, int count) {
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  frame->mutable_updated_region()->Clear();
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (int i = 0; i < count; ++i) {
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    frame->mutable_updated_region()->AddRect(rects[i]);
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoder_tester->AddRects(rects, count);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester->AddRects(rects, count);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate random data for the updated region.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  srand(0);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < count; ++i) {
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const int row_size =
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        webrtc::DesktopFrame::kBytesPerPixel * rects[i].width();
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint8* memory = frame->data() +
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      frame->stride() * rects[i].top() +
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      webrtc::DesktopFrame::kBytesPerPixel * rects[i].left();
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int y = 0; y < rects[i].height(); ++y) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int x = 0; x < row_size; ++x)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memory[x] = rand() % 256;
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      memory += frame->stride();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  encoder->Encode(frame, base::Bind(&VideoEncoderTester::DataAvailable,
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    base::Unretained(encoder_tester)));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester->VerifyResults();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester->Reset();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoderDecoder(
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoEncoder* encoder, VideoDecoder* decoder, bool strict) {
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DesktopSize kSize = DesktopSize(320, 240);
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderMessageTester message_tester;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_tester.set_strict(strict);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoEncoderTester encoder_tester(&message_tester);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<webrtc::DesktopFrame> frame = PrepareFrame(kSize);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecoderTester decoder_tester(decoder, kSize, kSize);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester.set_strict(strict);
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder_tester.set_frame(frame.get());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  encoder_tester.set_decoder_tester(&decoder_tester);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::vector<DesktopRect> > test_rect_lists =
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      MakeTestRectLists(kSize);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test_rect_lists.size(); ++i) {
44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::vector<DesktopRect> test_rects = test_rect_lists[i];
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    TestEncodeDecodeRects(encoder, &encoder_tester, &decoder_tester,
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          frame.get(), &test_rects[0], test_rects.size());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void FillWithGradient(webrtc::DesktopFrame* frame) {
45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (int j = 0; j < frame->size().height(); ++j) {
45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint8* p = frame->data() + j * frame->stride();
45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (int i = 0; i < frame->size().width(); ++i) {
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *p++ = (255.0 * i) / frame->size().width();
45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *p++ = (164.0 * j) / frame->size().height();
45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *p++ = (82.0 * (i + j)) /
45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          (frame->size().width() + frame->size().height());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *p++ = 0;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestVideoEncoderDecoderGradient(VideoEncoder* encoder,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     VideoDecoder* decoder,
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     const DesktopSize& screen_size,
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     const DesktopSize& view_size,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     double max_error_limit,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     double mean_error_limit) {
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<webrtc::BasicDesktopFrame> frame(
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new webrtc::BasicDesktopFrame(screen_size));
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FillWithGradient(frame.get());
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  frame->mutable_updated_region()->SetRect(DesktopRect::MakeSize(screen_size));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<webrtc::BasicDesktopFrame> expected_result(
47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new webrtc::BasicDesktopFrame(view_size));
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  FillWithGradient(expected_result.get());
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoDecoderTester decoder_tester(decoder, screen_size, view_size);
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder_tester.set_frame(frame.get());
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder_tester.AddRegion(frame->updated_region());
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  encoder->Encode(frame.get(),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::Bind(&VideoDecoderTester::ReceivedScopedPacket,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             base::Unretained(&decoder_tester)));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder_tester.VerifyResultsApprox(expected_result->data(),
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     max_error_limit, mean_error_limit);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that the decoder correctly re-renders the frame if its client
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidates the frame.
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester.ResetRenderedData();
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder->Invalidate(
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SkISize::Make(view_size.width(), view_size.height()),
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SkRegion(SkIRect::MakeWH(view_size.width(), view_size.height())));
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  decoder_tester.RenderFrame();
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  decoder_tester.VerifyResultsApprox(expected_result->data(),
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     max_error_limit, mean_error_limit);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
500