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 "media/base/video_frame.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/bind.h" 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/callback_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/aligned_memory.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gpu/command_buffer/common/mailbox_holder.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/buffers.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::MD5DigestToBase16; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function that initializes a YV12 frame with white and black scan 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lines based on the |white_to_black| parameter. If 0, then the entire 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// frame will be black, if 1 then the entire frame will be white. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InitializeYV12Frame(VideoFrame* frame, double white_to_black) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(VideoFrame::YV12, frame->format()); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_black_row = static_cast<int>(frame->coded_size().height() * 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) white_to_black); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* y_plane = frame->data(VideoFrame::kYPlane); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int row = 0; row < frame->coded_size().height(); ++row) { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int color = (row < first_black_row) ? 0xFF : 0x00; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(y_plane, color, frame->stride(VideoFrame::kYPlane)); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_plane += frame->stride(VideoFrame::kYPlane); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* u_plane = frame->data(VideoFrame::kUPlane); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* v_plane = frame->data(VideoFrame::kVPlane); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int row = 0; row < frame->coded_size().height(); row += 2) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(u_plane, 0x80, frame->stride(VideoFrame::kUPlane)); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(v_plane, 0x80, frame->stride(VideoFrame::kVPlane)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_plane += frame->stride(VideoFrame::kUPlane); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v_plane += frame->stride(VideoFrame::kVPlane); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Given a |yv12_frame| this method converts the YV12 frame to RGBA and 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// makes sure that all the pixels of the RBG frame equal |expect_rgb_color|. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(VideoFrame::YV12, yv12_frame->format()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(yv12_frame->stride(VideoFrame::kUPlane), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) yv12_frame->stride(VideoFrame::kVPlane)); 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ( 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yv12_frame->coded_size().width() & (VideoFrame::kFrameSizeAlignment - 1), 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 0); 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ASSERT_EQ( 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yv12_frame->coded_size().height() & (VideoFrame::kFrameSizeAlignment - 1), 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 0); 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t bytes_per_row = yv12_frame->coded_size().width() * 4u; 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint8* rgb_data = reinterpret_cast<uint8*>( 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::AlignedAlloc(bytes_per_row * yv12_frame->coded_size().height() + 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VideoFrame::kFrameSizePadding, 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VideoFrame::kFrameAddressAlignment)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::ConvertYUVToRGB32(yv12_frame->data(VideoFrame::kYPlane), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) yv12_frame->data(VideoFrame::kUPlane), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) yv12_frame->data(VideoFrame::kVPlane), 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rgb_data, 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yv12_frame->coded_size().width(), 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yv12_frame->coded_size().height(), 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) yv12_frame->stride(VideoFrame::kYPlane), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) yv12_frame->stride(VideoFrame::kUPlane), 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bytes_per_row, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::YV12); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (int row = 0; row < yv12_frame->coded_size().height(); ++row) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32* rgb_row_data = reinterpret_cast<uint32*>( 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) rgb_data + (bytes_per_row * row)); 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (int col = 0; col < yv12_frame->coded_size().width(); ++col) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SCOPED_TRACE( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("Checking (%d, %d)", row, col)); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(expect_rgb_color, rgb_row_data[col]); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::AlignedFree(rgb_data); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fill each plane to its reported extents and verify accessors report non 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// zero values. Additionally, for the first plane verify the rows and 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// row_bytes values are correct. 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ExpectFrameExtents(VideoFrame::Format format, const char* expected_hash) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char kFillByte = 0x80; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kWidth = 61; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kHeight = 31; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size size(kWidth, kHeight); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) format, size, gfx::Rect(size), size, kTimestamp); 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(frame.get()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int planes = VideoFrame::NumPlanes(format); 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (int plane = 0; plane < planes; plane++) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SCOPED_TRACE(base::StringPrintf("Checking plane %d", plane)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->data(plane)); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->stride(plane)); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->rows(plane)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->row_bytes(plane)); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(frame->data(plane), kFillByte, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->stride(plane) * frame->rows(plane)); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Context context; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&context); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->HashFrameForTesting(&context); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &context); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(MD5DigestToBase16(digest), expected_hash); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(VideoFrame, CreateFrame) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kWidth = 64; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kHeight = 48; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a YV12 Video Frame. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size size(kWidth, kHeight); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame::CreateFrame(media::VideoFrame::YV12, size, gfx::Rect(size), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size, kTimestamp); 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(frame.get()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test VideoFrame implementation. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(media::VideoFrame::YV12, frame->format()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SCOPED_TRACE(""); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InitializeYV12Frame(frame.get(), 0.0f); 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ExpectFrameColor(frame.get(), 0xFF000000); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Context context; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&context); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->HashFrameForTesting(&context); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &context); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(MD5DigestToBase16(digest), "9065c841d9fca49186ef8b4ef547e79b"); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SCOPED_TRACE(""); 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InitializeYV12Frame(frame.get(), 1.0f); 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ExpectFrameColor(frame.get(), 0xFFFFFFFF); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&context); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->HashFrameForTesting(&context); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &context); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(MD5DigestToBase16(digest), "911991d51438ad2e1a40ed5f6fc7c796"); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test an empty frame. 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) frame = VideoFrame::CreateEOSFrame(); 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_TRUE(frame->end_of_stream()); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(VideoFrame, CreateBlackFrame) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kWidth = 2; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kHeight = 2; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 kExpectedYRow[] = { 0, 0 }; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 kExpectedUVRow[] = { 128 }; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame = 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight)); 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_TRUE(frame.get()); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test basic properties. 173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch EXPECT_EQ(0, frame->timestamp().InMicroseconds()); 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_FALSE(frame->end_of_stream()); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test |frame| properties. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(VideoFrame::YV12, frame->format()); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kWidth, frame->coded_size().width()); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHeight, frame->coded_size().height()); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test frames themselves. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* y_plane = frame->data(VideoFrame::kYPlane); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < frame->coded_size().height(); ++y) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, memcmp(kExpectedYRow, y_plane, arraysize(kExpectedYRow))); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_plane += frame->stride(VideoFrame::kYPlane); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* u_plane = frame->data(VideoFrame::kUPlane); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* v_plane = frame->data(VideoFrame::kVPlane); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int y = 0; y < frame->coded_size().height() / 2; ++y) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, memcmp(kExpectedUVRow, u_plane, arraysize(kExpectedUVRow))); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0, memcmp(kExpectedUVRow, v_plane, arraysize(kExpectedUVRow))); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_plane += frame->stride(VideoFrame::kUPlane); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v_plane += frame->stride(VideoFrame::kVPlane); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void FrameNoLongerNeededCallback( 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame, 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool* triggered) { 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *triggered = true; 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST(VideoFrame, WrapVideoFrame) { 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int kWidth = 4; 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int kHeight = 4; 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> frame; 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool no_longer_needed_triggered = false; 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_refptr<media::VideoFrame> wrapped_frame = 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VideoFrame::CreateBlackFrame(gfx::Size(kWidth, kHeight)); 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ASSERT_TRUE(wrapped_frame.get()); 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Rect visible_rect(1, 1, 1, 1); 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Size natural_size = visible_rect.size(); 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame = media::VideoFrame::WrapVideoFrame( 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) wrapped_frame, visible_rect, natural_size, 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::Bind(&FrameNoLongerNeededCallback, wrapped_frame, 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &no_longer_needed_triggered)); 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(wrapped_frame->coded_size(), frame->coded_size()); 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(wrapped_frame->data(media::VideoFrame::kYPlane), 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame->data(media::VideoFrame::kYPlane)); 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NE(wrapped_frame->visible_rect(), frame->visible_rect()); 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(visible_rect, frame->visible_rect()); 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NE(wrapped_frame->natural_size(), frame->natural_size()); 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(natural_size, frame->natural_size()); 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_FALSE(no_longer_needed_triggered); 230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame = NULL; 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(no_longer_needed_triggered); 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ensure each frame is properly sized and allocated. Will trigger OOB reads 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and writes as well as incorrect frame hashes otherwise. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(VideoFrame, CheckFrameExtents) { 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Each call consists of a VideoFrame::Format and the expected hash of all 238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // planes if filled with kFillByte (defined in ExpectFrameExtents). 239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExpectFrameExtents(VideoFrame::YV12, "8e5d54cb23cd0edca111dd35ffb6ff05"); 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ExpectFrameExtents(VideoFrame::YV16, "cce408a044b212db42a10dfec304b3ef"); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void TextureCallback(uint32* called_sync_point, 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 release_sync_point) { 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *called_sync_point = release_sync_point; 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify the gpu::MailboxHolder::ReleaseCallback is called when VideoFrame is 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// destroyed with the default release sync point. 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(VideoFrame, TextureNoLongerNeededCallbackIsCalled) { 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 called_sync_point = 1; 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch { 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture( 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu make_scoped_ptr( 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new gpu::MailboxHolder(gpu::Mailbox(), 5, 0 /* sync_point */)), 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&TextureCallback, &called_sync_point), 2585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Size(10, 10), // coded_size 2595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Rect(10, 10), // visible_rect 2605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Size(10, 10), // natural_size 2615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeDelta(), // timestamp 2625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VideoFrame::ReadPixelsCB()); // read_pixels_cb 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Nobody set a sync point to |frame|, so |frame| set |called_sync_point| to 0 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // as default value. 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(0u, called_sync_point); 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SyncPointClientImpl : public VideoFrame::SyncPointClient { 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) explicit SyncPointClientImpl(uint32 sync_point) : sync_point_(sync_point) {} 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual ~SyncPointClientImpl() {} 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual uint32 InsertSyncPoint() OVERRIDE { return sync_point_; } 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE {} 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 sync_point_; 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify the gpu::MailboxHolder::ReleaseCallback is called when VideoFrame is 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// destroyed with the release sync point, which was updated by clients. 2865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// (i.e. the compositor, webgl). 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST(VideoFrame, TextureNoLongerNeededCallbackAfterTakingAndReleasingMailbox) { 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gpu::Mailbox mailbox; 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch mailbox.name[0] = 50; 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32 sync_point = 7; 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uint32 target = 9; 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 release_sync_point = 111; 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint32 called_sync_point = 0; 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch { 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTexture( 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) make_scoped_ptr(new gpu::MailboxHolder(mailbox, target, sync_point)), 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&TextureCallback, &called_sync_point), 2995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Size(10, 10), // coded_size 3005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Rect(10, 10), // visible_rect 3015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu gfx::Size(10, 10), // natural_size 3025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeDelta(), // timestamp 3035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu VideoFrame::ReadPixelsCB()); // read_pixels_cb 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const gpu::MailboxHolder* mailbox_holder = frame->mailbox_holder(); 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(mailbox.name[0], mailbox_holder->mailbox.name[0]); 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(target, mailbox_holder->texture_target); 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(sync_point, mailbox_holder->sync_point); 310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SyncPointClientImpl client(release_sync_point); 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) frame->UpdateReleaseSyncPoint(&client); 3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(sync_point, mailbox_holder->sync_point); 314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_EQ(release_sync_point, called_sync_point); 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 318116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST(VideoFrame, ZeroInitialized) { 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int kWidth = 64; 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const int kHeight = 48; 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeDelta kTimestamp = base::TimeDelta::FromMicroseconds(1337); 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Size size(kWidth, kHeight); 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<media::VideoFrame> frame = VideoFrame::CreateFrame( 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch media::VideoFrame::YV12, size, gfx::Rect(size), size, kTimestamp); 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t i = 0; i < VideoFrame::NumPlanes(frame->format()); ++i) 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(0, frame->data(i)[0]); 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 332