| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <inttypes.h> | 5 #include <inttypes.h> |
| 6 #include <stddef.h> | 6 #include <stddef.h> |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <queue> | 9 #include <queue> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "base/numerics/safe_conversions.h" | 21 #include "base/numerics/safe_conversions.h" |
| 22 #include "base/process/process_handle.h" | 22 #include "base/process/process_handle.h" |
| 23 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
| 24 #include "base/strings/string_split.h" | 24 #include "base/strings/string_split.h" |
| 25 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
| 26 #include "base/threading/thread.h" | 26 #include "base/threading/thread.h" |
| 27 #include "base/threading/thread_checker.h" | 27 #include "base/threading/thread_checker.h" |
| 28 #include "base/time/time.h" | 28 #include "base/time/time.h" |
| 29 #include "base/timer/timer.h" | 29 #include "base/timer/timer.h" |
| 30 #include "build/build_config.h" | 30 #include "build/build_config.h" |
| 31 #include "content/common/gpu/media/video_accelerator_unittest_helpers.h" | |
| 32 #include "media/base/bind_to_current_loop.h" | 31 #include "media/base/bind_to_current_loop.h" |
| 33 #include "media/base/bitstream_buffer.h" | 32 #include "media/base/bitstream_buffer.h" |
| 34 #include "media/base/cdm_context.h" | 33 #include "media/base/cdm_context.h" |
| 35 #include "media/base/decoder_buffer.h" | 34 #include "media/base/decoder_buffer.h" |
| 36 #include "media/base/media_util.h" | 35 #include "media/base/media_util.h" |
| 37 #include "media/base/test_data_util.h" | 36 #include "media/base/test_data_util.h" |
| 38 #include "media/base/video_decoder.h" | 37 #include "media/base/video_decoder.h" |
| 39 #include "media/base/video_frame.h" | 38 #include "media/base/video_frame.h" |
| 40 #include "media/filters/ffmpeg_glue.h" | 39 #include "media/filters/ffmpeg_glue.h" |
| 41 #include "media/filters/ffmpeg_video_decoder.h" | 40 #include "media/filters/ffmpeg_video_decoder.h" |
| 42 #include "media/filters/h264_parser.h" | 41 #include "media/filters/h264_parser.h" |
| 43 #include "media/filters/ivf_parser.h" | 42 #include "media/filters/ivf_parser.h" |
| 43 #include "media/gpu/video_accelerator_unittest_helpers.h" |
| 44 #include "media/video/fake_video_encode_accelerator.h" | 44 #include "media/video/fake_video_encode_accelerator.h" |
| 45 #include "media/video/video_encode_accelerator.h" | 45 #include "media/video/video_encode_accelerator.h" |
| 46 #include "testing/gtest/include/gtest/gtest.h" | 46 #include "testing/gtest/include/gtest/gtest.h" |
| 47 | 47 |
| 48 #if defined(OS_CHROMEOS) | 48 #if defined(OS_CHROMEOS) |
| 49 #if defined(ARCH_CPU_ARMEL) || (defined(USE_OZONE) && defined(USE_V4L2_CODEC)) | 49 #if defined(ARCH_CPU_ARMEL) || (defined(USE_OZONE) && defined(USE_V4L2_CODEC)) |
| 50 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" | 50 #include "media/gpu/v4l2_video_encode_accelerator.h" |
| 51 #endif | 51 #endif |
| 52 #if defined(ARCH_CPU_X86_FAMILY) | 52 #if defined(ARCH_CPU_X86_FAMILY) |
| 53 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" | 53 #include "media/gpu/vaapi_video_encode_accelerator.h" |
| 54 #include "content/common/gpu/media/vaapi_wrapper.h" | 54 #include "media/gpu/vaapi_wrapper.h" |
| 55 // Status has been defined as int in Xlib.h. | 55 // Status has been defined as int in Xlib.h. |
| 56 #undef Status | 56 #undef Status |
| 57 #endif // defined(ARCH_CPU_X86_FAMILY) | 57 #endif // defined(ARCH_CPU_X86_FAMILY) |
| 58 #elif defined(OS_MACOSX) | 58 #elif defined(OS_MACOSX) |
| 59 #include "content/common/gpu/media/vt_video_encode_accelerator_mac.h" | 59 #include "media/gpu/vt_video_encode_accelerator_mac.h" |
| 60 #else | 60 #else |
| 61 #error The VideoEncodeAcceleratorUnittest is not supported on this platform. | 61 #error The VideoEncodeAcceleratorUnittest is not supported on this platform. |
| 62 #endif | 62 #endif |
| 63 | 63 |
| 64 using media::VideoEncodeAccelerator; | 64 using media::VideoEncodeAccelerator; |
| 65 | 65 |
| 66 namespace content { | 66 namespace media { |
| 67 namespace { | 67 namespace { |
| 68 | 68 |
| 69 const media::VideoPixelFormat kInputFormat = media::PIXEL_FORMAT_I420; | 69 const media::VideoPixelFormat kInputFormat = media::PIXEL_FORMAT_I420; |
| 70 | 70 |
| 71 // The absolute differences between original frame and decoded frame usually | 71 // The absolute differences between original frame and decoded frame usually |
| 72 // ranges aroud 1 ~ 7. So we pick 10 as an extreme value to detect abnormal | 72 // ranges aroud 1 ~ 7. So we pick 10 as an extreme value to detect abnormal |
| 73 // decoded frames. | 73 // decoded frames. |
| 74 const double kDecodeSimilarityThreshold = 10.0; | 74 const double kDecodeSimilarityThreshold = 10.0; |
| 75 | 75 |
| 76 // Arbitrarily chosen to add some depth to the pipeline. | 76 // Arbitrarily chosen to add some depth to the pipeline. |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 test_stream->mapped_aligned_in_file.Initialize(std::move(dest_file))); | 320 test_stream->mapped_aligned_in_file.Initialize(std::move(dest_file))); |
| 321 // Assert that memory mapped of file starts at 64 byte boundary. So each | 321 // Assert that memory mapped of file starts at 64 byte boundary. So each |
| 322 // plane of frames also start at 64 byte boundary. | 322 // plane of frames also start at 64 byte boundary. |
| 323 | 323 |
| 324 ASSERT_EQ( | 324 ASSERT_EQ( |
| 325 reinterpret_cast<off_t>(test_stream->mapped_aligned_in_file.data()) & 63, | 325 reinterpret_cast<off_t>(test_stream->mapped_aligned_in_file.data()) & 63, |
| 326 0) | 326 0) |
| 327 << "File should be mapped at a 64 byte boundary"; | 327 << "File should be mapped at a 64 byte boundary"; |
| 328 | 328 |
| 329 LOG_ASSERT(test_stream->mapped_aligned_in_file.length() % | 329 LOG_ASSERT(test_stream->mapped_aligned_in_file.length() % |
| 330 test_stream->aligned_buffer_size == 0U) | 330 test_stream->aligned_buffer_size == |
| 331 0U) |
| 331 << "Stream byte size is not a product of calculated frame byte size"; | 332 << "Stream byte size is not a product of calculated frame byte size"; |
| 332 LOG_ASSERT(test_stream->num_frames > 0UL); | 333 LOG_ASSERT(test_stream->num_frames > 0UL); |
| 333 } | 334 } |
| 334 | 335 |
| 335 // Parse |data| into its constituent parts, set the various output fields | 336 // Parse |data| into its constituent parts, set the various output fields |
| 336 // accordingly, read in video stream, and store them to |test_streams|. | 337 // accordingly, read in video stream, and store them to |test_streams|. |
| 337 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, | 338 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, |
| 338 ScopedVector<TestStream>* test_streams) { | 339 ScopedVector<TestStream>* test_streams) { |
| 339 // Split the string to individual test stream data. | 340 // Split the string to individual test stream data. |
| 340 std::vector<base::FilePath::StringType> test_streams_data = base::SplitString( | 341 std::vector<base::FilePath::StringType> test_streams_data = |
| 341 data, base::FilePath::StringType(1, ';'), | 342 base::SplitString(data, base::FilePath::StringType(1, ';'), |
| 342 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 343 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 343 LOG_ASSERT(test_streams_data.size() >= 1U) << data; | 344 LOG_ASSERT(test_streams_data.size() >= 1U) << data; |
| 344 | 345 |
| 345 // Parse each test stream data and read the input file. | 346 // Parse each test stream data and read the input file. |
| 346 for (size_t index = 0; index < test_streams_data.size(); ++index) { | 347 for (size_t index = 0; index < test_streams_data.size(); ++index) { |
| 347 std::vector<base::FilePath::StringType> fields = base::SplitString( | 348 std::vector<base::FilePath::StringType> fields = base::SplitString( |
| 348 test_streams_data[index], base::FilePath::StringType(1, ':'), | 349 test_streams_data[index], base::FilePath::StringType(1, ':'), |
| 349 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 350 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 350 LOG_ASSERT(fields.size() >= 4U) << data; | 351 LOG_ASSERT(fields.size() >= 4U) << data; |
| 351 LOG_ASSERT(fields.size() <= 9U) << data; | 352 LOG_ASSERT(fields.size() <= 9U) << data; |
| 352 TestStream* test_stream = new TestStream(); | 353 TestStream* test_stream = new TestStream(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 364 LOG_ASSERT(result); | 365 LOG_ASSERT(result); |
| 365 LOG_ASSERT(profile > media::VIDEO_CODEC_PROFILE_UNKNOWN); | 366 LOG_ASSERT(profile > media::VIDEO_CODEC_PROFILE_UNKNOWN); |
| 366 LOG_ASSERT(profile <= media::VIDEO_CODEC_PROFILE_MAX); | 367 LOG_ASSERT(profile <= media::VIDEO_CODEC_PROFILE_MAX); |
| 367 test_stream->requested_profile = | 368 test_stream->requested_profile = |
| 368 static_cast<media::VideoCodecProfile>(profile); | 369 static_cast<media::VideoCodecProfile>(profile); |
| 369 | 370 |
| 370 if (fields.size() >= 5 && !fields[4].empty()) | 371 if (fields.size() >= 5 && !fields[4].empty()) |
| 371 test_stream->out_filename = fields[4]; | 372 test_stream->out_filename = fields[4]; |
| 372 | 373 |
| 373 if (fields.size() >= 6 && !fields[5].empty()) | 374 if (fields.size() >= 6 && !fields[5].empty()) |
| 374 LOG_ASSERT(base::StringToUint(fields[5], | 375 LOG_ASSERT( |
| 375 &test_stream->requested_bitrate)); | 376 base::StringToUint(fields[5], &test_stream->requested_bitrate)); |
| 376 | 377 |
| 377 if (fields.size() >= 7 && !fields[6].empty()) | 378 if (fields.size() >= 7 && !fields[6].empty()) |
| 378 LOG_ASSERT(base::StringToUint(fields[6], | 379 LOG_ASSERT( |
| 379 &test_stream->requested_framerate)); | 380 base::StringToUint(fields[6], &test_stream->requested_framerate)); |
| 380 | 381 |
| 381 if (fields.size() >= 8 && !fields[7].empty()) { | 382 if (fields.size() >= 8 && !fields[7].empty()) { |
| 382 LOG_ASSERT(base::StringToUint(fields[7], | 383 LOG_ASSERT(base::StringToUint( |
| 383 &test_stream->requested_subsequent_bitrate)); | 384 fields[7], &test_stream->requested_subsequent_bitrate)); |
| 384 } | 385 } |
| 385 | 386 |
| 386 if (fields.size() >= 9 && !fields[8].empty()) { | 387 if (fields.size() >= 9 && !fields[8].empty()) { |
| 387 LOG_ASSERT(base::StringToUint(fields[8], | 388 LOG_ASSERT(base::StringToUint( |
| 388 &test_stream->requested_subsequent_framerate)); | 389 fields[8], &test_stream->requested_subsequent_framerate)); |
| 389 } | 390 } |
| 390 test_streams->push_back(test_stream); | 391 test_streams->push_back(test_stream); |
| 391 } | 392 } |
| 392 } | 393 } |
| 393 | 394 |
| 394 // Basic test environment shared across multiple test cases. We only need to | 395 // Basic test environment shared across multiple test cases. We only need to |
| 395 // setup it once for all test cases. | 396 // setup it once for all test cases. |
| 396 // It helps | 397 // It helps |
| 397 // - maintain test stream data and other test settings. | 398 // - maintain test stream data and other test settings. |
| 398 // - clean up temporary aligned files. | 399 // - clean up temporary aligned files. |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 ASSERT_EQ(media::H264Parser::kOk, result); | 538 ASSERT_EQ(media::H264Parser::kOk, result); |
| 538 | 539 |
| 539 bool keyframe = false; | 540 bool keyframe = false; |
| 540 | 541 |
| 541 switch (nalu.nal_unit_type) { | 542 switch (nalu.nal_unit_type) { |
| 542 case media::H264NALU::kIDRSlice: | 543 case media::H264NALU::kIDRSlice: |
| 543 ASSERT_TRUE(seen_sps_); | 544 ASSERT_TRUE(seen_sps_); |
| 544 ASSERT_TRUE(seen_pps_); | 545 ASSERT_TRUE(seen_pps_); |
| 545 seen_idr_ = true; | 546 seen_idr_ = true; |
| 546 keyframe = true; | 547 keyframe = true; |
| 547 // fallthrough | 548 // fallthrough |
| 548 case media::H264NALU::kNonIDRSlice: { | 549 case media::H264NALU::kNonIDRSlice: { |
| 549 ASSERT_TRUE(seen_idr_); | 550 ASSERT_TRUE(seen_idr_); |
| 550 if (!frame_cb_.Run(keyframe)) | 551 if (!frame_cb_.Run(keyframe)) |
| 551 return; | 552 return; |
| 552 break; | 553 break; |
| 553 } | 554 } |
| 554 | 555 |
| 555 case media::H264NALU::kSPS: { | 556 case media::H264NALU::kSPS: { |
| 556 int sps_id; | 557 int sps_id; |
| 557 ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParseSPS(&sps_id)); | 558 ASSERT_EQ(media::H264Parser::kOk, h264_parser_.ParseSPS(&sps_id)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 569 | 570 |
| 570 default: | 571 default: |
| 571 break; | 572 break; |
| 572 } | 573 } |
| 573 } | 574 } |
| 574 } | 575 } |
| 575 | 576 |
| 576 class VP8Validator : public StreamValidator { | 577 class VP8Validator : public StreamValidator { |
| 577 public: | 578 public: |
| 578 explicit VP8Validator(const FrameFoundCallback& frame_cb) | 579 explicit VP8Validator(const FrameFoundCallback& frame_cb) |
| 579 : StreamValidator(frame_cb), | 580 : StreamValidator(frame_cb), seen_keyframe_(false) {} |
| 580 seen_keyframe_(false) {} | |
| 581 | 581 |
| 582 void ProcessStreamBuffer(const uint8_t* stream, size_t size) override; | 582 void ProcessStreamBuffer(const uint8_t* stream, size_t size) override; |
| 583 | 583 |
| 584 private: | 584 private: |
| 585 // Have we already got a keyframe in the stream? | 585 // Have we already got a keyframe in the stream? |
| 586 bool seen_keyframe_; | 586 bool seen_keyframe_; |
| 587 }; | 587 }; |
| 588 | 588 |
| 589 void VP8Validator::ProcessStreamBuffer(const uint8_t* stream, size_t size) { | 589 void VP8Validator::ProcessStreamBuffer(const uint8_t* stream, size_t size) { |
| 590 bool keyframe = !(stream[0] & 0x01); | 590 bool keyframe = !(stream[0] & 0x01); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 // Without it, AppendToFile() will not work. | 1042 // Without it, AppendToFile() will not work. |
| 1043 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); | 1043 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); |
| 1044 } | 1044 } |
| 1045 | 1045 |
| 1046 // Initialize the parameters of the test streams. | 1046 // Initialize the parameters of the test streams. |
| 1047 UpdateTestStreamData(mid_stream_bitrate_switch, mid_stream_framerate_switch); | 1047 UpdateTestStreamData(mid_stream_bitrate_switch, mid_stream_framerate_switch); |
| 1048 | 1048 |
| 1049 thread_checker_.DetachFromThread(); | 1049 thread_checker_.DetachFromThread(); |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 VEAClient::~VEAClient() { LOG_ASSERT(!has_encoder()); } | 1052 VEAClient::~VEAClient() { |
| 1053 LOG_ASSERT(!has_encoder()); |
| 1054 } |
| 1053 | 1055 |
| 1054 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateFakeVEA() { | 1056 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateFakeVEA() { |
| 1055 std::unique_ptr<media::VideoEncodeAccelerator> encoder; | 1057 std::unique_ptr<media::VideoEncodeAccelerator> encoder; |
| 1056 if (g_fake_encoder) { | 1058 if (g_fake_encoder) { |
| 1057 encoder.reset(new media::FakeVideoEncodeAccelerator( | 1059 encoder.reset(new media::FakeVideoEncodeAccelerator( |
| 1058 scoped_refptr<base::SingleThreadTaskRunner>( | 1060 scoped_refptr<base::SingleThreadTaskRunner>( |
| 1059 base::ThreadTaskRunnerHandle::Get()))); | 1061 base::ThreadTaskRunnerHandle::Get()))); |
| 1060 } | 1062 } |
| 1061 return encoder; | 1063 return encoder; |
| 1062 } | 1064 } |
| 1063 | 1065 |
| 1064 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateV4L2VEA() { | 1066 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateV4L2VEA() { |
| 1065 std::unique_ptr<media::VideoEncodeAccelerator> encoder; | 1067 std::unique_ptr<media::VideoEncodeAccelerator> encoder; |
| 1066 #if defined(OS_CHROMEOS) && (defined(ARCH_CPU_ARMEL) || \ | 1068 #if defined(OS_CHROMEOS) && (defined(ARCH_CPU_ARMEL) || \ |
| 1067 (defined(USE_OZONE) && defined(USE_V4L2_CODEC))) | 1069 (defined(USE_OZONE) && defined(USE_V4L2_CODEC))) |
| 1068 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); | 1070 scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); |
| 1069 if (device) | 1071 if (device) |
| 1070 encoder.reset(new V4L2VideoEncodeAccelerator(device)); | 1072 encoder.reset(new V4L2VideoEncodeAccelerator(device)); |
| 1071 #endif | 1073 #endif |
| 1072 return encoder; | 1074 return encoder; |
| 1073 } | 1075 } |
| 1074 | 1076 |
| 1075 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateVaapiVEA() { | 1077 std::unique_ptr<media::VideoEncodeAccelerator> VEAClient::CreateVaapiVEA() { |
| 1076 std::unique_ptr<media::VideoEncodeAccelerator> encoder; | 1078 std::unique_ptr<media::VideoEncodeAccelerator> encoder; |
| 1077 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 1079 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1096 CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA()}; | 1098 CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA()}; |
| 1097 | 1099 |
| 1098 DVLOG(1) << "Profile: " << test_stream_->requested_profile | 1100 DVLOG(1) << "Profile: " << test_stream_->requested_profile |
| 1099 << ", initial bitrate: " << requested_bitrate_; | 1101 << ", initial bitrate: " << requested_bitrate_; |
| 1100 | 1102 |
| 1101 for (size_t i = 0; i < arraysize(encoders); ++i) { | 1103 for (size_t i = 0; i < arraysize(encoders); ++i) { |
| 1102 if (!encoders[i]) | 1104 if (!encoders[i]) |
| 1103 continue; | 1105 continue; |
| 1104 encoder_ = std::move(encoders[i]); | 1106 encoder_ = std::move(encoders[i]); |
| 1105 SetState(CS_ENCODER_SET); | 1107 SetState(CS_ENCODER_SET); |
| 1106 if (encoder_->Initialize(kInputFormat, | 1108 if (encoder_->Initialize(kInputFormat, test_stream_->visible_size, |
| 1107 test_stream_->visible_size, | |
| 1108 test_stream_->requested_profile, | 1109 test_stream_->requested_profile, |
| 1109 requested_bitrate_, | 1110 requested_bitrate_, this)) { |
| 1110 this)) { | |
| 1111 SetStreamParameters(requested_bitrate_, requested_framerate_); | 1111 SetStreamParameters(requested_bitrate_, requested_framerate_); |
| 1112 SetState(CS_INITIALIZED); | 1112 SetState(CS_INITIALIZED); |
| 1113 | 1113 |
| 1114 if (verify_output_ && !g_fake_encoder) | 1114 if (verify_output_ && !g_fake_encoder) |
| 1115 quality_validator_.reset(new VideoFrameQualityValidator( | 1115 quality_validator_.reset(new VideoFrameQualityValidator( |
| 1116 test_stream_->requested_profile, | 1116 test_stream_->requested_profile, |
| 1117 base::Bind(&VEAClient::DecodeCompleted, base::Unretained(this)), | 1117 base::Bind(&VEAClient::DecodeCompleted, base::Unretained(this)), |
| 1118 base::Bind(&VEAClient::DecodeFailed, base::Unretained(this)))); | 1118 base::Bind(&VEAClient::DecodeFailed, base::Unretained(this)))); |
| 1119 return; | 1119 return; |
| 1120 } | 1120 } |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 } | 1350 } |
| 1351 | 1351 |
| 1352 scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame( | 1352 scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame( |
| 1353 off_t position, | 1353 off_t position, |
| 1354 int32_t* input_id) { | 1354 int32_t* input_id) { |
| 1355 CHECK_LE(position + test_stream_->aligned_buffer_size, | 1355 CHECK_LE(position + test_stream_->aligned_buffer_size, |
| 1356 test_stream_->mapped_aligned_in_file.length()); | 1356 test_stream_->mapped_aligned_in_file.length()); |
| 1357 | 1357 |
| 1358 scoped_refptr<media::VideoFrame> frame = CreateFrame(position); | 1358 scoped_refptr<media::VideoFrame> frame = CreateFrame(position); |
| 1359 EXPECT_TRUE(frame); | 1359 EXPECT_TRUE(frame); |
| 1360 frame->AddDestructionObserver( | 1360 frame->AddDestructionObserver(media::BindToCurrentLoop( |
| 1361 media::BindToCurrentLoop( | 1361 base::Bind(&VEAClient::InputNoLongerNeededCallback, |
| 1362 base::Bind(&VEAClient::InputNoLongerNeededCallback, | 1362 base::Unretained(this), next_input_id_))); |
| 1363 base::Unretained(this), | |
| 1364 next_input_id_))); | |
| 1365 | 1363 |
| 1366 LOG_ASSERT(inputs_at_client_.insert(next_input_id_).second); | 1364 LOG_ASSERT(inputs_at_client_.insert(next_input_id_).second); |
| 1367 | 1365 |
| 1368 *input_id = next_input_id_++; | 1366 *input_id = next_input_id_++; |
| 1369 return frame; | 1367 return frame; |
| 1370 } | 1368 } |
| 1371 | 1369 |
| 1372 void VEAClient::OnInputTimer() { | 1370 void VEAClient::OnInputTimer() { |
| 1373 if (!has_encoder() || state_ != CS_ENCODING) | 1371 if (!has_encoder() || state_ != CS_ENCODING) |
| 1374 input_timer_.reset(); | 1372 input_timer_.reset(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { | 1420 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { |
| 1423 if (!has_encoder()) | 1421 if (!has_encoder()) |
| 1424 return; | 1422 return; |
| 1425 | 1423 |
| 1426 if (state_ != CS_ENCODING) | 1424 if (state_ != CS_ENCODING) |
| 1427 return; | 1425 return; |
| 1428 | 1426 |
| 1429 base::SharedMemoryHandle dup_handle; | 1427 base::SharedMemoryHandle dup_handle; |
| 1430 LOG_ASSERT(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle)); | 1428 LOG_ASSERT(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle)); |
| 1431 | 1429 |
| 1432 media::BitstreamBuffer bitstream_buffer( | 1430 media::BitstreamBuffer bitstream_buffer(next_output_buffer_id_++, dup_handle, |
| 1433 next_output_buffer_id_++, dup_handle, output_buffer_size_); | 1431 output_buffer_size_); |
| 1434 LOG_ASSERT(output_buffers_at_client_.insert( | 1432 LOG_ASSERT(output_buffers_at_client_ |
| 1435 std::make_pair(bitstream_buffer.id(), shm)).second); | 1433 .insert(std::make_pair(bitstream_buffer.id(), shm)) |
| 1434 .second); |
| 1436 encoder_->UseOutputBitstreamBuffer(bitstream_buffer); | 1435 encoder_->UseOutputBitstreamBuffer(bitstream_buffer); |
| 1437 } | 1436 } |
| 1438 | 1437 |
| 1439 bool VEAClient::HandleEncodedFrame(bool keyframe) { | 1438 bool VEAClient::HandleEncodedFrame(bool keyframe) { |
| 1440 // This would be a bug in the test, which should not ignore false | 1439 // This would be a bug in the test, which should not ignore false |
| 1441 // return value from this method. | 1440 // return value from this method. |
| 1442 LOG_ASSERT(num_encoded_frames_ <= num_frames_to_encode_); | 1441 LOG_ASSERT(num_encoded_frames_ <= num_frames_to_encode_); |
| 1443 | 1442 |
| 1444 last_frame_ready_time_ = base::TimeTicks::Now(); | 1443 last_frame_ready_time_ = base::TimeTicks::Now(); |
| 1445 | 1444 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1519 if (test_perf_) | 1518 if (test_perf_) |
| 1520 EXPECT_GE(frames_per_second(), kMinPerfFPS); | 1519 EXPECT_GE(frames_per_second(), kMinPerfFPS); |
| 1521 } | 1520 } |
| 1522 | 1521 |
| 1523 void VEAClient::VerifyStreamProperties() { | 1522 void VEAClient::VerifyStreamProperties() { |
| 1524 LOG_ASSERT(num_frames_since_last_check_ > 0UL); | 1523 LOG_ASSERT(num_frames_since_last_check_ > 0UL); |
| 1525 LOG_ASSERT(encoded_stream_size_since_last_check_ > 0UL); | 1524 LOG_ASSERT(encoded_stream_size_since_last_check_ > 0UL); |
| 1526 unsigned int bitrate = encoded_stream_size_since_last_check_ * 8 * | 1525 unsigned int bitrate = encoded_stream_size_since_last_check_ * 8 * |
| 1527 current_framerate_ / num_frames_since_last_check_; | 1526 current_framerate_ / num_frames_since_last_check_; |
| 1528 DVLOG(1) << "Current chunk's bitrate: " << bitrate | 1527 DVLOG(1) << "Current chunk's bitrate: " << bitrate |
| 1529 << " (expected: " << current_requested_bitrate_ | 1528 << " (expected: " << current_requested_bitrate_ << " @ " |
| 1530 << " @ " << current_framerate_ << " FPS," | 1529 << current_framerate_ << " FPS," |
| 1531 << " num frames in chunk: " << num_frames_since_last_check_; | 1530 << " num frames in chunk: " << num_frames_since_last_check_; |
| 1532 | 1531 |
| 1533 num_frames_since_last_check_ = 0; | 1532 num_frames_since_last_check_ = 0; |
| 1534 encoded_stream_size_since_last_check_ = 0; | 1533 encoded_stream_size_since_last_check_ = 0; |
| 1535 | 1534 |
| 1536 if (force_bitrate_) { | 1535 if (force_bitrate_) { |
| 1537 EXPECT_NEAR(bitrate, | 1536 EXPECT_NEAR(bitrate, current_requested_bitrate_, |
| 1538 current_requested_bitrate_, | |
| 1539 kBitrateTolerance * current_requested_bitrate_); | 1537 kBitrateTolerance * current_requested_bitrate_); |
| 1540 } | 1538 } |
| 1541 | 1539 |
| 1542 // All requested keyframes should've been provided. Allow the last requested | 1540 // All requested keyframes should've been provided. Allow the last requested |
| 1543 // frame to remain undelivered if we haven't reached the maximum frame number | 1541 // frame to remain undelivered if we haven't reached the maximum frame number |
| 1544 // by which it should have arrived. | 1542 // by which it should have arrived. |
| 1545 if (num_encoded_frames_ < next_keyframe_at_ + kMaxKeyframeDelay) | 1543 if (num_encoded_frames_ < next_keyframe_at_ + kMaxKeyframeDelay) |
| 1546 EXPECT_LE(num_keyframes_requested_, 1UL); | 1544 EXPECT_LE(num_keyframes_requested_, 1UL); |
| 1547 else | 1545 else |
| 1548 EXPECT_EQ(num_keyframes_requested_, 0UL); | 1546 EXPECT_EQ(num_keyframes_requested_, 0UL); |
| 1549 } | 1547 } |
| 1550 | 1548 |
| 1551 void VEAClient::WriteIvfFileHeader() { | 1549 void VEAClient::WriteIvfFileHeader() { |
| 1552 media::IvfFileHeader header = {}; | 1550 media::IvfFileHeader header = {}; |
| 1553 | 1551 |
| 1554 memcpy(header.signature, media::kIvfHeaderSignature, | 1552 memcpy(header.signature, media::kIvfHeaderSignature, |
| 1555 sizeof(header.signature)); | 1553 sizeof(header.signature)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 size_t num_concurrent_encoders = base::get<0>(GetParam()); | 1599 size_t num_concurrent_encoders = base::get<0>(GetParam()); |
| 1602 const bool save_to_file = base::get<1>(GetParam()); | 1600 const bool save_to_file = base::get<1>(GetParam()); |
| 1603 const unsigned int keyframe_period = base::get<2>(GetParam()); | 1601 const unsigned int keyframe_period = base::get<2>(GetParam()); |
| 1604 const bool force_bitrate = base::get<3>(GetParam()); | 1602 const bool force_bitrate = base::get<3>(GetParam()); |
| 1605 const bool test_perf = base::get<4>(GetParam()); | 1603 const bool test_perf = base::get<4>(GetParam()); |
| 1606 const bool mid_stream_bitrate_switch = base::get<5>(GetParam()); | 1604 const bool mid_stream_bitrate_switch = base::get<5>(GetParam()); |
| 1607 const bool mid_stream_framerate_switch = base::get<6>(GetParam()); | 1605 const bool mid_stream_framerate_switch = base::get<6>(GetParam()); |
| 1608 const bool verify_output = | 1606 const bool verify_output = |
| 1609 base::get<7>(GetParam()) || g_env->verify_all_output(); | 1607 base::get<7>(GetParam()) || g_env->verify_all_output(); |
| 1610 | 1608 |
| 1611 ScopedVector<ClientStateNotification<ClientState> > notes; | 1609 ScopedVector<ClientStateNotification<ClientState>> notes; |
| 1612 ScopedVector<VEAClient> clients; | 1610 ScopedVector<VEAClient> clients; |
| 1613 base::Thread encoder_thread("EncoderThread"); | 1611 base::Thread encoder_thread("EncoderThread"); |
| 1614 ASSERT_TRUE(encoder_thread.Start()); | 1612 ASSERT_TRUE(encoder_thread.Start()); |
| 1615 | 1613 |
| 1616 if (g_env->test_streams_.size() > 1) | 1614 if (g_env->test_streams_.size() > 1) |
| 1617 num_concurrent_encoders = g_env->test_streams_.size(); | 1615 num_concurrent_encoders = g_env->test_streams_.size(); |
| 1618 | 1616 |
| 1619 // Create all encoders. | 1617 // Create all encoders. |
| 1620 for (size_t i = 0; i < num_concurrent_encoders; i++) { | 1618 for (size_t i = 0; i < num_concurrent_encoders; i++) { |
| 1621 size_t test_stream_index = i % g_env->test_streams_.size(); | 1619 size_t test_stream_index = i % g_env->test_streams_.size(); |
| 1622 // Disregard save_to_file if we didn't get an output filename. | 1620 // Disregard save_to_file if we didn't get an output filename. |
| 1623 bool encoder_save_to_file = | 1621 bool encoder_save_to_file = |
| 1624 (save_to_file && | 1622 (save_to_file && |
| 1625 !g_env->test_streams_[test_stream_index]->out_filename.empty()); | 1623 !g_env->test_streams_[test_stream_index]->out_filename.empty()); |
| 1626 | 1624 |
| 1627 notes.push_back(new ClientStateNotification<ClientState>()); | 1625 notes.push_back(new ClientStateNotification<ClientState>()); |
| 1628 clients.push_back(new VEAClient( | 1626 clients.push_back(new VEAClient( |
| 1629 g_env->test_streams_[test_stream_index], notes.back(), | 1627 g_env->test_streams_[test_stream_index], notes.back(), |
| 1630 encoder_save_to_file, keyframe_period, force_bitrate, test_perf, | 1628 encoder_save_to_file, keyframe_period, force_bitrate, test_perf, |
| 1631 mid_stream_bitrate_switch, mid_stream_framerate_switch, verify_output)); | 1629 mid_stream_bitrate_switch, mid_stream_framerate_switch, verify_output)); |
| 1632 | 1630 |
| 1633 encoder_thread.message_loop()->PostTask( | 1631 encoder_thread.message_loop()->PostTask( |
| 1634 FROM_HERE, | 1632 FROM_HERE, base::Bind(&VEAClient::CreateEncoder, |
| 1635 base::Bind(&VEAClient::CreateEncoder, | 1633 base::Unretained(clients.back()))); |
| 1636 base::Unretained(clients.back()))); | |
| 1637 } | 1634 } |
| 1638 | 1635 |
| 1639 // All encoders must pass through states in this order. | 1636 // All encoders must pass through states in this order. |
| 1640 enum ClientState state_transitions[] = { | 1637 enum ClientState state_transitions[] = { |
| 1641 CS_ENCODER_SET, CS_INITIALIZED, CS_ENCODING, CS_FINISHED, CS_VALIDATED}; | 1638 CS_ENCODER_SET, CS_INITIALIZED, CS_ENCODING, CS_FINISHED, CS_VALIDATED}; |
| 1642 | 1639 |
| 1643 // Wait for all encoders to go through all states and finish. | 1640 // Wait for all encoders to go through all states and finish. |
| 1644 // Do this by waiting for all encoders to advance to state n before checking | 1641 // Do this by waiting for all encoders to advance to state n before checking |
| 1645 // state n+1, to verify that they are able to operate concurrently. | 1642 // state n+1, to verify that they are able to operate concurrently. |
| 1646 // It also simulates the real-world usage better, as the main thread, on which | 1643 // It also simulates the real-world usage better, as the main thread, on which |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1729 base::MakeTuple(3, false, 0, false, false, false, false, false))); | 1726 base::MakeTuple(3, false, 0, false, false, false, false, false))); |
| 1730 #endif | 1727 #endif |
| 1731 | 1728 |
| 1732 // TODO(posciak): more tests: | 1729 // TODO(posciak): more tests: |
| 1733 // - async FeedEncoderWithOutput | 1730 // - async FeedEncoderWithOutput |
| 1734 // - out-of-order return of outputs to encoder | 1731 // - out-of-order return of outputs to encoder |
| 1735 // - multiple encoders + decoders | 1732 // - multiple encoders + decoders |
| 1736 // - mid-stream encoder_->Destroy() | 1733 // - mid-stream encoder_->Destroy() |
| 1737 | 1734 |
| 1738 } // namespace | 1735 } // namespace |
| 1739 } // namespace content | 1736 } // namespace media |
| 1740 | 1737 |
| 1741 int main(int argc, char** argv) { | 1738 int main(int argc, char** argv) { |
| 1742 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. | 1739 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. |
| 1743 base::CommandLine::Init(argc, argv); | 1740 base::CommandLine::Init(argc, argv); |
| 1744 | 1741 |
| 1745 base::ShadowingAtExitManager at_exit_manager; | 1742 base::ShadowingAtExitManager at_exit_manager; |
| 1746 base::MessageLoop main_loop; | 1743 base::MessageLoop main_loop; |
| 1747 | 1744 |
| 1748 std::unique_ptr<base::FilePath::StringType> test_stream_data( | 1745 std::unique_ptr<base::FilePath::StringType> test_stream_data( |
| 1749 new base::FilePath::StringType( | 1746 new base::FilePath::StringType( |
| 1750 media::GetTestDataFilePath(content::g_default_in_filename).value() + | 1747 media::GetTestDataFilePath(media::g_default_in_filename).value() + |
| 1751 content::g_default_in_parameters)); | 1748 media::g_default_in_parameters)); |
| 1752 | 1749 |
| 1753 // Needed to enable DVLOG through --vmodule. | 1750 // Needed to enable DVLOG through --vmodule. |
| 1754 logging::LoggingSettings settings; | 1751 logging::LoggingSettings settings; |
| 1755 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; | 1752 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; |
| 1756 LOG_ASSERT(logging::InitLogging(settings)); | 1753 LOG_ASSERT(logging::InitLogging(settings)); |
| 1757 | 1754 |
| 1758 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 1755 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 1759 DCHECK(cmd_line); | 1756 DCHECK(cmd_line); |
| 1760 | 1757 |
| 1761 bool run_at_fps = false; | 1758 bool run_at_fps = false; |
| 1762 bool needs_encode_latency = false; | 1759 bool needs_encode_latency = false; |
| 1763 bool verify_all_output = false; | 1760 bool verify_all_output = false; |
| 1764 base::FilePath log_path; | 1761 base::FilePath log_path; |
| 1765 | 1762 |
| 1766 base::CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | 1763 base::CommandLine::SwitchMap switches = cmd_line->GetSwitches(); |
| 1767 for (base::CommandLine::SwitchMap::const_iterator it = switches.begin(); | 1764 for (base::CommandLine::SwitchMap::const_iterator it = switches.begin(); |
| 1768 it != switches.end(); | 1765 it != switches.end(); ++it) { |
| 1769 ++it) { | |
| 1770 if (it->first == "test_stream_data") { | 1766 if (it->first == "test_stream_data") { |
| 1771 test_stream_data->assign(it->second.c_str()); | 1767 test_stream_data->assign(it->second.c_str()); |
| 1772 continue; | 1768 continue; |
| 1773 } | 1769 } |
| 1774 // Output machine-readable logs with fixed formats to a file. | 1770 // Output machine-readable logs with fixed formats to a file. |
| 1775 if (it->first == "output_log") { | 1771 if (it->first == "output_log") { |
| 1776 log_path = base::FilePath( | 1772 log_path = base::FilePath( |
| 1777 base::FilePath::StringType(it->second.begin(), it->second.end())); | 1773 base::FilePath::StringType(it->second.begin(), it->second.end())); |
| 1778 continue; | 1774 continue; |
| 1779 } | 1775 } |
| 1780 if (it->first == "num_frames_to_encode") { | 1776 if (it->first == "num_frames_to_encode") { |
| 1781 std::string input(it->second.begin(), it->second.end()); | 1777 std::string input(it->second.begin(), it->second.end()); |
| 1782 LOG_ASSERT(base::StringToInt(input, &content::g_num_frames_to_encode)); | 1778 LOG_ASSERT(base::StringToInt(input, &media::g_num_frames_to_encode)); |
| 1783 continue; | 1779 continue; |
| 1784 } | 1780 } |
| 1785 if (it->first == "measure_latency") { | 1781 if (it->first == "measure_latency") { |
| 1786 needs_encode_latency = true; | 1782 needs_encode_latency = true; |
| 1787 continue; | 1783 continue; |
| 1788 } | 1784 } |
| 1789 if (it->first == "fake_encoder") { | 1785 if (it->first == "fake_encoder") { |
| 1790 content::g_fake_encoder = true; | 1786 media::g_fake_encoder = true; |
| 1791 continue; | 1787 continue; |
| 1792 } | 1788 } |
| 1793 if (it->first == "run_at_fps") { | 1789 if (it->first == "run_at_fps") { |
| 1794 run_at_fps = true; | 1790 run_at_fps = true; |
| 1795 continue; | 1791 continue; |
| 1796 } | 1792 } |
| 1797 if (it->first == "verify_all_output") { | 1793 if (it->first == "verify_all_output") { |
| 1798 verify_all_output = true; | 1794 verify_all_output = true; |
| 1799 continue; | 1795 continue; |
| 1800 } | 1796 } |
| 1801 if (it->first == "v" || it->first == "vmodule") | 1797 if (it->first == "v" || it->first == "vmodule") |
| 1802 continue; | 1798 continue; |
| 1803 if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless") | 1799 if (it->first == "ozone-platform" || it->first == "ozone-use-surfaceless") |
| 1804 continue; | 1800 continue; |
| 1805 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1801 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 1806 } | 1802 } |
| 1807 | 1803 |
| 1808 if (needs_encode_latency && !run_at_fps) { | 1804 if (needs_encode_latency && !run_at_fps) { |
| 1809 // Encode latency can only be measured with --run_at_fps. Otherwise, we get | 1805 // Encode latency can only be measured with --run_at_fps. Otherwise, we get |
| 1810 // skewed results since it may queue too many frames at once with the same | 1806 // skewed results since it may queue too many frames at once with the same |
| 1811 // encode start time. | 1807 // encode start time. |
| 1812 LOG(FATAL) << "--measure_latency requires --run_at_fps enabled to work."; | 1808 LOG(FATAL) << "--measure_latency requires --run_at_fps enabled to work."; |
| 1813 } | 1809 } |
| 1814 | 1810 |
| 1815 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) | 1811 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) |
| 1816 content::VaapiWrapper::PreSandboxInitialization(); | 1812 media::VaapiWrapper::PreSandboxInitialization(); |
| 1817 #endif | 1813 #endif |
| 1818 | 1814 |
| 1819 content::g_env = | 1815 media::g_env = |
| 1820 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( | 1816 reinterpret_cast<media::VideoEncodeAcceleratorTestEnvironment*>( |
| 1821 testing::AddGlobalTestEnvironment( | 1817 testing::AddGlobalTestEnvironment( |
| 1822 new content::VideoEncodeAcceleratorTestEnvironment( | 1818 new media::VideoEncodeAcceleratorTestEnvironment( |
| 1823 std::move(test_stream_data), log_path, run_at_fps, | 1819 std::move(test_stream_data), log_path, run_at_fps, |
| 1824 needs_encode_latency, verify_all_output))); | 1820 needs_encode_latency, verify_all_output))); |
| 1825 | 1821 |
| 1826 return RUN_ALL_TESTS(); | 1822 return RUN_ALL_TESTS(); |
| 1827 } | 1823 } |
| OLD | NEW |