Chromium Code Reviews| 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 "base/at_exit.h" | 5 #include "base/at_exit.h" |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/files/memory_mapped_file.h" | 9 #include "base/files/memory_mapped_file.h" |
| 10 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_vector.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 #endif | 26 #endif |
| 27 | 27 |
| 28 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) | 28 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) |
| 29 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" | 29 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h" |
| 30 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 30 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
| 31 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" | 31 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" |
| 32 #else | 32 #else |
| 33 #error The VideoEncodeAcceleratorUnittest is not supported on this platform. | 33 #error The VideoEncodeAcceleratorUnittest is not supported on this platform. |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 #define ALIGN_64_BYTES(x) (((x) + 63) & ~63) | |
| 37 | |
| 36 using media::VideoEncodeAccelerator; | 38 using media::VideoEncodeAccelerator; |
| 37 | 39 |
| 38 namespace content { | 40 namespace content { |
| 39 namespace { | 41 namespace { |
| 40 | 42 |
| 41 const media::VideoFrame::Format kInputFormat = media::VideoFrame::I420; | 43 const media::VideoFrame::Format kInputFormat = media::VideoFrame::I420; |
| 42 | 44 |
| 43 // Arbitrarily chosen to add some depth to the pipeline. | 45 // Arbitrarily chosen to add some depth to the pipeline. |
| 44 const unsigned int kNumOutputBuffers = 4; | 46 const unsigned int kNumOutputBuffers = 4; |
| 45 const unsigned int kNumExtraInputFrames = 4; | 47 const unsigned int kNumExtraInputFrames = 4; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 gfx::Size size; | 107 gfx::Size size; |
| 106 base::MemoryMappedFile input_file; | 108 base::MemoryMappedFile input_file; |
| 107 media::VideoCodecProfile requested_profile; | 109 media::VideoCodecProfile requested_profile; |
| 108 std::string out_filename; | 110 std::string out_filename; |
| 109 unsigned int requested_bitrate; | 111 unsigned int requested_bitrate; |
| 110 unsigned int requested_framerate; | 112 unsigned int requested_framerate; |
| 111 unsigned int requested_subsequent_bitrate; | 113 unsigned int requested_subsequent_bitrate; |
| 112 unsigned int requested_subsequent_framerate; | 114 unsigned int requested_subsequent_framerate; |
| 113 }; | 115 }; |
| 114 | 116 |
| 117 static void PrepareAlignedTempFile( | |
|
Pawel Osciak
2014/08/01 00:48:32
Plenty of things may fail here, need to return val
| |
| 118 const base::FilePath::StringType& filename, | |
| 119 const size_t input_buffer_size) { | |
| 120 base::MemoryMappedFile input_file; | |
| 121 base::File *file = new base::File(base::FilePath("temp" + filename), | |
|
Pawel Osciak
2014/08/01 00:48:32
base::CreateAndOpenTemporaryFile()
henryhsu
2014/08/01 04:55:55
Done.
| |
| 122 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | |
| 123 input_file.Initialize(base::FilePath(filename)); | |
|
Pawel Osciak
2014/08/01 00:48:32
Please check the return value.
henryhsu
2014/08/01 04:55:55
Done.
| |
| 124 | |
| 125 size_t position = 0, frame_offset = 0; | |
|
Pawel Osciak
2014/08/01 00:48:32
off_t
henryhsu
2014/08/01 04:55:55
Done.
| |
| 126 size_t aligned_frame_size = ALIGN_64_BYTES(input_buffer_size); | |
| 127 char*dummy_buffer = new char[aligned_frame_size - input_buffer_size]; | |
| 128 while (position < input_file.length()) { | |
| 129 char *buffer = reinterpret_cast<char*>( | |
| 130 const_cast<uint8*>(input_file.data() + position)); | |
| 131 file->Write(frame_offset, buffer, input_buffer_size); | |
|
Pawel Osciak
2014/08/01 00:48:32
This function may not write all data. It returns t
| |
| 132 file->Write(frame_offset + input_buffer_size, dummy_buffer, | |
|
Pawel Osciak
2014/08/01 00:48:32
Why not use AppendToFile? You don't need to manage
| |
| 133 aligned_frame_size - input_buffer_size); | |
| 134 frame_offset += aligned_frame_size; | |
| 135 position += input_buffer_size; | |
| 136 } | |
| 137 file->Close(); | |
|
Pawel Osciak
2014/08/01 00:48:32
Leaking file?
henryhsu
2014/08/01 04:55:55
Done.
| |
| 138 } | |
|
Pawel Osciak
2014/08/01 00:48:32
And leaking dummy_buffer.
henryhsu
2014/08/01 04:55:55
Done.
| |
| 139 | |
| 115 // Parse |data| into its constituent parts, set the various output fields | 140 // Parse |data| into its constituent parts, set the various output fields |
| 116 // accordingly, read in video stream, and store them to |test_streams|. | 141 // accordingly, read in video stream, and store them to |test_streams|. |
| 117 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, | 142 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, |
| 118 ScopedVector<TestStream>* test_streams) { | 143 ScopedVector<TestStream>* test_streams) { |
| 119 // Split the string to individual test stream data. | 144 // Split the string to individual test stream data. |
| 120 std::vector<base::FilePath::StringType> test_streams_data; | 145 std::vector<base::FilePath::StringType> test_streams_data; |
| 121 base::SplitString(data, ';', &test_streams_data); | 146 base::SplitString(data, ';', &test_streams_data); |
| 122 CHECK_GE(test_streams_data.size(), 1U) << data; | 147 CHECK_GE(test_streams_data.size(), 1U) << data; |
| 123 | 148 |
| 124 // Parse each test stream data and read the input file. | 149 // Parse each test stream data and read the input file. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 154 if (fields.size() >= 8 && !fields[7].empty()) { | 179 if (fields.size() >= 8 && !fields[7].empty()) { |
| 155 CHECK(base::StringToUint(fields[7], | 180 CHECK(base::StringToUint(fields[7], |
| 156 &test_stream->requested_subsequent_bitrate)); | 181 &test_stream->requested_subsequent_bitrate)); |
| 157 } | 182 } |
| 158 | 183 |
| 159 if (fields.size() >= 9 && !fields[8].empty()) { | 184 if (fields.size() >= 9 && !fields[8].empty()) { |
| 160 CHECK(base::StringToUint(fields[8], | 185 CHECK(base::StringToUint(fields[8], |
| 161 &test_stream->requested_subsequent_framerate)); | 186 &test_stream->requested_subsequent_framerate)); |
| 162 } | 187 } |
| 163 | 188 |
| 164 CHECK(test_stream->input_file.Initialize(base::FilePath(filename))); | 189 size_t input_buffer_size = |
| 190 media::VideoFrame::AllocationSize(kInputFormat, test_stream->size); | |
| 191 // Prepare aligned temporary file if frame size is not 64-bytes alignment. | |
| 192 if (input_buffer_size & 63) { | |
|
Pawel Osciak
2014/08/01 00:48:32
Given the fact that I420 translates into V4L2_PIX_
henryhsu
2014/08/01 04:55:55
Done.
| |
| 193 PrepareAlignedTempFile(filename, input_buffer_size); | |
| 194 CHECK(test_stream->input_file.Initialize( | |
| 195 base::FilePath("temp" + filename))); | |
|
Pawel Osciak
2014/08/01 00:48:32
The name should be generated by CreateTemporaryFil
henryhsu
2014/08/01 04:55:55
Done.
| |
| 196 } else { | |
| 197 CHECK(test_stream->input_file.Initialize(base::FilePath(filename))); | |
| 198 } | |
| 165 test_streams->push_back(test_stream); | 199 test_streams->push_back(test_stream); |
| 166 } | 200 } |
| 167 } | 201 } |
| 168 | 202 |
| 169 // Set default parameters of |test_streams| and update the parameters according | 203 // Set default parameters of |test_streams| and update the parameters according |
| 170 // to |mid_stream_bitrate_switch| and |mid_stream_framerate_switch|. | 204 // to |mid_stream_bitrate_switch| and |mid_stream_framerate_switch|. |
| 171 static void UpdateTestStreamData(bool mid_stream_bitrate_switch, | 205 static void UpdateTestStreamData(bool mid_stream_bitrate_switch, |
| 172 bool mid_stream_framerate_switch, | 206 bool mid_stream_framerate_switch, |
| 173 ScopedVector<TestStream>* test_streams) { | 207 ScopedVector<TestStream>* test_streams) { |
| 174 for (size_t i = 0; i < test_streams->size(); i++) { | 208 for (size_t i = 0; i < test_streams->size(); i++) { |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 547 if (save_to_file_) { | 581 if (save_to_file_) { |
| 548 CHECK(!test_stream_.out_filename.empty()); | 582 CHECK(!test_stream_.out_filename.empty()); |
| 549 base::FilePath out_filename(test_stream_.out_filename); | 583 base::FilePath out_filename(test_stream_.out_filename); |
| 550 // This creates or truncates out_filename. | 584 // This creates or truncates out_filename. |
| 551 // Without it, AppendToFile() will not work. | 585 // Without it, AppendToFile() will not work. |
| 552 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); | 586 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); |
| 553 } | 587 } |
| 554 | 588 |
| 555 input_buffer_size_ = | 589 input_buffer_size_ = |
| 556 media::VideoFrame::AllocationSize(kInputFormat, test_stream.size); | 590 media::VideoFrame::AllocationSize(kInputFormat, test_stream.size); |
| 591 input_buffer_size_ = ALIGN_64_BYTES(input_buffer_size_); | |
|
Pawel Osciak
2014/08/01 00:48:32
It would be good if this was calculated in one pla
| |
| 557 CHECK_GT(input_buffer_size_, 0UL); | 592 CHECK_GT(input_buffer_size_, 0UL); |
| 558 | 593 |
| 559 // Calculate the number of frames in the input stream by dividing its length | 594 // Calculate the number of frames in the input stream by dividing its length |
| 560 // in bytes by frame size in bytes. | 595 // in bytes by frame size in bytes. |
| 561 CHECK_EQ(test_stream_.input_file.length() % input_buffer_size_, 0U) | 596 CHECK_EQ(test_stream_.input_file.length() % input_buffer_size_, 0U) |
| 562 << "Stream byte size is not a product of calculated frame byte size"; | 597 << "Stream byte size is not a product of calculated frame byte size"; |
| 563 num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_; | 598 num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_; |
| 564 CHECK_GT(num_frames_in_stream_, 0UL); | 599 CHECK_GT(num_frames_in_stream_, 0UL); |
| 565 CHECK_LE(num_frames_in_stream_, kMaxFrameNum); | 600 CHECK_LE(num_frames_in_stream_, kMaxFrameNum); |
| 566 | 601 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 SetState(CS_ENCODING); | 665 SetState(CS_ENCODING); |
| 631 | 666 |
| 632 // TODO(posciak): For now we only support input streams that meet encoder | 667 // TODO(posciak): For now we only support input streams that meet encoder |
| 633 // size requirements exactly (i.e. coded size == visible size), so that we | 668 // size requirements exactly (i.e. coded size == visible size), so that we |
| 634 // can simply mmap the stream file and feed the encoder directly with chunks | 669 // can simply mmap the stream file and feed the encoder directly with chunks |
| 635 // of that, instead of memcpying from mmapped file into a separate set of | 670 // of that, instead of memcpying from mmapped file into a separate set of |
| 636 // input buffers that would meet the coded size and alignment requirements. | 671 // input buffers that would meet the coded size and alignment requirements. |
| 637 // If/when this is changed, the ARM-specific alignment check below should be | 672 // If/when this is changed, the ARM-specific alignment check below should be |
| 638 // redone as well. | 673 // redone as well. |
| 639 input_coded_size_ = input_coded_size; | 674 input_coded_size_ = input_coded_size; |
| 640 ASSERT_EQ(input_coded_size_, test_stream_.size); | 675 // ASSERT_EQ(input_coded_size_, test_stream_.size); |
| 641 #if defined(ARCH_CPU_ARMEL) | 676 #if defined(ARCH_CPU_ARMEL) |
| 642 // ARM performs CPU cache management with CPU cache line granularity. We thus | 677 // ARM performs CPU cache management with CPU cache line granularity. We thus |
| 643 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned). | 678 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned). |
| 644 // Otherwise newer kernels will refuse to accept them, and on older kernels | 679 // Otherwise newer kernels will refuse to accept them, and on older kernels |
| 645 // we'll be treating ourselves to random corruption. | 680 // we'll be treating ourselves to random corruption. |
| 646 // Since we are just mmapping and passing chunks of the input file, to ensure | 681 // Since we are just mmapping and passing chunks of the input file, to ensure |
| 647 // alignment, if the starting virtual addresses of the frames in it were not | 682 // alignment, if the starting virtual addresses of the frames in it were not |
| 648 // 64 byte-aligned, we'd have to use a separate set of input buffers and copy | 683 // 64 byte-aligned, we'd have to use a separate set of input buffers and copy |
| 649 // the frames into them before sending to the encoder. It would have been an | 684 // the frames into them before sending to the encoder. It would have been an |
| 650 // overkill here though, because, for now at least, we only test resolutions | 685 // overkill here though, because, for now at least, we only test resolutions |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 746 uint8* frame_data = | 781 uint8* frame_data = |
| 747 const_cast<uint8*>(test_stream_.input_file.data() + position); | 782 const_cast<uint8*>(test_stream_.input_file.data() + position); |
| 748 | 783 |
| 749 CHECK_GT(current_framerate_, 0U); | 784 CHECK_GT(current_framerate_, 0U); |
| 750 scoped_refptr<media::VideoFrame> frame = | 785 scoped_refptr<media::VideoFrame> frame = |
| 751 media::VideoFrame::WrapExternalYuvData( | 786 media::VideoFrame::WrapExternalYuvData( |
| 752 kInputFormat, | 787 kInputFormat, |
| 753 input_coded_size_, | 788 input_coded_size_, |
| 754 gfx::Rect(test_stream_.size), | 789 gfx::Rect(test_stream_.size), |
| 755 test_stream_.size, | 790 test_stream_.size, |
| 756 input_coded_size_.width(), | 791 input_coded_size_.width(), |
|
wuchengli
2014/07/30 09:32:50
All strides should be test_stream_.size. Right?
| |
| 757 input_coded_size_.width() / 2, | 792 input_coded_size_.width() / 2, |
| 758 input_coded_size_.width() / 2, | 793 input_coded_size_.width() / 2, |
| 759 frame_data, | 794 frame_data, |
| 760 frame_data + input_coded_size_.GetArea(), | 795 frame_data + input_coded_size_.GetArea(), |
|
wuchengli
2014/07/30 09:32:50
The offsets of u and v planes should also be calcu
| |
| 761 frame_data + (input_coded_size_.GetArea() * 5 / 4), | 796 frame_data + (input_coded_size_.GetArea() * 5 / 4), |
| 762 base::TimeDelta().FromMilliseconds( | 797 base::TimeDelta().FromMilliseconds( |
| 763 next_input_id_ * base::Time::kMillisecondsPerSecond / | 798 next_input_id_ * base::Time::kMillisecondsPerSecond / |
| 764 current_framerate_), | 799 current_framerate_), |
| 765 media::BindToCurrentLoop( | 800 media::BindToCurrentLoop( |
| 766 base::Bind(&VEAClient::InputNoLongerNeededCallback, | 801 base::Bind(&VEAClient::InputNoLongerNeededCallback, |
| 767 base::Unretained(this), | 802 base::Unretained(this), |
| 768 next_input_id_))); | 803 next_input_id_))); |
| 769 | 804 |
| 770 CHECK(inputs_at_client_.insert(next_input_id_).second); | 805 CHECK(inputs_at_client_.insert(next_input_id_).second); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1054 test_stream_data->assign(it->second.c_str()); | 1089 test_stream_data->assign(it->second.c_str()); |
| 1055 continue; | 1090 continue; |
| 1056 } | 1091 } |
| 1057 if (it->first == "v" || it->first == "vmodule") | 1092 if (it->first == "v" || it->first == "vmodule") |
| 1058 continue; | 1093 continue; |
| 1059 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1094 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 1060 } | 1095 } |
| 1061 | 1096 |
| 1062 return RUN_ALL_TESTS(); | 1097 return RUN_ALL_TESTS(); |
| 1063 } | 1098 } |
| OLD | NEW |