summaryrefslogtreecommitdiff
path: root/chromium/media/mojo/common/mojo_shared_buffer_video_frame_unittest.cc
blob: 68f463f3014cf2201fba0380e216404aead22916 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/mojo/common/mojo_shared_buffer_video_frame.h"

#include <stddef.h>
#include <stdint.h>

#include <string>

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "mojo/public/cpp/system/buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"

namespace media {

namespace {

void CompareDestructionCallbackValues(
    mojo::SharedBufferHandle expected_handle,
    size_t expected_handle_size,
    bool* callback_called,
    mojo::ScopedSharedBufferHandle actual_handle,
    size_t actual_handle_size) {
  // Compare expected vs actual. Ownership of the memory is transferred with
  // |actual_handle|, thus it is a ScopedSharedBufferHandle.
  EXPECT_EQ(expected_handle, actual_handle.get());
  EXPECT_EQ(expected_handle_size, actual_handle_size);
  *callback_called = true;
}

}  // namespace

TEST(MojoSharedBufferVideoFrameTest, CreateFrameWithSharedMemory) {
  const int kWidth = 16;
  const int kHeight = 9;
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337);

  // Create a MojoSharedBufferVideoFrame which will allocate enough space
  // to hold a 16x9 video frame.
  gfx::Size size(kWidth, kHeight);
  scoped_refptr<MojoSharedBufferVideoFrame> frame =
      MojoSharedBufferVideoFrame::CreateDefaultI420(size, kTimestamp);
  ASSERT_TRUE(frame.get());

  // Verify that the correct frame was allocated.
  EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format());

  // The offsets should be set appropriately.
  EXPECT_EQ(frame->PlaneOffset(VideoFrame::kYPlane), 0u);
  EXPECT_GT(frame->PlaneOffset(VideoFrame::kUPlane), 0u);
  EXPECT_GT(frame->PlaneOffset(VideoFrame::kVPlane), 0u);

  // The strides should be set appropriately.
  EXPECT_EQ(frame->stride(VideoFrame::kYPlane), kWidth);
  EXPECT_EQ(frame->stride(VideoFrame::kUPlane), kWidth / 2);
  EXPECT_EQ(frame->stride(VideoFrame::kVPlane), kWidth / 2);

  // The data pointers for each plane should be set.
  EXPECT_TRUE(frame->data(VideoFrame::kYPlane));
  EXPECT_TRUE(frame->data(VideoFrame::kUPlane));
  EXPECT_TRUE(frame->data(VideoFrame::kVPlane));
}

TEST(MojoSharedBufferVideoFrameTest, CreateFrameAndPassSharedMemory) {
  const int kWidth = 32;
  const int kHeight = 18;
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1338);

  // Some random values to use. Since we actually don't use the data inside the
  // frame, random values are fine (as long as the offsets are within the
  // memory size allocated).
  const VideoPixelFormat format = PIXEL_FORMAT_I420;
  const size_t y_offset = kWidth * 2;
  const size_t u_offset = kWidth * 3;
  const size_t v_offset = kWidth * 5;
  const int32_t y_stride = kWidth;
  const int32_t u_stride = kWidth - 1;
  const int32_t v_stride = kWidth - 2;

  // Allocate some shared memory.
  gfx::Size size(kWidth, kHeight);
  gfx::Rect visible_rect(size);
  size_t requested_size = VideoFrame::AllocationSize(format, size);
  ASSERT_LT(y_offset, requested_size);
  mojo::ScopedSharedBufferHandle handle =
      mojo::SharedBufferHandle::Create(requested_size);
  ASSERT_TRUE(handle.is_valid());

  // Allocate frame.
  scoped_refptr<MojoSharedBufferVideoFrame> frame =
      MojoSharedBufferVideoFrame::Create(format, size, visible_rect, size,
                                         std::move(handle), requested_size,
                                         y_offset, u_offset, v_offset, y_stride,
                                         u_stride, v_stride, kTimestamp);
  ASSERT_TRUE(frame.get());
  EXPECT_EQ(frame->format(), format);

  // The offsets should be set appropriately.
  EXPECT_EQ(frame->PlaneOffset(VideoFrame::kYPlane), y_offset);
  EXPECT_EQ(frame->PlaneOffset(VideoFrame::kUPlane), u_offset);
  EXPECT_EQ(frame->PlaneOffset(VideoFrame::kVPlane), v_offset);

  // The strides should be set appropriately.
  EXPECT_EQ(frame->stride(VideoFrame::kYPlane), y_stride);
  EXPECT_EQ(frame->stride(VideoFrame::kUPlane), u_stride);
  EXPECT_EQ(frame->stride(VideoFrame::kVPlane), v_stride);

  // The data pointers for each plane should be set.
  EXPECT_TRUE(frame->data(VideoFrame::kYPlane));
  EXPECT_TRUE(frame->data(VideoFrame::kUPlane));
  EXPECT_TRUE(frame->data(VideoFrame::kVPlane));
}

TEST(MojoSharedBufferVideoFrameTest, CreateFrameOddWidth) {
  const int kWidth = 15;
  const int kHeight = 9;
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337);

  // Create a MojoSharedBufferVideoFrame which will allocate enough space
  // to hold the video frame. Size should be adjusted.
  gfx::Size size(kWidth, kHeight);
  scoped_refptr<MojoSharedBufferVideoFrame> frame =
      MojoSharedBufferVideoFrame::CreateDefaultI420(size, kTimestamp);
  ASSERT_TRUE(frame.get());

  // Verify that the correct frame was allocated.
  EXPECT_EQ(media::PIXEL_FORMAT_I420, frame->format());

  // The size should be >= 15x9.
  EXPECT_GE(frame->coded_size().width(), kWidth);
  EXPECT_GE(frame->coded_size().height(), kHeight);
}

TEST(MojoSharedBufferVideoFrameTest, TestDestructionCallback) {
  const VideoPixelFormat format = PIXEL_FORMAT_I420;
  const int kWidth = 32;
  const int kHeight = 18;
  const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1338);

  // Allocate some shared memory.
  gfx::Size size(kWidth, kHeight);
  gfx::Rect visible_rect(size);
  size_t requested_size = VideoFrame::AllocationSize(format, size);
  mojo::ScopedSharedBufferHandle handle =
      mojo::SharedBufferHandle::Create(requested_size);
  ASSERT_TRUE(handle.is_valid());

  // Keep track of the original handle. MojoSharedBufferVideoFrame::Create()
  // will get ownership of the memory.
  mojo::SharedBufferHandle original_handle = handle.get();

  // Allocate frame.
  scoped_refptr<MojoSharedBufferVideoFrame> frame =
      MojoSharedBufferVideoFrame::Create(
          format, size, visible_rect, size, std::move(handle), requested_size,
          0, 0, 0, kWidth, kWidth, kWidth, kTimestamp);
  ASSERT_TRUE(frame.get());
  EXPECT_EQ(frame->format(), format);

  // Set the destruction callback.
  bool callback_called = false;
  frame->SetMojoSharedBufferDoneCB(base::Bind(&CompareDestructionCallbackValues,
                                              original_handle, requested_size,
                                              &callback_called));
  EXPECT_FALSE(callback_called);

  // Force destruction of |frame|.
  frame = nullptr;
  EXPECT_TRUE(callback_called);
}

}  // namespace media