video_decode_accelerator_unittest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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)// The bulk of this file is support code; sorry about that. Here's an overview 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to hopefully help readers of this code: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - RenderingHelper is charged with interacting with X11/{EGL/GLES2,GLX/GL} or 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Win/EGL. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - ClientState is an enum for the state of the decode client used by the test. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - ClientStateNotification is a barrier abstraction that allows the test code 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be written sequentially and wait for the decode client to see certain 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// state transitions. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - GLRenderingVDAClient is a VideoDecodeAccelerator::Client implementation 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Finally actual TEST cases are at the bottom of this file, using the above 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// infrastructure. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Include gtest.h out of order because <X11/X.h> #define's Bool & None, which 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gtest uses as struct names (inside a namespace). This means that 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #include'ing gtest after anything that pulls in X.h fails to compile. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is http://code.google.com/p/googletest/issues/detail?id=371 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/format_macros.h" 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/platform_file.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/stringize_macros.h" 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/stringprintf.h" 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/condition_variable.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/rendering_helper.h" 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/dxva_video_decode_accelerator.h" 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ARCH_CPU_ARMEL) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/common/gpu/media/exynos_video_decode_accelerator.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(ARCH_CPU_X86_FAMILY) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/gpu/media/vaapi_video_decode_accelerator.h" 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/common/gpu/media/vaapi_wrapper.h" 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // ARCH_CPU_ARMEL 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error The VideoAccelerator tests are not supported on this platform. 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // OS_WIN 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using media::VideoDecodeAccelerator; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Values optionally filled in from flags; see main() below. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The syntax of multiple test videos is: 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// test-video1;test-video2;test-video3 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// where only the first video is required and other optional videos would be 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// decoded by concurrent decoders. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The syntax of each test-video is: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// filename:width:height:numframes:numfragments:minFPSwithRender:minFPSnoRender 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where only the first field is required. Value details: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |filename| must be an h264 Annex B (NAL) stream or an IVF VP8 stream. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |width| and |height| are in pixels. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |numframes| is the number of picture frames in the file. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |numfragments| NALU (h264) or frame (VP8) count in the stream. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |minFPSwithRender| and |minFPSnoRender| are minimum frames/second speeds 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expected to be achieved with and without rendering to the screen, resp. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (the latter tests just decode speed). 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - |profile| is the media::VideoCodecProfile set during Initialization. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An empty value for a numeric field means "ignore". 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType* test_video_data = 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FILE_PATH_LITERAL("test-25fps.vp8:320:240:250:250:50:175:11"); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("test-25fps.h264:320:240:250:258:50:175:1"); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// The path of the frame delivery time log. We can enable the log and specify 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// the filename by the "--frame_delivery_log" switch. 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst base::FilePath::CharType* frame_delivery_log = NULL; 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Magic constants for differentiating the reasons for NotifyResetDone being 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// called. 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum ResetPoint { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MID_STREAM_RESET = -2, 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) END_OF_STREAM_RESET = -1 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kMaxResetAfterFrameNum = 100; 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kMaxFramesToDelayReuse = 64; 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kReuseDelayMs = 1000; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct TestVideoFile { 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) explicit TestVideoFile(base::FilePath::StringType file_name) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : file_name(file_name), 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) width(-1), 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) height(-1), 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_frames(-1), 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_fragments(-1), 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) min_fps_render(-1), 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) min_fps_no_render(-1), 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile(-1), 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reset_after_frame_num(END_OF_STREAM_RESET) { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::StringType file_name; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int width; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int height; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_frames; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_fragments; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int min_fps_render; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int min_fps_no_render; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int profile; 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int reset_after_frame_num; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string data_str; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Parse |data| into its constituent parts, set the various output fields 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// accordingly, and read in video stream. CHECK-fails on unexpected or 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// missing required data. Unspecified optional fields are set to -1. 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ParseAndReadTestVideoData(base::FilePath::StringType data, 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t num_concurrent_decoders, 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int reset_point, 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<TestVideoFile*>* test_video_files) { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::FilePath::StringType> entries; 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SplitString(data, ';', &entries); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_GE(entries.size(), 1U) << data; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t index = 0; index < entries.size(); ++index) { 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::FilePath::StringType> fields; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::SplitString(entries[index], ':', &fields); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_GE(fields.size(), 1U) << entries[index]; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK_LE(fields.size(), 8U) << entries[index]; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestVideoFile* video_file = new TestVideoFile(fields[0]); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[1].empty()) 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[1], &video_file->width)); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[2].empty()) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[2], &video_file->height)); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[3].empty()) { 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[3], &video_file->num_frames)); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we reset mid-stream and start playback over, account for frames 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // that are decoded twice in our expectations. 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (video_file->num_frames > 0 && reset_point == MID_STREAM_RESET) { 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reset should not go beyond the last frame; reset after the first 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // frame for short videos. 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video_file->reset_after_frame_num = kMaxResetAfterFrameNum; 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (video_file->num_frames <= kMaxResetAfterFrameNum) 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video_file->reset_after_frame_num = 1; 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video_file->num_frames += video_file->reset_after_frame_num; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[4].empty()) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[4], &video_file->num_fragments)); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[5].empty()) { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[5], &video_file->min_fps_render)); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_file->min_fps_render /= num_concurrent_decoders; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[6].empty()) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[6], &video_file->min_fps_no_render)); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_file->min_fps_no_render /= num_concurrent_decoders; 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fields[7].empty()) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(base::StringToInt(fields[7], &video_file->profile)); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Read in the video data. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath filepath(video_file->file_name); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(file_util::ReadFileToString(filepath, &video_file->data_str)) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << "test_video_file: " << filepath.MaybeAsASCII(); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_video_files->push_back(video_file); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// State of the GLRenderingVDAClient below. Order matters here as the test 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// makes assumptions about it. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ClientState { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_CREATED = 0, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_DECODER_SET = 1, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_INITIALIZED = 2, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_FLUSHING = 3, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_FLUSHED = 4, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_DONE = 5, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_RESETTING = 6, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_RESET = 7, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_ERROR = 8, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_DESTROYED = 9, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CS_MAX, // Must be last entry. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class allowing one thread to wait on a notification from another. 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If notifications come in faster than they are Wait()'d for, they are 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accumulated (so exactly as many Wait() calls will unblock as Notify() calls 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// were made, regardless of order). 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClientStateNotification { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientStateNotification(); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ClientStateNotification(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used to notify a single waiter of a ClientState. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Notify(ClientState state); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used by waiters to wait for the next ClientState Notification. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState Wait(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ConditionVariable cv_; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::queue<ClientState> pending_states_for_notification_; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientStateNotification::ClientStateNotification() : cv_(&lock_) {} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientStateNotification::~ClientStateNotification() {} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ClientStateNotification::Notify(ClientState state) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_states_for_notification_.push(state); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cv_.Signal(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ClientState ClientStateNotification::Wait() { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock auto_lock(lock_); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (pending_states_for_notification_.empty()) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cv_.Wait(); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState ret = pending_states_for_notification_.front(); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_states_for_notification_.pop(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Client that can accept callbacks from a VideoDecodeAccelerator and is used by 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the TESTs below. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GLRenderingVDAClient : public VideoDecodeAccelerator::Client { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Doesn't take ownership of |rendering_helper| or |note|, which must outlive 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |*this|. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |num_fragments_per_decode| counts NALUs for h264 and frames for VP8. 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |num_play_throughs| indicates how many times to play through the video. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |reset_after_frame_num| can be a frame number >=0 indicating a mid-stream 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset() should be done after that frame number is delivered, or 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // END_OF_STREAM_RESET to indicate no mid-stream Reset(). 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |delete_decoder_state| indicates when the underlying decoder should be 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Destroy()'d and deleted and can take values: N<0: delete after -N Decode() 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls have been made, N>=0 means interpret as ClientState. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Both |reset_after_frame_num| & |delete_decoder_state| apply only to the 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last play-through (governed by |num_play_throughs|). 2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // After |delay_reuse_after_frame_num| frame has been delivered, the client 2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // will start delaying the call to ReusePictureBuffer() for kReuseDelayMs. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLRenderingVDAClient(RenderingHelper* rendering_helper, 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rendering_window_id, 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClientStateNotification* note, 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& encoded_data, 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_fragments_per_decode, 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_in_flight_decodes, 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_play_throughs, 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int reset_after_frame_num, 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int delete_decoder_state, 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int frame_width, 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int frame_height, 265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int profile, 2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool suppress_rendering, 2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int delay_reuse_after_frame_num); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~GLRenderingVDAClient(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateDecoder(); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // VideoDecodeAccelerator::Client implementation. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The heart of the Client. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ProvidePictureBuffers(uint32 requested_num_of_buffers, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& dimensions, 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 texture_target) OVERRIDE; 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void DismissPictureBuffer(int32 picture_buffer_id) OVERRIDE; 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void PictureReady(const media::Picture& picture) OVERRIDE; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simple state changes. 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void NotifyInitializeDone() OVERRIDE; 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void NotifyEndOfBitstreamBuffer(int32 bitstream_buffer_id) OVERRIDE; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void NotifyFlushDone() OVERRIDE; 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void NotifyResetDone() OVERRIDE; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void NotifyError(VideoDecodeAccelerator::Error error) OVERRIDE; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void OutputFrameDeliveryTimes(base::PlatformFile output); 286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simple getters for inspecting the state of the Client. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_done_bitstream_buffers() { return num_done_bitstream_buffers_; } 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_skipped_fragments() { return num_skipped_fragments_; } 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_queued_fragments() { return num_queued_fragments_; } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_decoded_frames() { return num_decoded_frames_; } 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double frames_per_second(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool decoder_deleted() { return !decoder_.get(); } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<int, media::PictureBuffer*> PictureBufferById; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetState(ClientState new_state); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Delete the associated OMX decoder helper. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteDecoder(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Compute & return the first encoded bytes (including a start frame) to send 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to the decoder, starting at |start_pos| and returning 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |num_fragments_per_decode| units. Skips to the first decodable position. 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string GetBytesForFirstFragments(size_t start_pos, size_t* end_pos); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute & return the next encoded bytes to send to the decoder (based on 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |start_pos| & |num_fragments_per_decode_|). 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GetBytesForNextFragments(size_t start_pos, size_t* end_pos); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helpers for GetRangeForNextFragments above. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void GetBytesForNextNALU(size_t start_pos, size_t* end_pos); // For h.264. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string GetBytesForNextFrames( 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_pos, size_t* end_pos); // For VP8. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Request decode of the next batch of fragments in the encoded data. 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DecodeNextFragments(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderingHelper* rendering_helper_; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rendering_window_id_; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string encoded_data_; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_fragments_per_decode_; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_in_flight_decodes_; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int outstanding_decodes_; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t encoded_data_next_pos_to_decode_; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int next_bitstream_buffer_id_; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientStateNotification* note_; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<VideoDecodeAccelerator> decoder_; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<int> outstanding_texture_ids_; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int remaining_play_throughs_; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int reset_after_frame_num_; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delete_decoder_state_; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState state_; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_skipped_fragments_; 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_queued_fragments_; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_decoded_frames_; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_done_bitstream_buffers_; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictureBufferById picture_buffers_by_id_; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks initialize_done_ticks_; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int profile_; 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool suppress_rendering_; 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<base::TimeTicks> frame_delivery_times_; 3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int delay_reuse_after_frame_num_; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLRenderingVDAClient::GLRenderingVDAClient( 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderingHelper* rendering_helper, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rendering_window_id, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientStateNotification* note, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& encoded_data, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_fragments_per_decode, 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_in_flight_decodes, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_play_throughs, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int reset_after_frame_num, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delete_decoder_state, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_width, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int frame_height, 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int profile, 3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool suppress_rendering, 3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int delay_reuse_after_frame_num) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : rendering_helper_(rendering_helper), 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_window_id_(rendering_window_id), 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_data_(encoded_data), 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_fragments_per_decode_(num_fragments_per_decode), 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_in_flight_decodes_(num_in_flight_decodes), outstanding_decodes_(0), 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_data_next_pos_to_decode_(0), next_bitstream_buffer_id_(0), 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) note_(note), 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_play_throughs_(num_play_throughs), 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset_after_frame_num_(reset_after_frame_num), 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete_decoder_state_(delete_decoder_state), 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_(CS_CREATED), 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_skipped_fragments_(0), num_queued_fragments_(0), 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_decoded_frames_(0), num_done_bitstream_buffers_(0), 373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch profile_(profile), 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch suppress_rendering_(suppress_rendering), 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delay_reuse_after_frame_num_(delay_reuse_after_frame_num) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GT(num_fragments_per_decode, 0); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GT(num_in_flight_decodes, 0); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_GT(num_play_throughs, 0); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLRenderingVDAClient::~GLRenderingVDAClient() { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteDecoder(); // Clean up in case of expected error. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(decoder_deleted()); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&picture_buffers_by_id_); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_DESTROYED); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool DoNothingReturnTrue() { return true; } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::CreateDecoder() { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(decoder_deleted()); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!decoder_.get()); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_.reset(new DXVAVideoDecodeAccelerator( 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, base::Bind(&DoNothingReturnTrue))); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ARCH_CPU_ARMEL) 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) decoder_.reset( 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new ExynosVideoDecodeAccelerator( 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()), 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<EGLContext>(rendering_helper_->GetGLContext()), 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) this, base::Bind(&DoNothingReturnTrue))); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(ARCH_CPU_X86_FAMILY) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_.reset(new VaapiVideoDecodeAccelerator( 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<Display*>(rendering_helper_->GetGLDisplay()), 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<GLXContext>(rendering_helper_->GetGLContext()), 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, base::Bind(&DoNothingReturnTrue))); 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // ARCH_CPU_ARMEL 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_WIN 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(decoder_.get()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_DECODER_SET); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Configure the decoder. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::VideoCodecProfile profile = media::H264PROFILE_BASELINE; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_ != -1) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile = static_cast<media::VideoCodecProfile>(profile_); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(decoder_->Initialize(profile)); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::ProvidePictureBuffers( 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 requested_num_of_buffers, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Size& dimensions, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 texture_target) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<media::PictureBuffer> buffers; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 i = 0; i < requested_num_of_buffers; ++i) { 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 id = picture_buffers_by_id_.size(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 texture_id; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent done(false, false); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_helper_->CreateTexture( 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_window_id_, texture_target, &texture_id, &done); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(outstanding_texture_ids_.insert(texture_id).second); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::PictureBuffer* buffer = 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new media::PictureBuffer(id, dimensions, texture_id); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(picture_buffers_by_id_.insert(std::make_pair(id, buffer)).second); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers.push_back(*buffer); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->AssignPictureBuffers(buffers); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::DismissPictureBuffer(int32 picture_buffer_id) { 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PictureBufferById::iterator it = 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) picture_buffers_by_id_.find(picture_buffer_id); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(it != picture_buffers_by_id_.end()); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(outstanding_texture_ids_.erase(it->second->texture_id()), 1U); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_helper_->DeleteTexture(it->second->texture_id()); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete it->second; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) picture_buffers_by_id_.erase(it); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::PictureReady(const media::Picture& picture) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We shouldn't be getting pictures delivered after Reset has completed. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(state_, CS_RESET); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_delivery_times_.push_back(base::TimeTicks::Now()); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(picture.bitstream_buffer_id(), next_bitstream_buffer_id_); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_decoded_frames_; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mid-stream reset applies only to the last play-through per constructor 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // comment. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_play_throughs_ == 1 && 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset_after_frame_num_ == num_decoded_frames_) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset_after_frame_num_ = MID_STREAM_RESET; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Reset(); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-start decoding from the beginning of the stream to avoid needing to 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // know how to find I-frames and so on in this test. 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_data_next_pos_to_decode_ = 0; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::PictureBuffer* picture_buffer = 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) picture_buffers_by_id_[picture.picture_buffer_id()]; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(picture_buffer); 4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!suppress_rendering_) { 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rendering_helper_->RenderTexture(picture_buffer->texture_id()); 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (num_decoded_frames_ > delay_reuse_after_frame_num_) { 4867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind( 4877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &VideoDecodeAccelerator::ReusePictureBuffer, 4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Unretained(decoder_.get()), picture.picture_buffer_id()), 4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta::FromMilliseconds(kReuseDelayMs)); 4907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 4917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch decoder_->ReusePictureBuffer(picture.picture_buffer_id()); 4927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::NotifyInitializeDone() { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_INITIALIZED); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialize_done_ticks_ = base::TimeTicks::Now(); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_in_flight_decodes_; ++i) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNextFragments(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(outstanding_decodes_, num_in_flight_decodes_); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::NotifyEndOfBitstreamBuffer( 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 bitstream_buffer_id) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(fischman): this test currently relies on this notification to make 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // forward progress during a Reset(). But the VDA::Reset() API doesn't 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guarantee this, so stop relying on it (and remove the notifications from 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // VaapiVideoDecodeAccelerator::FinishReset()). 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_done_bitstream_buffers_; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --outstanding_decodes_; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNextFragments(); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::NotifyFlushDone() { 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_FLUSHED); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --remaining_play_throughs_; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(remaining_play_throughs_, 0); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Reset(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_RESETTING); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::NotifyResetDone() { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reset_after_frame_num_ == MID_STREAM_RESET) { 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reset_after_frame_num_ = END_OF_STREAM_RESET; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeNextFragments(); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_play_throughs_) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_data_next_pos_to_decode_ = 0; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyInitializeDone(); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_RESET); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!decoder_deleted()) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteDecoder(); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::NotifyError(VideoDecodeAccelerator::Error error) { 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_ERROR); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid GLRenderingVDAClient::OutputFrameDeliveryTimes(base::PlatformFile output) { 552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string s = base::StringPrintf("frame count: %" PRIuS "\n", 553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_delivery_times_.size()); 554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WritePlatformFileAtCurrentPos(output, s.data(), s.length()); 555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeTicks t0 = initialize_done_ticks_; 556eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < frame_delivery_times_.size(); ++i) { 557eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch s = base::StringPrintf("frame %04" PRIuS ": %" PRId64 " us\n", 558eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch i, 559eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (frame_delivery_times_[i] - t0).InMicroseconds()); 560eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch t0 = frame_delivery_times_[i]; 561eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::WritePlatformFileAtCurrentPos(output, s.data(), s.length()); 562eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 563eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 564eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool LookingAtNAL(const std::string& encoded, size_t pos) { 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return encoded[pos] == 0 && encoded[pos + 1] == 0 && 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded[pos + 2] == 0 && encoded[pos + 3] == 1; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::SetState(ClientState new_state) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) note_->Notify(new_state); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = new_state; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remaining_play_throughs_ && new_state == delete_decoder_state_) { 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!decoder_deleted()); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteDecoder(); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::DeleteDecoder() { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_.release()->Destroy(); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLClearObject(&encoded_data_); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<int>::iterator it = outstanding_texture_ids_.begin(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != outstanding_texture_ids_.end(); ++it) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_helper_->DeleteTexture(*it); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outstanding_texture_ids_.clear(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cascade through the rest of the states to simplify test code below. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = state_ + 1; i < CS_MAX; ++i) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(static_cast<ClientState>(i)); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string GLRenderingVDAClient::GetBytesForFirstFragments( 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t start_pos, size_t* end_pos) { 5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (profile_ < media::H264PROFILE_MAX) { 5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos = start_pos; 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (*end_pos + 4 < encoded_data_.size()) { 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((encoded_data_[*end_pos + 4] & 0x1f) == 0x7) // SPS start frame 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetBytesForNextFragments(*end_pos, end_pos); 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetBytesForNextNALU(*end_pos, end_pos); 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_skipped_fragments_++; 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos = start_pos; 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return std::string(); 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(profile_, media::VP8PROFILE_MAX); 6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetBytesForNextFragments(start_pos, end_pos); 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GLRenderingVDAClient::GetBytesForNextFragments( 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_pos, size_t* end_pos) { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_ < media::H264PROFILE_MAX) { 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_end_pos = start_pos; 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos = start_pos; 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < num_fragments_per_decode_; ++i) { 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetBytesForNextNALU(*end_pos, &new_end_pos); 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*end_pos == new_end_pos) 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos = new_end_pos; 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_queued_fragments_++; 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return encoded_data_.substr(start_pos, *end_pos - start_pos); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(profile_, media::VP8PROFILE_MAX); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetBytesForNextFrames(start_pos, end_pos); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GLRenderingVDAClient::GetBytesForNextNALU( 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_pos, size_t* end_pos) { 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *end_pos = start_pos; 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*end_pos + 4 > encoded_data_.size()) 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(LookingAtNAL(encoded_data_, start_pos)); 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos += 4; 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (*end_pos + 4 <= encoded_data_.size() && 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !LookingAtNAL(encoded_data_, *end_pos)) { 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++*end_pos; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*end_pos + 3 >= encoded_data_.size()) 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *end_pos = encoded_data_.size(); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GLRenderingVDAClient::GetBytesForNextFrames( 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start_pos, size_t* end_pos) { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helpful description: http://wiki.multimedia.cx/index.php?title=IVF 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string bytes; 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start_pos == 0) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_pos = 32; // Skip IVF header. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *end_pos = start_pos; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_fragments_per_decode_; ++i) { 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 frame_size = *reinterpret_cast<uint32*>(&encoded_data_[*end_pos]); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *end_pos += 12; // Skip frame header. 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes.append(encoded_data_.substr(*end_pos, frame_size)); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *end_pos += frame_size; 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_queued_fragments_++; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*end_pos + 12 >= encoded_data_.size()) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLRenderingVDAClient::DecodeNextFragments() { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_deleted()) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoded_data_next_pos_to_decode_ == encoded_data_.size()) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (outstanding_decodes_ == 0) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Flush(); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetState(CS_FLUSHING); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t end_pos; 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string next_fragment_bytes; 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (encoded_data_next_pos_to_decode_ == 0) { 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_fragment_bytes = GetBytesForFirstFragments(0, &end_pos); 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_fragment_bytes = 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetBytesForNextFragments(encoded_data_next_pos_to_decode_, &end_pos); 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t next_fragment_size = next_fragment_bytes.size(); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Populate the shared memory buffer w/ the fragments, duplicate its handle, 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and hand it off to the decoder. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemory shm; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(shm.CreateAndMapAnonymous(next_fragment_size)); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(shm.memory(), next_fragment_bytes.data(), next_fragment_size); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::SharedMemoryHandle dup_handle; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(shm.ShareToProcess(base::Process::Current().handle(), &dup_handle)); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) media::BitstreamBuffer bitstream_buffer( 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_bitstream_buffer_id_, dup_handle, next_fragment_size); 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Mask against 30 bits, to avoid (undefined) wraparound on signed integer. 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Decode(bitstream_buffer); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++outstanding_decodes_; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoded_data_next_pos_to_decode_ = end_pos; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!remaining_play_throughs_ && 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) -delete_decoder_state_ == next_bitstream_buffer_id_) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteDecoder(); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double GLRenderingVDAClient::frames_per_second() { 705eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::TimeDelta delta = frame_delivery_times_.back() - initialize_done_ticks_; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delta.InSecondsF() == 0) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_decoded_frames_ / delta.InSecondsF(); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test parameters: 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Number of fragments per Decode() call. 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Number of concurrent decoders. 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Number of concurrent in-flight Decode() calls per decoder. 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Number of play-throughs. 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - reset_after_frame_num: see GLRenderingVDAClient ctor. 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - delete_decoder_phase: see GLRenderingVDAClient ctor. 7187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// - whether to test slow rendering by delaying ReusePictureBuffer(). 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoDecodeAcceleratorTest 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public ::testing::TestWithParam< 7217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Tuple7<int, int, int, int, ResetPoint, ClientState, bool> > { 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper so that gtest failures emit a more readable version of the tuple than 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its byte representation. 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::std::ostream& operator<<( 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::std::ostream& os, 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Tuple6<int, int, int, int, ResetPoint, ClientState>& t) { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return os << t.a << ", " << t.b << ", " << t.c << ", " << t.d << ", " << t.e 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", " << t.f; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wait for |note| to report a state and if it's not |expected_state| then 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assert |client| has deleted its decoder. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void AssertWaitForStateOrDeleted(ClientStateNotification* note, 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLRenderingVDAClient* client, 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState expected_state) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState state = note->Wait(); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == expected_state) return; 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(client->decoder_deleted()) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Decoder not deleted but Wait() returned " << state 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", instead of " << expected_state; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We assert a minimal number of concurrent decoders we expect to succeed. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Different platforms can support more concurrent decoders, so we don't assert 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// failure above this. 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kMinSupportedNumConcurrentDecoders = 3 }; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test the most straightforward case possible: data is decoded from a single 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chunk and rendered to the screen. 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(VideoDecodeAcceleratorTest, TestSimpleDecode) { 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Can be useful for debugging VLOGs from OVDA. 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // logging::SetMinLogLevel(-1); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Required for Thread to work. Not used otherwise. 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ShadowingAtExitManager at_exit_manager; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_fragments_per_decode = GetParam().a; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t num_concurrent_decoders = GetParam().b; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t num_in_flight_decodes = GetParam().c; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int num_play_throughs = GetParam().d; 763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int reset_point = GetParam().e; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int delete_decoder_state = GetParam().f; 7657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool test_reuse_delay = GetParam().g; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<TestVideoFile*> test_video_files; 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ParseAndReadTestVideoData(test_video_data, num_concurrent_decoders, 769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reset_point, &test_video_files); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 771eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Suppress GL rendering when we are logging the frame delivery time and a 772eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // few other tests, to cut down overall test runtime. 773eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const bool suppress_rendering = num_fragments_per_decode > 1 || 774eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_delivery_log != NULL; 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ClientStateNotification*> notes(num_concurrent_decoders, NULL); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<GLRenderingVDAClient*> clients(num_concurrent_decoders, NULL); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the rendering helper. 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread rendering_thread("GLRenderingVDAClientThread"); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Thread::Options options; 782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For windows the decoding thread initializes the media foundation decoder 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which uses COM. We need the thread to be a UI thread. 786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.message_loop_type = base::MessageLoop::TYPE_UI; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_WIN 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.StartWithOptions(options); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RenderingHelper> rendering_helper(RenderingHelper::Create()); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent done(false, false); 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<gfx::Size> frame_dimensions; 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t index = 0; index < test_video_files.size(); ++index) { 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_dimensions.push_back(gfx::Size( 7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_video_files[index]->width, test_video_files[index]->height)); 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.message_loop()->PostTask( 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RenderingHelper::Initialize, 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(rendering_helper.get()), 802eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch num_concurrent_decoders, 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_dimensions, &done)); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First kick off all the decoders. 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t index = 0; index < num_concurrent_decoders; ++index) { 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestVideoFile* video_file = 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) test_video_files[index % test_video_files.size()]; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientStateNotification* note = new ClientStateNotification(); 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notes[index] = note; 8127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int delay_after_frame_num = std::numeric_limits<int>::max(); 8147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (test_reuse_delay && 8157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch kMaxFramesToDelayReuse * 2 < video_file->num_frames) { 8167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delay_after_frame_num = video_file->num_frames - kMaxFramesToDelayReuse; 8177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 8187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLRenderingVDAClient* client = new GLRenderingVDAClient( 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rendering_helper.get(), index, note, video_file->data_str, 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_fragments_per_decode, num_in_flight_decodes, num_play_throughs, 822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) video_file->reset_after_frame_num, delete_decoder_state, 823eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch video_file->width, video_file->height, video_file->profile, 8247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch suppress_rendering, delay_after_frame_num); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clients[index] = client; 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.message_loop()->PostTask( 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&GLRenderingVDAClient::CreateDecoder, 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(client))); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(note->Wait(), CS_DECODER_SET); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then wait for all the decodes to finish. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only check performance & correctness later if we play through only once. 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool skip_performance_and_correctness_checks = num_play_throughs > 1; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < num_concurrent_decoders; ++i) { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientStateNotification* note = notes[i]; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientState state = note->Wait(); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state != CS_INITIALIZED) { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skip_performance_and_correctness_checks = true; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We expect initialization to fail only when more than the supported 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number of decoders is instantiated. Assert here that something else 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // didn't trigger failure. 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_GT(num_concurrent_decoders, 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(state, CS_INITIALIZED); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int n = 0; n < num_play_throughs; ++n) { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For play-throughs other than the first, we expect initialization to 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // succeed unconditionally. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n > 0) { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_INITIALIZED)); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // InitializeDone kicks off decoding inside the client, so we just need to 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wait for Flush. 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHING)); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_FLUSHED)); 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FlushDone requests Reset(). 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_RESETTING)); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_RESET)); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ResetDone requests Destroy(). 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_NO_FATAL_FAILURE( 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertWaitForStateOrDeleted(note, clients[i], CS_DESTROYED)); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally assert that decoding went as expected. 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < num_concurrent_decoders && 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !skip_performance_and_correctness_checks; ++i) { 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can only make performance/correctness assertions if the decoder was 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allowed to finish. 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delete_decoder_state < CS_FLUSHED) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLRenderingVDAClient* client = clients[i]; 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TestVideoFile* video_file = test_video_files[i % test_video_files.size()]; 882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (video_file->num_frames > 0) { 883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Expect the decoded frames may be more than the video frames as frames 884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // could still be returned until resetting done. 885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (video_file->reset_after_frame_num > 0) 886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_GE(client->num_decoded_frames(), video_file->num_frames); 887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else 888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_EQ(client->num_decoded_frames(), video_file->num_frames); 889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (reset_point == END_OF_STREAM_RESET) { 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(video_file->num_fragments, client->num_skipped_fragments() + 8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) client->num_queued_fragments()); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(client->num_done_bitstream_buffers(), 8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ceil(static_cast<double>(client->num_queued_fragments()) / 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_fragments_per_decode)); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(INFO) << "Decoder " << i << " fps: " << client->frames_per_second(); 898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int min_fps = suppress_rendering ? 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_file->min_fps_no_render : video_file->min_fps_render; 9007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (min_fps > 0 && !test_reuse_delay) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GT(client->frames_per_second(), min_fps); 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Output the frame delivery time to file 905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We can only make performance/correctness assertions if the decoder was 906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // allowed to finish. 907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (frame_delivery_log != NULL && delete_decoder_state >= CS_FLUSHED) { 908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::PlatformFile output_file = base::CreatePlatformFile( 909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath(frame_delivery_log), 910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE, 911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL, 912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NULL); 913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < num_concurrent_decoders; ++i) { 914eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch clients[i]->OutputFrameDeliveryTimes(output_file); 915eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 916eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::ClosePlatformFile(output_file); 917eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.message_loop()->PostTask( 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&STLDeleteElements<std::vector<GLRenderingVDAClient*> >, 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &clients)); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.message_loop()->PostTask( 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&STLDeleteElements<std::vector<ClientStateNotification*> >, 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¬es)); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.message_loop()->PostTask( 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&STLDeleteElements<std::vector<TestVideoFile*> >, 9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &test_video_files)); 9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rendering_thread.message_loop()->PostTask( 9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RenderingHelper::UnInitialize, 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(rendering_helper.get()), 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &done)); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rendering_thread.Stop(); 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that replay after EOS works fine. 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplayAfterEOS, VideoDecodeAcceleratorTest, 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::Values( 9447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 4, END_OF_STREAM_RESET, CS_RESET, false))); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Reset() mid-stream works fine and doesn't affect decoding even when 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decode() calls are made during the reset. 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MidStreamReset, VideoDecodeAcceleratorTest, 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::Values( 9517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, MID_STREAM_RESET, CS_RESET, false))); 9527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 9537dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochINSTANTIATE_TEST_CASE_P( 9547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SlowRendering, VideoDecodeAcceleratorTest, 9557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ::testing::Values( 9567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, true))); 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that Destroy() mid-stream works fine (primarily this is testing that no 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// crashes occur). 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TearDownTiming, VideoDecodeAcceleratorTest, 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::Values( 9637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_DECODER_SET, false), 9647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_INITIALIZED, false), 9657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHING, false), 9667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_FLUSHED, false), 9677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESETTING, false), 9687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, 9707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static_cast<ClientState>(-1), false), 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, 9727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static_cast<ClientState>(-10), false), 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, 9747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static_cast<ClientState>(-100), false))); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 976b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Test that decoding various variation works: multiple fragments per Decode() 977b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// call and multiple in-flight decodes. 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecodeVariations, VideoDecodeAcceleratorTest, 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::Values( 9817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 10, 1, END_OF_STREAM_RESET, CS_RESET, false), 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tests queuing. 9847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(1, 1, 15, 1, END_OF_STREAM_RESET, CS_RESET, false), 9857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(2, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(3, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(5, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(8, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false), 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(fischman): decoding more than 15 NALUs at once breaks decode - 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visual artifacts are introduced as well as spurious frames are 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delivered (more pictures are returned than NALUs are fed to the 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // decoder). Increase the "15" below when 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/chrome-os-partner/issues/detail?id=4378 is 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fixed. 9957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch MakeTuple(15, 1, 1, 1, END_OF_STREAM_RESET, CS_RESET, false))); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Find out how many concurrent decoders can go before we exhaust system 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resources. 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P( 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceExhaustion, VideoDecodeAcceleratorTest, 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::Values( 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // +0 hack below to promote enum to int. 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTuple(1, kMinSupportedNumConcurrentDecoders + 0, 1, 1, 10047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch END_OF_STREAM_RESET, CS_RESET, false), 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MakeTuple(1, kMinSupportedNumConcurrentDecoders + 1, 1, 1, 10067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch END_OF_STREAM_RESET, CS_RESET, false))); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(fischman, vrk): add more tests! In particular: 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Test life-cycle: Seek/Stop/Pause/Play for a single decoder. 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Test alternate configurations 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Test failure conditions. 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Test frame size changes mid-stream 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char **argv) { 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(argc, argv); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Needed to enable DVLOG through --vmodule. 1022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logging::LoggingSettings settings; 1023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; 1024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch settings.dcheck_state = 1025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS; 1026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch CHECK(logging::InitLogging(settings)); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cmd_line); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::SwitchMap switches = cmd_line->GetSwitches(); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CommandLine::SwitchMap::const_iterator it = switches.begin(); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != switches.end(); ++it) { 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first == "test_video_data") { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::test_video_data = it->second.c_str(); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (it->first == "frame_delivery_log") { 1039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::frame_delivery_log = it->second.c_str(); 1040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 1041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first == "v" || it->first == "vmodule") 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ShadowingAtExitManager at_exit_manager; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::DXVAVideoDecodeAccelerator::PreSandboxInitialization(); 10512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_CHROMEOS) 10522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ARCH_CPU_ARMEL) 1053c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::ExynosVideoDecodeAccelerator::PreSandboxInitialization(); 10542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(ARCH_CPU_X86_FAMILY) 1055868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::VaapiWrapper::PreSandboxInitialization(); 10562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // ARCH_CPU_ARMEL 10572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // OS_CHROMEOS 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RUN_ALL_TESTS(); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1061