1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "base/memory/shared_memory_mapping.h"
11 #include "base/memory/unsafe_shared_memory_region.h"
12 #include "media/base/video_frame.h"
13 #include "media/cdm/api/content_decryption_module.h"
14 #include "media/cdm/cdm_helpers.h"
15 #include "media/mojo/services/mojo_cdm_allocator.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/gfx/geometry/size.h"
21 class MojoCdmAllocatorTest : public testing::Test {
23 MojoCdmAllocatorTest() = default;
25 MojoCdmAllocatorTest(const MojoCdmAllocatorTest&) = delete;
26 MojoCdmAllocatorTest& operator=(const MojoCdmAllocatorTest&) = delete;
28 ~MojoCdmAllocatorTest() override = default;
31 cdm::Buffer* CreateCdmBuffer(size_t capacity) {
32 return allocator_.CreateCdmBuffer(capacity);
35 std::unique_ptr<VideoFrameImpl> CreateCdmVideoFrame() {
36 return allocator_.CreateCdmVideoFrame();
39 const base::MappedReadOnlyRegion& GetRegion(cdm::Buffer* buffer) {
40 return allocator_.GetRegionForTesting(buffer);
43 size_t GetAvailableRegionCount() {
44 return allocator_.GetAvailableRegionCountForTesting();
48 MojoCdmAllocator allocator_;
51 TEST_F(MojoCdmAllocatorTest, CreateCdmBuffer) {
52 cdm::Buffer* buffer = CreateCdmBuffer(100);
53 EXPECT_GE(buffer->Capacity(), 100u);
55 EXPECT_EQ(50u, buffer->Size());
59 TEST_F(MojoCdmAllocatorTest, ReuseCdmBuffer) {
60 const size_t kRandomDataSize = 46;
62 const char kTestData[] = "reduce reuse recycle";
64 // Create a small buffer.
65 cdm::Buffer* buffer = CreateCdmBuffer(kRandomDataSize);
67 // Create a mapping and write some test data.
68 auto& mapping = GetRegion(buffer).mapping;
69 // Note: deliberately using sizeof() to include the null terminator.
70 memcpy(mapping.memory(), kTestData, sizeof(kTestData));
74 // Now allocate a new buffer of the same size, it should reuse the one
76 cdm::Buffer* new_buffer = CreateCdmBuffer(kRandomDataSize);
78 auto& mapping = GetRegion(new_buffer).mapping;
79 // Check that the test data that was written there is still there as a proxy
80 // signal for checking that the shmem region is reused.
81 EXPECT_STREQ(kTestData, mapping.GetMemoryAs<char>());
83 new_buffer->Destroy();
86 TEST_F(MojoCdmAllocatorTest, MaxFreeBuffers) {
87 const size_t kMaxExpectedFreeBuffers = 3;
88 size_t buffer_size = 0;
89 const size_t kBufferSizeIncrease = 1000;
90 std::vector<cdm::Buffer*> buffers;
92 // Allocate and destroy 10 buffers in increasing size (to avoid buffer reuse).
93 // Eventually allocating a new buffer will free the smallest free buffer, so
94 // the number of free buffers will be capped at |kMaxExpectedFreeBuffers|.
95 for (int i = 0; i < 10; ++i) {
96 buffer_size += kBufferSizeIncrease;
97 cdm::Buffer* buffer = CreateCdmBuffer(buffer_size);
99 EXPECT_LE(GetAvailableRegionCount(), kMaxExpectedFreeBuffers);
103 TEST_F(MojoCdmAllocatorTest, CreateCdmVideoFrame) {
104 const int kWidth = 16;
105 const int kHeight = 9;
106 const VideoPixelFormat kFormat = PIXEL_FORMAT_I420;
107 const gfx::Size kSize(kWidth, kHeight);
108 const size_t kBufferSize = VideoFrame::AllocationSize(kFormat, kSize);
110 // Create a VideoFrameImpl and initialize it.
111 std::unique_ptr<VideoFrameImpl> video_frame = CreateCdmVideoFrame();
112 video_frame->SetFormat(cdm::kI420);
113 video_frame->SetSize({kWidth, kHeight});
114 video_frame->SetStride(
115 cdm::kYPlane, static_cast<uint32_t>(
116 VideoFrame::RowBytes(cdm::kYPlane, kFormat, kWidth)));
117 video_frame->SetStride(
118 cdm::kUPlane, static_cast<uint32_t>(
119 VideoFrame::RowBytes(cdm::kUPlane, kFormat, kWidth)));
120 video_frame->SetStride(
121 cdm::kVPlane, static_cast<uint32_t>(
122 VideoFrame::RowBytes(cdm::kVPlane, kFormat, kWidth)));
123 EXPECT_EQ(nullptr, video_frame->FrameBuffer());
125 // Now create a buffer to hold the frame and assign it to the VideoFrameImpl.
126 cdm::Buffer* buffer = CreateCdmBuffer(kBufferSize);
127 EXPECT_EQ(0u, GetAvailableRegionCount());
128 buffer->SetSize(static_cast<uint32_t>(kBufferSize));
129 video_frame->SetFrameBuffer(buffer);
130 EXPECT_NE(nullptr, video_frame->FrameBuffer());
132 // Transform it into a VideoFrame and make sure the buffer is no longer owned.
133 scoped_refptr<VideoFrame> frame = video_frame->TransformToVideoFrame(kSize);
134 EXPECT_EQ(nullptr, video_frame->FrameBuffer());
135 EXPECT_EQ(0u, GetAvailableRegionCount());
138 // Check that the buffer is still in use. It will be freed when |frame|
140 EXPECT_EQ(0u, GetAvailableRegionCount());
143 // Check that the buffer is now in the free list.
144 EXPECT_EQ(1u, GetAvailableRegionCount());