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