| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/mac/video_frame_mac.h" | 5 #include "media/base/mac/video_frame_mac.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "media/base/mac/corevideo_glue.h" | 13 #include "media/base/mac/corevideo_glue.h" |
| 14 #include "media/base/video_frame.h" | 14 #include "media/base/video_frame.h" |
| 15 | 15 |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 17 |
| 18 namespace media { | 18 namespace media { |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 const int kWidth = 64; | 22 const int kWidth = 64; |
| 23 const int kHeight = 48; | 23 const int kHeight = 48; |
| 24 const int kVisibleRectOffset = 8; |
| 24 const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337); | 25 const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337); |
| 25 | 26 |
| 26 struct FormatPair { | 27 struct FormatPair { |
| 27 VideoPixelFormat chrome; | 28 VideoPixelFormat chrome; |
| 28 OSType corevideo; | 29 OSType corevideo; |
| 29 }; | 30 }; |
| 30 | 31 |
| 31 void Increment(int* i) { | 32 void Increment(int* i) { |
| 32 ++(*i); | 33 ++(*i); |
| 33 } | 34 } |
| 34 | 35 |
| 35 } // namespace | 36 } // namespace |
| 36 | 37 |
| 37 TEST(VideoFrameMac, CheckBasicAttributes) { | 38 TEST(VideoFrameMac, CheckBasicAttributes) { |
| 38 gfx::Size size(kWidth, kHeight); | 39 gfx::Size size(kWidth, kHeight); |
| 39 auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size, gfx::Rect(size), | 40 auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_I420, size, gfx::Rect(size), |
| 40 size, kTimestamp); | 41 size, kTimestamp); |
| 41 ASSERT_TRUE(frame.get()); | 42 ASSERT_TRUE(frame.get()); |
| 42 | 43 |
| 43 auto pb = WrapVideoFrameInCVPixelBuffer(*frame); | 44 auto pb = WrapVideoFrameInCVPixelBuffer(*frame); |
| 44 ASSERT_TRUE(pb.get()); | 45 ASSERT_TRUE(pb.get()); |
| 45 | 46 |
| 46 gfx::Size coded_size = frame->coded_size(); | 47 const gfx::Size coded_size = frame->coded_size(); |
| 47 VideoPixelFormat format = frame->format(); | 48 const VideoPixelFormat format = frame->format(); |
| 48 | 49 |
| 49 EXPECT_EQ(coded_size.width(), static_cast<int>(CVPixelBufferGetWidth(pb))); | 50 EXPECT_EQ(coded_size.width(), static_cast<int>(CVPixelBufferGetWidth(pb))); |
| 50 EXPECT_EQ(coded_size.height(), static_cast<int>(CVPixelBufferGetHeight(pb))); | 51 EXPECT_EQ(coded_size.height(), static_cast<int>(CVPixelBufferGetHeight(pb))); |
| 51 EXPECT_EQ(VideoFrame::NumPlanes(format), CVPixelBufferGetPlaneCount(pb)); | 52 EXPECT_EQ(VideoFrame::NumPlanes(format), CVPixelBufferGetPlaneCount(pb)); |
| 52 | 53 |
| 53 CVPixelBufferLockBaseAddress(pb, 0); | 54 CVPixelBufferLockBaseAddress(pb, 0); |
| 54 for (size_t i = 0; i < VideoFrame::NumPlanes(format); ++i) { | 55 for (size_t i = 0; i < VideoFrame::NumPlanes(format); ++i) { |
| 55 gfx::Size plane_size = VideoFrame::PlaneSize(format, i, coded_size); | 56 const gfx::Size plane_size = VideoFrame::PlaneSize(format, i, coded_size); |
| 56 EXPECT_EQ(plane_size.width(), | 57 EXPECT_EQ(plane_size.width(), |
| 57 static_cast<int>(CVPixelBufferGetWidthOfPlane(pb, i))); | 58 static_cast<int>(CVPixelBufferGetWidthOfPlane(pb, i))); |
| 58 EXPECT_EQ(plane_size.height(), | 59 EXPECT_EQ(plane_size.height(), |
| 59 static_cast<int>(CVPixelBufferGetHeightOfPlane(pb, i))); | 60 static_cast<int>(CVPixelBufferGetHeightOfPlane(pb, i))); |
| 60 EXPECT_EQ(frame->data(i), CVPixelBufferGetBaseAddressOfPlane(pb, i)); | 61 EXPECT_EQ(frame->data(i), CVPixelBufferGetBaseAddressOfPlane(pb, i)); |
| 61 } | 62 } |
| 62 CVPixelBufferUnlockBaseAddress(pb, 0); | 63 CVPixelBufferUnlockBaseAddress(pb, 0); |
| 63 } | 64 } |
| 64 | 65 |
| 65 TEST(VideoFrameMac, CheckFormats) { | 66 TEST(VideoFrameMac, CheckFormats) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 EXPECT_EQ(1, instances_destroyed); | 109 EXPECT_EQ(1, instances_destroyed); |
| 109 } | 110 } |
| 110 | 111 |
| 111 TEST(VideoFrameMac, CheckWrapperFrame) { | 112 TEST(VideoFrameMac, CheckWrapperFrame) { |
| 112 const FormatPair format_pairs[] = { | 113 const FormatPair format_pairs[] = { |
| 113 {PIXEL_FORMAT_I420, kCVPixelFormatType_420YpCbCr8Planar}, | 114 {PIXEL_FORMAT_I420, kCVPixelFormatType_420YpCbCr8Planar}, |
| 114 {PIXEL_FORMAT_NV12, | 115 {PIXEL_FORMAT_NV12, |
| 115 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}, | 116 CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}, |
| 116 }; | 117 }; |
| 117 | 118 |
| 118 gfx::Size size(kWidth, kHeight); | 119 const gfx::Size size(kWidth, kHeight); |
| 119 for (const auto& format_pair : format_pairs) { | 120 for (const auto& format_pair : format_pairs) { |
| 120 base::ScopedCFTypeRef<CVPixelBufferRef> pb; | 121 base::ScopedCFTypeRef<CVPixelBufferRef> pb; |
| 121 CVPixelBufferCreate(nullptr, kWidth, kHeight, format_pair.corevideo, | 122 CVPixelBufferCreate(nullptr, kWidth, kHeight, format_pair.corevideo, |
| 122 nullptr, pb.InitializeInto()); | 123 nullptr, pb.InitializeInto()); |
| 123 ASSERT_TRUE(pb.get()); | 124 ASSERT_TRUE(pb.get()); |
| 124 | 125 |
| 125 auto frame = VideoFrame::WrapCVPixelBuffer(pb.get(), kTimestamp); | 126 auto frame = VideoFrame::WrapCVPixelBuffer(pb.get(), kTimestamp); |
| 126 ASSERT_TRUE(frame.get()); | 127 ASSERT_TRUE(frame.get()); |
| 127 EXPECT_EQ(pb.get(), frame->cv_pixel_buffer()); | 128 EXPECT_EQ(pb.get(), frame->cv_pixel_buffer()); |
| 128 EXPECT_EQ(format_pair.chrome, frame->format()); | 129 EXPECT_EQ(format_pair.chrome, frame->format()); |
| 129 | 130 |
| 130 frame = nullptr; | 131 frame = nullptr; |
| 131 EXPECT_EQ(1, CFGetRetainCount(pb.get())); | 132 EXPECT_EQ(1, CFGetRetainCount(pb.get())); |
| 132 } | 133 } |
| 133 } | 134 } |
| 134 | 135 |
| 136 static void FillFrameWithPredictableValues(const VideoFrame& frame) { |
| 137 for (size_t i = 0; i < VideoFrame::NumPlanes(frame.format()); ++i) { |
| 138 const gfx::Size& size = |
| 139 VideoFrame::PlaneSize(frame.format(), i, frame.coded_size()); |
| 140 uint8_t* plane_ptr = const_cast<uint8_t*>(frame.data(i)); |
| 141 for (int h = 0; h < size.height(); ++h) { |
| 142 const int row_index = h * frame.stride(i); |
| 143 for (int w = 0; w < size.width(); ++w) { |
| 144 const int index = row_index + w; |
| 145 plane_ptr[index] = static_cast<uint8_t>(w ^ h); |
| 146 } |
| 147 } |
| 148 } |
| 149 } |
| 150 |
| 151 TEST(VideoFrameMac, CorrectlyWrapsFramesWithPadding) { |
| 152 const gfx::Size coded_size(kWidth, kHeight); |
| 153 const gfx::Rect visible_rect(kVisibleRectOffset, kVisibleRectOffset, |
| 154 kWidth - 2 * kVisibleRectOffset, |
| 155 kHeight - 2 * kVisibleRectOffset); |
| 156 auto frame = |
| 157 VideoFrame::CreateFrame(PIXEL_FORMAT_I420, coded_size, visible_rect, |
| 158 visible_rect.size(), kTimestamp); |
| 159 ASSERT_TRUE(frame.get()); |
| 160 FillFrameWithPredictableValues(*frame); |
| 161 |
| 162 auto pb = WrapVideoFrameInCVPixelBuffer(*frame); |
| 163 ASSERT_TRUE(pb.get()); |
| 164 EXPECT_EQ(kCVPixelFormatType_420YpCbCr8Planar, |
| 165 CVPixelBufferGetPixelFormatType(pb)); |
| 166 EXPECT_EQ(visible_rect.width(), static_cast<int>(CVPixelBufferGetWidth(pb))); |
| 167 EXPECT_EQ(visible_rect.height(), |
| 168 static_cast<int>(CVPixelBufferGetHeight(pb))); |
| 169 |
| 170 CVPixelBufferLockBaseAddress(pb, 0); |
| 171 for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i) { |
| 172 const gfx::Size plane_size = |
| 173 VideoFrame::PlaneSize(frame->format(), i, visible_rect.size()); |
| 174 EXPECT_EQ(plane_size.width(), |
| 175 static_cast<int>(CVPixelBufferGetWidthOfPlane(pb, i))); |
| 176 EXPECT_EQ(plane_size.height(), |
| 177 static_cast<int>(CVPixelBufferGetHeightOfPlane(pb, i))); |
| 178 |
| 179 uint8_t* plane_ptr = |
| 180 reinterpret_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pb, i)); |
| 181 EXPECT_EQ(frame->visible_data(i), plane_ptr); |
| 182 const int stride = |
| 183 static_cast<int>(CVPixelBufferGetBytesPerRowOfPlane(pb, i)); |
| 184 EXPECT_EQ(frame->stride(i), stride); |
| 185 const int offset = kVisibleRectOffset / ((i == 0) ? 1 : 2); |
| 186 for (int h = 0; h < plane_size.height(); ++h) { |
| 187 const int row_index = h * stride; |
| 188 for (int w = 0; w < plane_size.width(); ++w) { |
| 189 const int index = row_index + w; |
| 190 EXPECT_EQ(static_cast<uint8_t>((w + offset) ^ (h + offset)), |
| 191 plane_ptr[index]); |
| 192 } |
| 193 } |
| 194 } |
| 195 CVPixelBufferUnlockBaseAddress(pb, 0); |
| 196 } |
| 197 |
| 135 } // namespace media | 198 } // namespace media |
| OLD | NEW |