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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 // parameters if a specific subsequent parameter is required): | 85 // parameters if a specific subsequent parameter is required): |
86 // - |requested_bitrate| requested bitrate in bits per second. | 86 // - |requested_bitrate| requested bitrate in bits per second. |
87 // - |requested_framerate| requested initial framerate. | 87 // - |requested_framerate| requested initial framerate. |
88 // - |requested_subsequent_bitrate| bitrate to switch to in the middle of the | 88 // - |requested_subsequent_bitrate| bitrate to switch to in the middle of the |
89 // stream. | 89 // stream. |
90 // - |requested_subsequent_framerate| framerate to switch to in the middle | 90 // - |requested_subsequent_framerate| framerate to switch to in the middle |
91 // of the stream. | 91 // of the stream. |
92 // Bitrate is only forced for tests that test bitrate. | 92 // Bitrate is only forced for tests that test bitrate. |
93 const char* g_default_in_filename = "bear_320x192_40frames.yuv"; | 93 const char* g_default_in_filename = "bear_320x192_40frames.yuv"; |
94 const char* g_default_in_parameters = ":320:192:1:out.h264:200000"; | 94 const char* g_default_in_parameters = ":320:192:1:out.h264:200000"; |
95 base::FilePath::StringType* g_test_stream_data; | 95 // Environment to store test stream data for all test cases. |
96 class VideoEncodeAcceleratorTestEnvironment; | |
97 VideoEncodeAcceleratorTestEnvironment* g_env; | |
96 | 98 |
97 struct TestStream { | 99 struct TestStream { |
98 TestStream() | 100 TestStream() |
99 : requested_bitrate(0), | 101 : num_frames(0), |
102 aligned_buffer_size(0), | |
103 requested_bitrate(0), | |
100 requested_framerate(0), | 104 requested_framerate(0), |
101 requested_subsequent_bitrate(0), | 105 requested_subsequent_bitrate(0), |
102 requested_subsequent_framerate(0) {} | 106 requested_subsequent_framerate(0) {} |
103 ~TestStream() {} | 107 ~TestStream() {} |
104 | 108 |
105 gfx::Size size; | 109 gfx::Size visible_size; |
106 base::MemoryMappedFile input_file; | 110 gfx::Size coded_size; |
111 unsigned int num_frames; | |
112 | |
113 // Original unaligned input file name provided as an argument to the test. | |
114 // And the file must be an I420 (YUV planar) raw stream. | |
115 std::string in_filename; | |
116 | |
117 // A temporary file used to prepare aligned input buffers of |in_filename|. | |
118 // The file makes sure starting address of YUV planes are 64 byte-aligned. | |
119 base::FilePath aligned_in_file; | |
120 | |
121 // The memory mapping of |aligned_in_file| | |
122 base::MemoryMappedFile mapped_aligned_in_file; | |
123 | |
124 // Byte size of a frame of |aligned_in_file|. | |
125 size_t aligned_buffer_size; | |
126 | |
127 // Byte size for each aligned plane of a frame | |
128 std::vector<size_t> aligned_plane_size; | |
129 | |
130 std::string out_filename; | |
107 media::VideoCodecProfile requested_profile; | 131 media::VideoCodecProfile requested_profile; |
108 std::string out_filename; | |
109 unsigned int requested_bitrate; | 132 unsigned int requested_bitrate; |
110 unsigned int requested_framerate; | 133 unsigned int requested_framerate; |
111 unsigned int requested_subsequent_bitrate; | 134 unsigned int requested_subsequent_bitrate; |
112 unsigned int requested_subsequent_framerate; | 135 unsigned int requested_subsequent_framerate; |
113 }; | 136 }; |
114 | 137 |
138 inline static size_t Align64Bytes(size_t value) { | |
139 return (value + 63) & ~63; | |
140 } | |
141 | |
142 // Write |data| of |size| bytes at |offset| bytes into |file|. | |
143 static bool WriteFile(base::File* file, | |
144 const off_t offset, | |
145 const uint8* data, | |
146 size_t size) { | |
147 size_t written_bytes = 0; | |
148 while (written_bytes < size) { | |
149 int bytes = file->Write(offset + written_bytes, | |
150 reinterpret_cast<const char*>(data + written_bytes), | |
151 size - written_bytes); | |
152 if (bytes <= 0) | |
153 return false; | |
154 written_bytes += bytes; | |
155 } | |
156 return true; | |
157 } | |
158 | |
159 // ARM performs CPU cache management with CPU cache line granularity. We thus | |
160 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned). | |
161 // Otherwise newer kernels will refuse to accept them, and on older kernels | |
162 // we'll be treating ourselves to random corruption. | |
163 // Since we are just mapping and passing chunks of the input file directly to | |
164 // the VEA as input frames to avoid copying large chunks of raw data on each | |
165 // frame and thus affecting performance measurements, we have to prepare a | |
166 // temporary file with all planes aligned to 64-byte boundaries beforehand. | |
167 static void CreateAlignedInputStreamFile(const gfx::Size& coded_size, | |
168 TestStream* test_stream) { | |
169 // Test case may have many encoders and memory should be prepared once. | |
170 if (test_stream->coded_size == coded_size) { | |
171 if (test_stream->mapped_aligned_in_file.IsValid()) | |
Pawel Osciak
2014/09/17 09:58:28
instead of:
if (a)
if (b)
please:
if (a && b)
henryhsu
2014/09/17 10:42:23
Done.
| |
172 return; | |
173 } else { | |
174 // Delete previous temporary aligned file if coded_size changed. | |
Pawel Osciak
2014/09/17 09:58:28
What if we have a multi-instance test? We may dele
henryhsu
2014/09/17 10:42:23
Good idea. We just make sure multi-instance use th
| |
175 if (test_stream->mapped_aligned_in_file.IsValid()) | |
176 base::DeleteFile(test_stream->aligned_in_file, false); | |
177 test_stream->coded_size = coded_size; | |
178 } | |
179 | |
180 size_t num_planes = media::VideoFrame::NumPlanes(kInputFormat); | |
181 std::vector<size_t> padding_sizes(num_planes); | |
182 std::vector<size_t> coded_bpl(num_planes); | |
183 std::vector<size_t> visible_bpl(num_planes); | |
184 std::vector<size_t> visible_plane_rows(num_planes); | |
185 | |
186 // Calculate padding in bytes to be added after each plane required to keep | |
187 // starting addresses of all planes at a 64 byte boudnary. This padding will | |
188 // be added after each plane when copying to the temporary file. | |
189 // At the same time we also need to take into account coded_size requested by | |
190 // the VEA; each row of visible_bpl bytes in the original file needs to be | |
191 // copied into a row of coded_bpl bytes in the aligned file. | |
192 for (size_t i = 0; i < num_planes; i++) { | |
193 size_t size = | |
194 media::VideoFrame::PlaneAllocationSize(kInputFormat, i, coded_size); | |
195 test_stream->aligned_plane_size.push_back(Align64Bytes(size)); | |
196 test_stream->aligned_buffer_size += test_stream->aligned_plane_size.back(); | |
197 | |
198 coded_bpl[i] = | |
199 media::VideoFrame::RowBytes(i, kInputFormat, coded_size.width()); | |
200 visible_bpl[i] = media::VideoFrame::RowBytes( | |
201 i, kInputFormat, test_stream->visible_size.width()); | |
202 visible_plane_rows[i] = media::VideoFrame::Rows( | |
203 i, kInputFormat, test_stream->visible_size.height()); | |
204 size_t padding_rows = | |
205 media::VideoFrame::Rows(i, kInputFormat, coded_size.height()) - | |
206 visible_plane_rows[i]; | |
207 padding_sizes[i] = Align64Bytes(padding_rows * coded_bpl[i]); | |
208 } | |
209 | |
210 base::MemoryMappedFile src_file; | |
211 CHECK(src_file.Initialize(base::FilePath(test_stream->in_filename))); | |
212 CHECK(base::CreateTemporaryFile(&test_stream->aligned_in_file)); | |
213 | |
214 size_t visible_buffer_size = media::VideoFrame::AllocationSize( | |
215 kInputFormat, test_stream->visible_size); | |
216 CHECK_EQ(src_file.length() % visible_buffer_size, 0U) | |
217 << "Stream byte size is not a product of calculated frame byte size"; | |
218 | |
219 test_stream->num_frames = src_file.length() / visible_buffer_size; | |
220 uint32 flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | | |
221 base::File::FLAG_READ; | |
222 | |
223 // Create a temporary file with coded_size length. | |
224 base::File dest_file(test_stream->aligned_in_file, flags); | |
225 CHECK_GT(test_stream->aligned_buffer_size, 0UL); | |
226 dest_file.SetLength(test_stream->aligned_buffer_size * | |
227 test_stream->num_frames); | |
228 | |
229 const uint8* src = src_file.data(); | |
230 off_t dest_offset = 0; | |
231 for (size_t frame = 0; frame < test_stream->num_frames; frame++) { | |
232 for (size_t i = 0; i < num_planes; i++) { | |
233 // Assert that each plane of frame starts at 64 byte boundary. | |
234 ASSERT_EQ(dest_offset & 63, 0) | |
235 << "Planes of frame should be mapped at a 64 byte boundary"; | |
236 for (size_t j = 0; j < visible_plane_rows[i]; j++) { | |
237 CHECK(WriteFile(&dest_file, dest_offset, src, visible_bpl[i])); | |
238 src += visible_bpl[i]; | |
239 dest_offset += coded_bpl[i]; | |
240 } | |
241 dest_offset += padding_sizes[i]; | |
242 } | |
243 } | |
244 CHECK(test_stream->mapped_aligned_in_file.Initialize(dest_file.Pass())); | |
245 // Assert that memory mapped of file starts at 64 byte boundary. So each | |
246 // plane of frames also start at 64 byte boundary. | |
247 ASSERT_EQ( | |
248 reinterpret_cast<off_t>(test_stream->mapped_aligned_in_file.data()) & 63, | |
249 0) | |
250 << "File should be mapped at a 64 byte boundary"; | |
251 | |
252 CHECK_EQ(test_stream->mapped_aligned_in_file.length() % | |
253 test_stream->aligned_buffer_size, | |
254 0U) | |
255 << "Stream byte size is not a product of calculated frame byte size"; | |
256 CHECK_GT(test_stream->num_frames, 0UL); | |
257 CHECK_LE(test_stream->num_frames, kMaxFrameNum); | |
258 } | |
259 | |
115 // Parse |data| into its constituent parts, set the various output fields | 260 // Parse |data| into its constituent parts, set the various output fields |
116 // accordingly, read in video stream, and store them to |test_streams|. | 261 // accordingly, read in video stream, and store them to |test_streams|. |
117 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, | 262 static void ParseAndReadTestStreamData(const base::FilePath::StringType& data, |
118 ScopedVector<TestStream>* test_streams) { | 263 ScopedVector<TestStream>* test_streams) { |
119 // Split the string to individual test stream data. | 264 // Split the string to individual test stream data. |
120 std::vector<base::FilePath::StringType> test_streams_data; | 265 std::vector<base::FilePath::StringType> test_streams_data; |
121 base::SplitString(data, ';', &test_streams_data); | 266 base::SplitString(data, ';', &test_streams_data); |
122 CHECK_GE(test_streams_data.size(), 1U) << data; | 267 CHECK_GE(test_streams_data.size(), 1U) << data; |
123 | 268 |
124 // Parse each test stream data and read the input file. | 269 // Parse each test stream data and read the input file. |
125 for (size_t index = 0; index < test_streams_data.size(); ++index) { | 270 for (size_t index = 0; index < test_streams_data.size(); ++index) { |
126 std::vector<base::FilePath::StringType> fields; | 271 std::vector<base::FilePath::StringType> fields; |
127 base::SplitString(test_streams_data[index], ':', &fields); | 272 base::SplitString(test_streams_data[index], ':', &fields); |
128 CHECK_GE(fields.size(), 4U) << data; | 273 CHECK_GE(fields.size(), 4U) << data; |
129 CHECK_LE(fields.size(), 9U) << data; | 274 CHECK_LE(fields.size(), 9U) << data; |
130 TestStream* test_stream = new TestStream(); | 275 TestStream* test_stream = new TestStream(); |
131 | 276 |
132 base::FilePath::StringType filename = fields[0]; | 277 test_stream->in_filename = fields[0]; |
133 int width, height; | 278 int width, height; |
134 CHECK(base::StringToInt(fields[1], &width)); | 279 CHECK(base::StringToInt(fields[1], &width)); |
135 CHECK(base::StringToInt(fields[2], &height)); | 280 CHECK(base::StringToInt(fields[2], &height)); |
136 test_stream->size = gfx::Size(width, height); | 281 test_stream->visible_size = gfx::Size(width, height); |
137 CHECK(!test_stream->size.IsEmpty()); | 282 CHECK(!test_stream->visible_size.IsEmpty()); |
138 int profile; | 283 int profile; |
139 CHECK(base::StringToInt(fields[3], &profile)); | 284 CHECK(base::StringToInt(fields[3], &profile)); |
140 CHECK_GT(profile, media::VIDEO_CODEC_PROFILE_UNKNOWN); | 285 CHECK_GT(profile, media::VIDEO_CODEC_PROFILE_UNKNOWN); |
141 CHECK_LE(profile, media::VIDEO_CODEC_PROFILE_MAX); | 286 CHECK_LE(profile, media::VIDEO_CODEC_PROFILE_MAX); |
142 test_stream->requested_profile = | 287 test_stream->requested_profile = |
143 static_cast<media::VideoCodecProfile>(profile); | 288 static_cast<media::VideoCodecProfile>(profile); |
144 | 289 |
145 if (fields.size() >= 5 && !fields[4].empty()) | 290 if (fields.size() >= 5 && !fields[4].empty()) |
146 test_stream->out_filename = fields[4]; | 291 test_stream->out_filename = fields[4]; |
147 | 292 |
148 if (fields.size() >= 6 && !fields[5].empty()) | 293 if (fields.size() >= 6 && !fields[5].empty()) |
149 CHECK(base::StringToUint(fields[5], &test_stream->requested_bitrate)); | 294 CHECK(base::StringToUint(fields[5], &test_stream->requested_bitrate)); |
150 | 295 |
151 if (fields.size() >= 7 && !fields[6].empty()) | 296 if (fields.size() >= 7 && !fields[6].empty()) |
152 CHECK(base::StringToUint(fields[6], &test_stream->requested_framerate)); | 297 CHECK(base::StringToUint(fields[6], &test_stream->requested_framerate)); |
153 | 298 |
154 if (fields.size() >= 8 && !fields[7].empty()) { | 299 if (fields.size() >= 8 && !fields[7].empty()) { |
155 CHECK(base::StringToUint(fields[7], | 300 CHECK(base::StringToUint(fields[7], |
156 &test_stream->requested_subsequent_bitrate)); | 301 &test_stream->requested_subsequent_bitrate)); |
157 } | 302 } |
158 | 303 |
159 if (fields.size() >= 9 && !fields[8].empty()) { | 304 if (fields.size() >= 9 && !fields[8].empty()) { |
160 CHECK(base::StringToUint(fields[8], | 305 CHECK(base::StringToUint(fields[8], |
161 &test_stream->requested_subsequent_framerate)); | 306 &test_stream->requested_subsequent_framerate)); |
162 } | 307 } |
163 | |
164 CHECK(test_stream->input_file.Initialize(base::FilePath(filename))); | |
165 test_streams->push_back(test_stream); | 308 test_streams->push_back(test_stream); |
166 } | 309 } |
167 } | 310 } |
168 | 311 |
169 // Set default parameters of |test_streams| and update the parameters according | |
170 // to |mid_stream_bitrate_switch| and |mid_stream_framerate_switch|. | |
171 static void UpdateTestStreamData(bool mid_stream_bitrate_switch, | |
172 bool mid_stream_framerate_switch, | |
173 ScopedVector<TestStream>* test_streams) { | |
174 for (size_t i = 0; i < test_streams->size(); i++) { | |
175 TestStream* test_stream = (*test_streams)[i]; | |
176 // Use defaults for bitrate/framerate if they are not provided. | |
177 if (test_stream->requested_bitrate == 0) | |
178 test_stream->requested_bitrate = kDefaultBitrate; | |
179 | |
180 if (test_stream->requested_framerate == 0) | |
181 test_stream->requested_framerate = kDefaultFramerate; | |
182 | |
183 // If bitrate/framerate switch is requested, use the subsequent values if | |
184 // provided, or, if not, calculate them from their initial values using | |
185 // the default ratios. | |
186 // Otherwise, if a switch is not requested, keep the initial values. | |
187 if (mid_stream_bitrate_switch) { | |
188 if (test_stream->requested_subsequent_bitrate == 0) { | |
189 test_stream->requested_subsequent_bitrate = | |
190 test_stream->requested_bitrate * kDefaultSubsequentBitrateRatio; | |
191 } | |
192 } else { | |
193 test_stream->requested_subsequent_bitrate = | |
194 test_stream->requested_bitrate; | |
195 } | |
196 if (test_stream->requested_subsequent_bitrate == 0) | |
197 test_stream->requested_subsequent_bitrate = 1; | |
198 | |
199 if (mid_stream_framerate_switch) { | |
200 if (test_stream->requested_subsequent_framerate == 0) { | |
201 test_stream->requested_subsequent_framerate = | |
202 test_stream->requested_framerate * kDefaultSubsequentFramerateRatio; | |
203 } | |
204 } else { | |
205 test_stream->requested_subsequent_framerate = | |
206 test_stream->requested_framerate; | |
207 } | |
208 if (test_stream->requested_subsequent_framerate == 0) | |
209 test_stream->requested_subsequent_framerate = 1; | |
210 } | |
211 } | |
212 | |
213 enum ClientState { | 312 enum ClientState { |
214 CS_CREATED, | 313 CS_CREATED, |
215 CS_ENCODER_SET, | 314 CS_ENCODER_SET, |
216 CS_INITIALIZED, | 315 CS_INITIALIZED, |
217 CS_ENCODING, | 316 CS_ENCODING, |
218 CS_FINISHED, | 317 CS_FINISHED, |
219 CS_ERROR, | 318 CS_ERROR, |
220 }; | 319 }; |
221 | 320 |
222 // Performs basic, codec-specific sanity checks on the stream buffers passed | 321 // Performs basic, codec-specific sanity checks on the stream buffers passed |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
361 validator.reset(new VP8Validator(frame_cb)); | 460 validator.reset(new VP8Validator(frame_cb)); |
362 } else { | 461 } else { |
363 LOG(FATAL) << "Unsupported profile: " << profile; | 462 LOG(FATAL) << "Unsupported profile: " << profile; |
364 } | 463 } |
365 | 464 |
366 return validator.Pass(); | 465 return validator.Pass(); |
367 } | 466 } |
368 | 467 |
369 class VEAClient : public VideoEncodeAccelerator::Client { | 468 class VEAClient : public VideoEncodeAccelerator::Client { |
370 public: | 469 public: |
371 VEAClient(const TestStream& test_stream, | 470 VEAClient(TestStream* test_stream, |
372 ClientStateNotification<ClientState>* note, | 471 ClientStateNotification<ClientState>* note, |
373 bool save_to_file, | 472 bool save_to_file, |
374 unsigned int keyframe_period, | 473 unsigned int keyframe_period, |
375 bool force_bitrate, | 474 bool force_bitrate, |
376 bool test_perf); | 475 bool test_perf, |
476 bool mid_stream_bitrate_switch, | |
477 bool mid_stream_framerate_switch); | |
377 virtual ~VEAClient(); | 478 virtual ~VEAClient(); |
378 void CreateEncoder(); | 479 void CreateEncoder(); |
379 void DestroyEncoder(); | 480 void DestroyEncoder(); |
380 | 481 |
381 // Return the number of encoded frames per second. | 482 // Return the number of encoded frames per second. |
382 double frames_per_second(); | 483 double frames_per_second(); |
383 | 484 |
384 // VideoDecodeAccelerator::Client implementation. | 485 // VideoDecodeAccelerator::Client implementation. |
385 virtual void RequireBitstreamBuffers(unsigned int input_count, | 486 virtual void RequireBitstreamBuffers(unsigned int input_count, |
386 const gfx::Size& input_coded_size, | 487 const gfx::Size& input_coded_size, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 void VerifyStreamProperties(); | 521 void VerifyStreamProperties(); |
421 | 522 |
422 // Test codec performance, failing the test if we are currently running | 523 // Test codec performance, failing the test if we are currently running |
423 // the performance test. | 524 // the performance test. |
424 void VerifyPerf(); | 525 void VerifyPerf(); |
425 | 526 |
426 // Prepare and return a frame wrapping the data at |position| bytes in | 527 // Prepare and return a frame wrapping the data at |position| bytes in |
427 // the input stream, ready to be sent to encoder. | 528 // the input stream, ready to be sent to encoder. |
428 scoped_refptr<media::VideoFrame> PrepareInputFrame(off_t position); | 529 scoped_refptr<media::VideoFrame> PrepareInputFrame(off_t position); |
429 | 530 |
531 // Update the parameters according to |mid_stream_bitrate_switch| and | |
532 // |mid_stream_framerate_switch|. | |
533 void UpdateTestStreamData(bool mid_stream_bitrate_switch, | |
534 bool mid_stream_framerate_switch); | |
535 | |
430 ClientState state_; | 536 ClientState state_; |
431 scoped_ptr<VideoEncodeAccelerator> encoder_; | 537 scoped_ptr<VideoEncodeAccelerator> encoder_; |
432 | 538 |
433 const TestStream& test_stream_; | 539 TestStream* test_stream_; |
434 // Used to notify another thread about the state. VEAClient does not own this. | 540 // Used to notify another thread about the state. VEAClient does not own this. |
435 ClientStateNotification<ClientState>* note_; | 541 ClientStateNotification<ClientState>* note_; |
436 | 542 |
437 // Ids assigned to VideoFrames (start at 1 for easy comparison with | 543 // Ids assigned to VideoFrames (start at 1 for easy comparison with |
438 // num_encoded_frames_). | 544 // num_encoded_frames_). |
439 std::set<int32> inputs_at_client_; | 545 std::set<int32> inputs_at_client_; |
440 int32 next_input_id_; | 546 int32 next_input_id_; |
441 | 547 |
442 // Ids for output BitstreamBuffers. | 548 // Ids for output BitstreamBuffers. |
443 typedef std::map<int32, base::SharedMemory*> IdToSHM; | 549 typedef std::map<int32, base::SharedMemory*> IdToSHM; |
444 ScopedVector<base::SharedMemory> output_shms_; | 550 ScopedVector<base::SharedMemory> output_shms_; |
445 IdToSHM output_buffers_at_client_; | 551 IdToSHM output_buffers_at_client_; |
446 int32 next_output_buffer_id_; | 552 int32 next_output_buffer_id_; |
447 | 553 |
448 // Current offset into input stream. | 554 // Current offset into input stream. |
449 off_t pos_in_input_stream_; | 555 off_t pos_in_input_stream_; |
450 // Byte size of an input frame. | |
451 size_t input_buffer_size_; | |
452 gfx::Size input_coded_size_; | 556 gfx::Size input_coded_size_; |
453 // Requested by encoder. | 557 // Requested by encoder. |
454 unsigned int num_required_input_buffers_; | 558 unsigned int num_required_input_buffers_; |
455 size_t output_buffer_size_; | 559 size_t output_buffer_size_; |
456 | 560 |
457 // Precalculated number of frames in the stream. | 561 // Number of frames to encode. This may differ from the number of frames in |
458 unsigned int num_frames_in_stream_; | 562 // stream if we need more frames for bitrate tests. |
459 | |
460 // Number of frames to encode. This may differ from num_frames_in_stream_ if | |
461 // we need more frames for bitrate tests. | |
462 unsigned int num_frames_to_encode_; | 563 unsigned int num_frames_to_encode_; |
463 | 564 |
464 // Number of encoded frames we've got from the encoder thus far. | 565 // Number of encoded frames we've got from the encoder thus far. |
465 unsigned int num_encoded_frames_; | 566 unsigned int num_encoded_frames_; |
466 | 567 |
467 // Frames since last bitrate verification. | 568 // Frames since last bitrate verification. |
468 unsigned int num_frames_since_last_check_; | 569 unsigned int num_frames_since_last_check_; |
469 | 570 |
470 // True if received a keyframe while processing current bitstream buffer. | 571 // True if received a keyframe while processing current bitstream buffer. |
471 bool seen_keyframe_in_this_buffer_; | 572 bool seen_keyframe_in_this_buffer_; |
(...skipping 26 matching lines...) Expand all Loading... | |
498 scoped_ptr<StreamValidator> validator_; | 599 scoped_ptr<StreamValidator> validator_; |
499 | 600 |
500 // The time when the encoding started. | 601 // The time when the encoding started. |
501 base::TimeTicks encode_start_time_; | 602 base::TimeTicks encode_start_time_; |
502 | 603 |
503 // The time when the last encoded frame is ready. | 604 // The time when the last encoded frame is ready. |
504 base::TimeTicks last_frame_ready_time_; | 605 base::TimeTicks last_frame_ready_time_; |
505 | 606 |
506 // All methods of this class should be run on the same thread. | 607 // All methods of this class should be run on the same thread. |
507 base::ThreadChecker thread_checker_; | 608 base::ThreadChecker thread_checker_; |
609 | |
610 // Requested bitrate in bits per second. | |
611 unsigned int requested_bitrate_; | |
612 | |
613 // Requested initial framerate. | |
614 unsigned int requested_framerate_; | |
615 | |
616 // Bitrate to switch to in the middle of the stream. | |
617 unsigned int requested_subsequent_bitrate_; | |
618 | |
619 // Framerate to switch to in the middle of the stream. | |
620 unsigned int requested_subsequent_framerate_; | |
508 }; | 621 }; |
509 | 622 |
510 VEAClient::VEAClient(const TestStream& test_stream, | 623 VEAClient::VEAClient(TestStream* test_stream, |
511 ClientStateNotification<ClientState>* note, | 624 ClientStateNotification<ClientState>* note, |
512 bool save_to_file, | 625 bool save_to_file, |
513 unsigned int keyframe_period, | 626 unsigned int keyframe_period, |
514 bool force_bitrate, | 627 bool force_bitrate, |
515 bool test_perf) | 628 bool test_perf, |
629 bool mid_stream_bitrate_switch, | |
630 bool mid_stream_framerate_switch) | |
516 : state_(CS_CREATED), | 631 : state_(CS_CREATED), |
517 test_stream_(test_stream), | 632 test_stream_(test_stream), |
518 note_(note), | 633 note_(note), |
519 next_input_id_(1), | 634 next_input_id_(1), |
520 next_output_buffer_id_(0), | 635 next_output_buffer_id_(0), |
521 pos_in_input_stream_(0), | 636 pos_in_input_stream_(0), |
522 input_buffer_size_(0), | |
523 num_required_input_buffers_(0), | 637 num_required_input_buffers_(0), |
524 output_buffer_size_(0), | 638 output_buffer_size_(0), |
525 num_frames_in_stream_(0), | |
526 num_frames_to_encode_(0), | 639 num_frames_to_encode_(0), |
527 num_encoded_frames_(0), | 640 num_encoded_frames_(0), |
528 num_frames_since_last_check_(0), | 641 num_frames_since_last_check_(0), |
529 seen_keyframe_in_this_buffer_(false), | 642 seen_keyframe_in_this_buffer_(false), |
530 save_to_file_(save_to_file), | 643 save_to_file_(save_to_file), |
531 keyframe_period_(keyframe_period), | 644 keyframe_period_(keyframe_period), |
532 keyframe_requested_at_(kMaxFrameNum), | 645 keyframe_requested_at_(kMaxFrameNum), |
533 force_bitrate_(force_bitrate), | 646 force_bitrate_(force_bitrate), |
534 current_requested_bitrate_(0), | 647 current_requested_bitrate_(0), |
535 current_framerate_(0), | 648 current_framerate_(0), |
536 encoded_stream_size_since_last_check_(0), | 649 encoded_stream_size_since_last_check_(0), |
537 test_perf_(test_perf) { | 650 test_perf_(test_perf), |
651 requested_bitrate_(0), | |
652 requested_framerate_(0), | |
653 requested_subsequent_bitrate_(0), | |
654 requested_subsequent_framerate_(0) { | |
538 if (keyframe_period_) | 655 if (keyframe_period_) |
539 CHECK_LT(kMaxKeyframeDelay, keyframe_period_); | 656 CHECK_LT(kMaxKeyframeDelay, keyframe_period_); |
540 | 657 |
541 validator_ = StreamValidator::Create( | 658 validator_ = StreamValidator::Create( |
542 test_stream_.requested_profile, | 659 test_stream_->requested_profile, |
543 base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this))); | 660 base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this))); |
544 | 661 |
545 CHECK(validator_.get()); | 662 CHECK(validator_.get()); |
546 | 663 |
547 if (save_to_file_) { | 664 if (save_to_file_) { |
548 CHECK(!test_stream_.out_filename.empty()); | 665 CHECK(!test_stream_->out_filename.empty()); |
549 base::FilePath out_filename(test_stream_.out_filename); | 666 base::FilePath out_filename(test_stream_->out_filename); |
550 // This creates or truncates out_filename. | 667 // This creates or truncates out_filename. |
551 // Without it, AppendToFile() will not work. | 668 // Without it, AppendToFile() will not work. |
552 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); | 669 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); |
553 } | 670 } |
554 | 671 |
555 input_buffer_size_ = | 672 // Initialize the parameters of the test streams. |
556 media::VideoFrame::AllocationSize(kInputFormat, test_stream.size); | 673 UpdateTestStreamData(mid_stream_bitrate_switch, mid_stream_framerate_switch); |
557 CHECK_GT(input_buffer_size_, 0UL); | |
558 | |
559 // Calculate the number of frames in the input stream by dividing its length | |
560 // in bytes by frame size in bytes. | |
561 CHECK_EQ(test_stream_.input_file.length() % input_buffer_size_, 0U) | |
562 << "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_; | |
564 CHECK_GT(num_frames_in_stream_, 0UL); | |
565 CHECK_LE(num_frames_in_stream_, kMaxFrameNum); | |
566 | |
567 // We may need to loop over the stream more than once if more frames than | |
568 // provided is required for bitrate tests. | |
569 if (force_bitrate_ && num_frames_in_stream_ < kMinFramesForBitrateTests) { | |
570 DVLOG(1) << "Stream too short for bitrate test (" << num_frames_in_stream_ | |
571 << " frames), will loop it to reach " << kMinFramesForBitrateTests | |
572 << " frames"; | |
573 num_frames_to_encode_ = kMinFramesForBitrateTests; | |
574 } else { | |
575 num_frames_to_encode_ = num_frames_in_stream_; | |
576 } | |
577 | 674 |
578 thread_checker_.DetachFromThread(); | 675 thread_checker_.DetachFromThread(); |
579 } | 676 } |
580 | 677 |
581 VEAClient::~VEAClient() { CHECK(!has_encoder()); } | 678 VEAClient::~VEAClient() { CHECK(!has_encoder()); } |
582 | 679 |
583 void VEAClient::CreateEncoder() { | 680 void VEAClient::CreateEncoder() { |
584 DCHECK(thread_checker_.CalledOnValidThread()); | 681 DCHECK(thread_checker_.CalledOnValidThread()); |
585 CHECK(!has_encoder()); | 682 CHECK(!has_encoder()); |
586 | 683 |
587 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) | 684 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL) |
588 scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); | 685 scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); |
589 encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); | 686 encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); |
590 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) | 687 #elif defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY) && defined(USE_X11) |
591 encoder_.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay())); | 688 encoder_.reset(new VaapiVideoEncodeAccelerator(gfx::GetXDisplay())); |
592 #endif | 689 #endif |
593 | 690 |
594 SetState(CS_ENCODER_SET); | 691 SetState(CS_ENCODER_SET); |
595 | 692 |
596 DVLOG(1) << "Profile: " << test_stream_.requested_profile | 693 DVLOG(1) << "Profile: " << test_stream_->requested_profile |
597 << ", initial bitrate: " << test_stream_.requested_bitrate; | 694 << ", initial bitrate: " << requested_bitrate_; |
598 if (!encoder_->Initialize(kInputFormat, | 695 if (!encoder_->Initialize(kInputFormat, |
599 test_stream_.size, | 696 test_stream_->visible_size, |
600 test_stream_.requested_profile, | 697 test_stream_->requested_profile, |
601 test_stream_.requested_bitrate, | 698 requested_bitrate_, |
602 this)) { | 699 this)) { |
603 DLOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed"; | 700 DLOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed"; |
604 SetState(CS_ERROR); | 701 SetState(CS_ERROR); |
605 return; | 702 return; |
606 } | 703 } |
607 | 704 |
608 SetStreamParameters(test_stream_.requested_bitrate, | 705 SetStreamParameters(requested_bitrate_, requested_framerate_); |
609 test_stream_.requested_framerate); | |
610 SetState(CS_INITIALIZED); | 706 SetState(CS_INITIALIZED); |
611 } | 707 } |
612 | 708 |
613 void VEAClient::DestroyEncoder() { | 709 void VEAClient::DestroyEncoder() { |
614 DCHECK(thread_checker_.CalledOnValidThread()); | 710 DCHECK(thread_checker_.CalledOnValidThread()); |
615 if (!has_encoder()) | 711 if (!has_encoder()) |
616 return; | 712 return; |
617 encoder_.reset(); | 713 encoder_.reset(); |
618 } | 714 } |
619 | 715 |
716 void VEAClient::UpdateTestStreamData(bool mid_stream_bitrate_switch, | |
717 bool mid_stream_framerate_switch) { | |
718 // Use defaults for bitrate/framerate if they are not provided. | |
719 if (test_stream_->requested_bitrate == 0) | |
720 requested_bitrate_ = kDefaultBitrate; | |
721 else | |
722 requested_bitrate_ = test_stream_->requested_bitrate; | |
723 | |
724 if (test_stream_->requested_framerate == 0) | |
725 requested_framerate_ = kDefaultFramerate; | |
726 else | |
727 requested_framerate_ = test_stream_->requested_framerate; | |
728 | |
729 // If bitrate/framerate switch is requested, use the subsequent values if | |
730 // provided, or, if not, calculate them from their initial values using | |
731 // the default ratios. | |
732 // Otherwise, if a switch is not requested, keep the initial values. | |
733 if (mid_stream_bitrate_switch) { | |
734 if (test_stream_->requested_subsequent_bitrate == 0) | |
735 requested_subsequent_bitrate_ = | |
736 requested_bitrate_ * kDefaultSubsequentBitrateRatio; | |
737 else | |
738 requested_subsequent_bitrate_ = | |
739 test_stream_->requested_subsequent_bitrate; | |
740 } else { | |
741 requested_subsequent_bitrate_ = requested_bitrate_; | |
742 } | |
743 if (requested_subsequent_bitrate_ == 0) | |
744 requested_subsequent_bitrate_ = 1; | |
745 | |
746 if (mid_stream_framerate_switch) { | |
747 if (test_stream_->requested_subsequent_framerate == 0) | |
748 requested_subsequent_framerate_ = | |
749 requested_framerate_ * kDefaultSubsequentFramerateRatio; | |
750 else | |
751 requested_subsequent_framerate_ = | |
752 test_stream_->requested_subsequent_framerate; | |
753 } else { | |
754 requested_subsequent_framerate_ = requested_framerate_; | |
755 } | |
756 if (requested_subsequent_framerate_ == 0) | |
757 requested_subsequent_framerate_ = 1; | |
758 } | |
759 | |
620 double VEAClient::frames_per_second() { | 760 double VEAClient::frames_per_second() { |
621 base::TimeDelta duration = last_frame_ready_time_ - encode_start_time_; | 761 base::TimeDelta duration = last_frame_ready_time_ - encode_start_time_; |
622 return num_encoded_frames_ / duration.InSecondsF(); | 762 return num_encoded_frames_ / duration.InSecondsF(); |
623 } | 763 } |
624 | 764 |
625 void VEAClient::RequireBitstreamBuffers(unsigned int input_count, | 765 void VEAClient::RequireBitstreamBuffers(unsigned int input_count, |
626 const gfx::Size& input_coded_size, | 766 const gfx::Size& input_coded_size, |
627 size_t output_size) { | 767 size_t output_size) { |
628 DCHECK(thread_checker_.CalledOnValidThread()); | 768 DCHECK(thread_checker_.CalledOnValidThread()); |
629 ASSERT_EQ(state_, CS_INITIALIZED); | 769 ASSERT_EQ(state_, CS_INITIALIZED); |
630 SetState(CS_ENCODING); | 770 SetState(CS_ENCODING); |
631 | 771 |
632 // TODO(posciak): For now we only support input streams that meet encoder | 772 CreateAlignedInputStreamFile(input_coded_size, test_stream_); |
633 // size requirements exactly (i.e. coded size == visible size), so that we | 773 |
634 // can simply mmap the stream file and feed the encoder directly with chunks | 774 // We may need to loop over the stream more than once if more frames than |
635 // of that, instead of memcpying from mmapped file into a separate set of | 775 // provided is required for bitrate tests. |
636 // input buffers that would meet the coded size and alignment requirements. | 776 if (force_bitrate_ && test_stream_->num_frames < kMinFramesForBitrateTests) { |
637 // If/when this is changed, the ARM-specific alignment check below should be | 777 DVLOG(1) << "Stream too short for bitrate test (" |
638 // redone as well. | 778 << test_stream_->num_frames << " frames), will loop it to reach " |
779 << kMinFramesForBitrateTests << " frames"; | |
780 num_frames_to_encode_ = kMinFramesForBitrateTests; | |
781 } else { | |
782 num_frames_to_encode_ = test_stream_->num_frames; | |
783 } | |
784 | |
639 input_coded_size_ = input_coded_size; | 785 input_coded_size_ = input_coded_size; |
640 ASSERT_EQ(input_coded_size_, test_stream_.size); | |
641 #if defined(ARCH_CPU_ARMEL) | |
642 // 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). | |
644 // Otherwise newer kernels will refuse to accept them, and on older kernels | |
645 // we'll be treating ourselves to random corruption. | |
646 // 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 | |
648 // 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 | |
650 // overkill here though, because, for now at least, we only test resolutions | |
651 // that result in proper alignment, and it would have also interfered with | |
652 // performance testing. So just assert that the frame size is a multiple of | |
653 // 64 bytes. This ensures all frames start at 64-byte boundary, because | |
654 // MemoryMappedFile should be mmapp()ed at virtual page start as well. | |
655 ASSERT_EQ(input_buffer_size_ & 63, 0u) | |
656 << "Frame size has to be a multiple of 64 bytes"; | |
657 ASSERT_EQ(reinterpret_cast<off_t>(test_stream_.input_file.data()) & 63, 0) | |
658 << "Mapped file should be mapped at a 64 byte boundary"; | |
659 #endif | |
660 | |
661 num_required_input_buffers_ = input_count; | 786 num_required_input_buffers_ = input_count; |
662 ASSERT_GT(num_required_input_buffers_, 0UL); | 787 ASSERT_GT(num_required_input_buffers_, 0UL); |
663 | 788 |
664 output_buffer_size_ = output_size; | 789 output_buffer_size_ = output_size; |
665 ASSERT_GT(output_buffer_size_, 0UL); | 790 ASSERT_GT(output_buffer_size_, 0UL); |
666 | 791 |
667 for (unsigned int i = 0; i < kNumOutputBuffers; ++i) { | 792 for (unsigned int i = 0; i < kNumOutputBuffers; ++i) { |
668 base::SharedMemory* shm = new base::SharedMemory(); | 793 base::SharedMemory* shm = new base::SharedMemory(); |
669 CHECK(shm->CreateAndMapAnonymous(output_buffer_size_)); | 794 CHECK(shm->CreateAndMapAnonymous(output_buffer_size_)); |
670 output_shms_.push_back(shm); | 795 output_shms_.push_back(shm); |
(...skipping 23 matching lines...) Expand all Loading... | |
694 const uint8* stream_ptr = static_cast<const uint8*>(shm->memory()); | 819 const uint8* stream_ptr = static_cast<const uint8*>(shm->memory()); |
695 if (payload_size > 0) | 820 if (payload_size > 0) |
696 validator_->ProcessStreamBuffer(stream_ptr, payload_size); | 821 validator_->ProcessStreamBuffer(stream_ptr, payload_size); |
697 | 822 |
698 EXPECT_EQ(key_frame, seen_keyframe_in_this_buffer_); | 823 EXPECT_EQ(key_frame, seen_keyframe_in_this_buffer_); |
699 seen_keyframe_in_this_buffer_ = false; | 824 seen_keyframe_in_this_buffer_ = false; |
700 | 825 |
701 if (save_to_file_) { | 826 if (save_to_file_) { |
702 int size = base::checked_cast<int>(payload_size); | 827 int size = base::checked_cast<int>(payload_size); |
703 EXPECT_EQ(base::AppendToFile( | 828 EXPECT_EQ(base::AppendToFile( |
704 base::FilePath::FromUTF8Unsafe(test_stream_.out_filename), | 829 base::FilePath::FromUTF8Unsafe(test_stream_->out_filename), |
705 static_cast<char*>(shm->memory()), | 830 static_cast<char*>(shm->memory()), |
706 size), | 831 size), |
707 size); | 832 size); |
708 } | 833 } |
709 | 834 |
710 FeedEncoderWithOutput(shm); | 835 FeedEncoderWithOutput(shm); |
711 } | 836 } |
712 | 837 |
713 void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) { | 838 void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) { |
714 DCHECK(thread_checker_.CalledOnValidThread()); | 839 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 19 matching lines...) Expand all Loading... | |
734 } | 859 } |
735 | 860 |
736 void VEAClient::InputNoLongerNeededCallback(int32 input_id) { | 861 void VEAClient::InputNoLongerNeededCallback(int32 input_id) { |
737 std::set<int32>::iterator it = inputs_at_client_.find(input_id); | 862 std::set<int32>::iterator it = inputs_at_client_.find(input_id); |
738 ASSERT_NE(it, inputs_at_client_.end()); | 863 ASSERT_NE(it, inputs_at_client_.end()); |
739 inputs_at_client_.erase(it); | 864 inputs_at_client_.erase(it); |
740 FeedEncoderWithInputs(); | 865 FeedEncoderWithInputs(); |
741 } | 866 } |
742 | 867 |
743 scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame(off_t position) { | 868 scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame(off_t position) { |
744 CHECK_LE(position + input_buffer_size_, test_stream_.input_file.length()); | 869 CHECK_LE(position + test_stream_->aligned_buffer_size, |
870 test_stream_->mapped_aligned_in_file.length()); | |
745 | 871 |
746 uint8* frame_data = | 872 uint8* frame_data_y = const_cast<uint8*>( |
747 const_cast<uint8*>(test_stream_.input_file.data() + position); | 873 test_stream_->mapped_aligned_in_file.data() + position); |
874 uint8* frame_data_u = frame_data_y + test_stream_->aligned_plane_size[0]; | |
875 uint8* frame_data_v = frame_data_u + test_stream_->aligned_plane_size[1]; | |
748 | 876 |
749 CHECK_GT(current_framerate_, 0U); | 877 CHECK_GT(current_framerate_, 0U); |
750 scoped_refptr<media::VideoFrame> frame = | 878 scoped_refptr<media::VideoFrame> frame = |
751 media::VideoFrame::WrapExternalYuvData( | 879 media::VideoFrame::WrapExternalYuvData( |
752 kInputFormat, | 880 kInputFormat, |
753 input_coded_size_, | 881 input_coded_size_, |
754 gfx::Rect(test_stream_.size), | 882 gfx::Rect(test_stream_->visible_size), |
755 test_stream_.size, | 883 test_stream_->visible_size, |
756 input_coded_size_.width(), | 884 input_coded_size_.width(), |
757 input_coded_size_.width() / 2, | 885 input_coded_size_.width() / 2, |
758 input_coded_size_.width() / 2, | 886 input_coded_size_.width() / 2, |
759 frame_data, | 887 frame_data_y, |
760 frame_data + input_coded_size_.GetArea(), | 888 frame_data_u, |
761 frame_data + (input_coded_size_.GetArea() * 5 / 4), | 889 frame_data_v, |
762 base::TimeDelta().FromMilliseconds( | 890 base::TimeDelta().FromMilliseconds( |
763 next_input_id_ * base::Time::kMillisecondsPerSecond / | 891 next_input_id_ * base::Time::kMillisecondsPerSecond / |
764 current_framerate_), | 892 current_framerate_), |
765 media::BindToCurrentLoop( | 893 media::BindToCurrentLoop( |
766 base::Bind(&VEAClient::InputNoLongerNeededCallback, | 894 base::Bind(&VEAClient::InputNoLongerNeededCallback, |
767 base::Unretained(this), | 895 base::Unretained(this), |
768 next_input_id_))); | 896 next_input_id_))); |
769 | 897 |
770 CHECK(inputs_at_client_.insert(next_input_id_).second); | 898 CHECK(inputs_at_client_.insert(next_input_id_).second); |
771 ++next_input_id_; | 899 ++next_input_id_; |
772 | 900 |
773 return frame; | 901 return frame; |
774 } | 902 } |
775 | 903 |
776 void VEAClient::FeedEncoderWithInputs() { | 904 void VEAClient::FeedEncoderWithInputs() { |
777 if (!has_encoder()) | 905 if (!has_encoder()) |
778 return; | 906 return; |
779 | 907 |
780 if (state_ != CS_ENCODING) | 908 if (state_ != CS_ENCODING) |
781 return; | 909 return; |
782 | 910 |
783 while (inputs_at_client_.size() < | 911 while (inputs_at_client_.size() < |
784 num_required_input_buffers_ + kNumExtraInputFrames) { | 912 num_required_input_buffers_ + kNumExtraInputFrames) { |
785 size_t bytes_left = test_stream_.input_file.length() - pos_in_input_stream_; | 913 size_t bytes_left = |
786 if (bytes_left < input_buffer_size_) { | 914 test_stream_->mapped_aligned_in_file.length() - pos_in_input_stream_; |
915 if (bytes_left < test_stream_->aligned_buffer_size) { | |
787 DCHECK_EQ(bytes_left, 0UL); | 916 DCHECK_EQ(bytes_left, 0UL); |
788 // Rewind if at the end of stream and we are still encoding. | 917 // Rewind if at the end of stream and we are still encoding. |
789 // This is to flush the encoder with additional frames from the beginning | 918 // This is to flush the encoder with additional frames from the beginning |
790 // of the stream, or if the stream is shorter that the number of frames | 919 // of the stream, or if the stream is shorter that the number of frames |
791 // we require for bitrate tests. | 920 // we require for bitrate tests. |
792 pos_in_input_stream_ = 0; | 921 pos_in_input_stream_ = 0; |
793 continue; | 922 continue; |
794 } | 923 } |
795 | 924 |
796 bool force_keyframe = false; | 925 bool force_keyframe = false; |
797 if (keyframe_period_ && next_input_id_ % keyframe_period_ == 0) { | 926 if (keyframe_period_ && next_input_id_ % keyframe_period_ == 0) { |
798 keyframe_requested_at_ = next_input_id_; | 927 keyframe_requested_at_ = next_input_id_; |
799 force_keyframe = true; | 928 force_keyframe = true; |
800 } | 929 } |
801 | 930 |
802 scoped_refptr<media::VideoFrame> video_frame = | 931 scoped_refptr<media::VideoFrame> video_frame = |
803 PrepareInputFrame(pos_in_input_stream_); | 932 PrepareInputFrame(pos_in_input_stream_); |
804 pos_in_input_stream_ += input_buffer_size_; | 933 pos_in_input_stream_ += test_stream_->aligned_buffer_size; |
805 | 934 |
806 encoder_->Encode(video_frame, force_keyframe); | 935 encoder_->Encode(video_frame, force_keyframe); |
807 } | 936 } |
808 } | 937 } |
809 | 938 |
810 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { | 939 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { |
811 if (!has_encoder()) | 940 if (!has_encoder()) |
812 return; | 941 return; |
813 | 942 |
814 if (state_ != CS_ENCODING) | 943 if (state_ != CS_ENCODING) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
847 // is asynchronous, i.e. not bound to any concrete frame, and because | 976 // is asynchronous, i.e. not bound to any concrete frame, and because |
848 // the pipeline can be deeper than one frame), at that frame, or after. | 977 // the pipeline can be deeper than one frame), at that frame, or after. |
849 // So the only constraints we put here is that we get a keyframe not | 978 // So the only constraints we put here is that we get a keyframe not |
850 // earlier than we requested one (in time), and not later than | 979 // earlier than we requested one (in time), and not later than |
851 // kMaxKeyframeDelay frames after the frame, for which we requested | 980 // kMaxKeyframeDelay frames after the frame, for which we requested |
852 // it, comes back encoded. | 981 // it, comes back encoded. |
853 EXPECT_LE(num_encoded_frames_, keyframe_requested_at_ + kMaxKeyframeDelay); | 982 EXPECT_LE(num_encoded_frames_, keyframe_requested_at_ + kMaxKeyframeDelay); |
854 | 983 |
855 if (num_encoded_frames_ == num_frames_to_encode_ / 2) { | 984 if (num_encoded_frames_ == num_frames_to_encode_ / 2) { |
856 VerifyStreamProperties(); | 985 VerifyStreamProperties(); |
857 if (test_stream_.requested_subsequent_bitrate != | 986 if (requested_subsequent_bitrate_ != current_requested_bitrate_ || |
858 current_requested_bitrate_ || | 987 requested_subsequent_framerate_ != current_framerate_) { |
859 test_stream_.requested_subsequent_framerate != current_framerate_) { | 988 SetStreamParameters(requested_subsequent_bitrate_, |
860 SetStreamParameters(test_stream_.requested_subsequent_bitrate, | 989 requested_subsequent_framerate_); |
861 test_stream_.requested_subsequent_framerate); | |
862 } | 990 } |
863 } else if (num_encoded_frames_ == num_frames_to_encode_) { | 991 } else if (num_encoded_frames_ == num_frames_to_encode_) { |
864 VerifyPerf(); | 992 VerifyPerf(); |
865 VerifyStreamProperties(); | 993 VerifyStreamProperties(); |
866 SetState(CS_FINISHED); | 994 SetState(CS_FINISHED); |
867 return false; | 995 return false; |
868 } | 996 } |
869 | 997 |
870 return true; | 998 return true; |
871 } | 999 } |
(...skipping 18 matching lines...) Expand all Loading... | |
890 num_frames_since_last_check_ = 0; | 1018 num_frames_since_last_check_ = 0; |
891 encoded_stream_size_since_last_check_ = 0; | 1019 encoded_stream_size_since_last_check_ = 0; |
892 | 1020 |
893 if (force_bitrate_) { | 1021 if (force_bitrate_) { |
894 EXPECT_NEAR(bitrate, | 1022 EXPECT_NEAR(bitrate, |
895 current_requested_bitrate_, | 1023 current_requested_bitrate_, |
896 kBitrateTolerance * current_requested_bitrate_); | 1024 kBitrateTolerance * current_requested_bitrate_); |
897 } | 1025 } |
898 } | 1026 } |
899 | 1027 |
1028 // Setup test stream data and delete temporary aligned files at the beginning | |
1029 // and end of unittest. We only need to setup once for all test cases. | |
1030 class VideoEncodeAcceleratorTestEnvironment : public ::testing::Environment { | |
1031 public: | |
1032 VideoEncodeAcceleratorTestEnvironment(base::FilePath::StringType* data) { | |
1033 test_stream_data = data; | |
1034 } | |
1035 | |
1036 virtual void SetUp() { | |
1037 ParseAndReadTestStreamData(*test_stream_data, &test_streams); | |
1038 } | |
1039 | |
1040 virtual void TearDown() { | |
1041 for (size_t i = 0; i < test_streams.size(); i++) { | |
1042 base::DeleteFile(test_streams[i]->aligned_in_file, false); | |
1043 } | |
1044 } | |
1045 | |
1046 ScopedVector<TestStream> test_streams; | |
1047 | |
1048 private: | |
1049 base::FilePath::StringType* test_stream_data; | |
1050 }; | |
1051 | |
900 // Test parameters: | 1052 // Test parameters: |
901 // - Number of concurrent encoders. | 1053 // - Number of concurrent encoders. |
902 // - If true, save output to file (provided an output filename was supplied). | 1054 // - If true, save output to file (provided an output filename was supplied). |
903 // - Force a keyframe every n frames. | 1055 // - Force a keyframe every n frames. |
904 // - Force bitrate; the actual required value is provided as a property | 1056 // - Force bitrate; the actual required value is provided as a property |
905 // of the input stream, because it depends on stream type/resolution/etc. | 1057 // of the input stream, because it depends on stream type/resolution/etc. |
906 // - If true, measure performance. | 1058 // - If true, measure performance. |
907 // - If true, switch bitrate mid-stream. | 1059 // - If true, switch bitrate mid-stream. |
908 // - If true, switch framerate mid-stream. | 1060 // - If true, switch framerate mid-stream. |
909 class VideoEncodeAcceleratorTest | 1061 class VideoEncodeAcceleratorTest |
910 : public ::testing::TestWithParam< | 1062 : public ::testing::TestWithParam< |
911 Tuple7<int, bool, int, bool, bool, bool, bool> > {}; | 1063 Tuple7<int, bool, int, bool, bool, bool, bool> > {}; |
912 | 1064 |
913 TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) { | 1065 TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) { |
914 const size_t num_concurrent_encoders = GetParam().a; | 1066 const size_t num_concurrent_encoders = GetParam().a; |
915 const bool save_to_file = GetParam().b; | 1067 const bool save_to_file = GetParam().b; |
916 const unsigned int keyframe_period = GetParam().c; | 1068 const unsigned int keyframe_period = GetParam().c; |
917 const bool force_bitrate = GetParam().d; | 1069 const bool force_bitrate = GetParam().d; |
918 const bool test_perf = GetParam().e; | 1070 const bool test_perf = GetParam().e; |
919 const bool mid_stream_bitrate_switch = GetParam().f; | 1071 const bool mid_stream_bitrate_switch = GetParam().f; |
920 const bool mid_stream_framerate_switch = GetParam().g; | 1072 const bool mid_stream_framerate_switch = GetParam().g; |
921 | 1073 |
922 // Initialize the test streams. | |
923 ScopedVector<TestStream> test_streams; | |
924 ParseAndReadTestStreamData(*g_test_stream_data, &test_streams); | |
925 UpdateTestStreamData( | |
926 mid_stream_bitrate_switch, mid_stream_framerate_switch, &test_streams); | |
927 | |
928 ScopedVector<ClientStateNotification<ClientState> > notes; | 1074 ScopedVector<ClientStateNotification<ClientState> > notes; |
929 ScopedVector<VEAClient> clients; | 1075 ScopedVector<VEAClient> clients; |
930 base::Thread encoder_thread("EncoderThread"); | 1076 base::Thread encoder_thread("EncoderThread"); |
931 ASSERT_TRUE(encoder_thread.Start()); | 1077 ASSERT_TRUE(encoder_thread.Start()); |
932 | 1078 |
933 // Create all encoders. | 1079 // Create all encoders. |
934 for (size_t i = 0; i < num_concurrent_encoders; i++) { | 1080 for (size_t i = 0; i < num_concurrent_encoders; i++) { |
935 size_t test_stream_index = i % test_streams.size(); | 1081 size_t test_stream_index = i % g_env->test_streams.size(); |
936 // Disregard save_to_file if we didn't get an output filename. | 1082 // Disregard save_to_file if we didn't get an output filename. |
937 bool encoder_save_to_file = | 1083 bool encoder_save_to_file = |
938 (save_to_file && | 1084 (save_to_file && |
939 !test_streams[test_stream_index]->out_filename.empty()); | 1085 !g_env->test_streams[test_stream_index]->out_filename.empty()); |
940 | 1086 |
941 notes.push_back(new ClientStateNotification<ClientState>()); | 1087 notes.push_back(new ClientStateNotification<ClientState>()); |
942 clients.push_back(new VEAClient(*test_streams[test_stream_index], | 1088 clients.push_back(new VEAClient(g_env->test_streams[test_stream_index], |
943 notes.back(), | 1089 notes.back(), |
944 encoder_save_to_file, | 1090 encoder_save_to_file, |
945 keyframe_period, | 1091 keyframe_period, |
946 force_bitrate, | 1092 force_bitrate, |
947 test_perf)); | 1093 test_perf, |
1094 mid_stream_bitrate_switch, | |
1095 mid_stream_framerate_switch)); | |
948 | 1096 |
949 encoder_thread.message_loop()->PostTask( | 1097 encoder_thread.message_loop()->PostTask( |
950 FROM_HERE, | 1098 FROM_HERE, |
951 base::Bind(&VEAClient::CreateEncoder, | 1099 base::Bind(&VEAClient::CreateEncoder, |
952 base::Unretained(clients.back()))); | 1100 base::Unretained(clients.back()))); |
953 } | 1101 } |
954 | 1102 |
955 // All encoders must pass through states in this order. | 1103 // All encoders must pass through states in this order. |
956 enum ClientState state_transitions[] = {CS_ENCODER_SET, CS_INITIALIZED, | 1104 enum ClientState state_transitions[] = {CS_ENCODER_SET, CS_INITIALIZED, |
957 CS_ENCODING, CS_FINISHED}; | 1105 CS_ENCODING, CS_FINISHED}; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1029 | 1177 |
1030 int main(int argc, char** argv) { | 1178 int main(int argc, char** argv) { |
1031 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. | 1179 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args. |
1032 base::CommandLine::Init(argc, argv); | 1180 base::CommandLine::Init(argc, argv); |
1033 | 1181 |
1034 base::ShadowingAtExitManager at_exit_manager; | 1182 base::ShadowingAtExitManager at_exit_manager; |
1035 scoped_ptr<base::FilePath::StringType> test_stream_data( | 1183 scoped_ptr<base::FilePath::StringType> test_stream_data( |
1036 new base::FilePath::StringType( | 1184 new base::FilePath::StringType( |
1037 media::GetTestDataFilePath(content::g_default_in_filename).value() + | 1185 media::GetTestDataFilePath(content::g_default_in_filename).value() + |
1038 content::g_default_in_parameters)); | 1186 content::g_default_in_parameters)); |
1039 content::g_test_stream_data = test_stream_data.get(); | 1187 |
1188 content::g_env = | |
Pawel Osciak
2014/09/17 09:58:28
Could you move this to l.1214 and test_stream_data
henryhsu
2014/09/17 10:42:23
Done.
| |
1189 reinterpret_cast<content::VideoEncodeAcceleratorTestEnvironment*>( | |
1190 testing::AddGlobalTestEnvironment( | |
1191 new content::VideoEncodeAcceleratorTestEnvironment( | |
1192 test_stream_data.get()))); | |
1040 | 1193 |
1041 // Needed to enable DVLOG through --vmodule. | 1194 // Needed to enable DVLOG through --vmodule. |
1042 logging::LoggingSettings settings; | 1195 logging::LoggingSettings settings; |
1043 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; | 1196 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; |
1044 CHECK(logging::InitLogging(settings)); | 1197 CHECK(logging::InitLogging(settings)); |
1045 | 1198 |
1046 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | 1199 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
1047 DCHECK(cmd_line); | 1200 DCHECK(cmd_line); |
1048 | 1201 |
1049 base::CommandLine::SwitchMap switches = cmd_line->GetSwitches(); | 1202 base::CommandLine::SwitchMap switches = cmd_line->GetSwitches(); |
1050 for (base::CommandLine::SwitchMap::const_iterator it = switches.begin(); | 1203 for (base::CommandLine::SwitchMap::const_iterator it = switches.begin(); |
1051 it != switches.end(); | 1204 it != switches.end(); |
1052 ++it) { | 1205 ++it) { |
1053 if (it->first == "test_stream_data") { | 1206 if (it->first == "test_stream_data") { |
1054 test_stream_data->assign(it->second.c_str()); | 1207 test_stream_data->assign(it->second.c_str()); |
1055 continue; | 1208 continue; |
1056 } | 1209 } |
1057 if (it->first == "v" || it->first == "vmodule") | 1210 if (it->first == "v" || it->first == "vmodule") |
1058 continue; | 1211 continue; |
1059 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1212 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
1060 } | 1213 } |
1061 | 1214 |
1062 return RUN_ALL_TESTS(); | 1215 return RUN_ALL_TESTS(); |
1063 } | 1216 } |
OLD | NEW |