blob: 9d05dd510b4b988cff2a97caab478579a999afb0 [file] [log] [blame]
// 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/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_YV12;
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_YV12;
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