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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 const double kDefaultSubsequentBitrateRatio = 2.0; | 45 const double kDefaultSubsequentBitrateRatio = 2.0; |
| 46 // Default initial framerate. | 46 // Default initial framerate. |
| 47 const uint32 kDefaultFramerate = 30; | 47 const uint32 kDefaultFramerate = 30; |
| 48 // Default ratio of requested_subsequent_framerate to initial_framerate | 48 // Default ratio of requested_subsequent_framerate to initial_framerate |
| 49 // (see test parameters below) if one is not provided. | 49 // (see test parameters below) if one is not provided. |
| 50 const double kDefaultSubsequentFramerateRatio = 0.1; | 50 const double kDefaultSubsequentFramerateRatio = 0.1; |
| 51 // Tolerance factor for how encoded bitrate can differ from requested bitrate. | 51 // Tolerance factor for how encoded bitrate can differ from requested bitrate. |
| 52 const double kBitrateTolerance = 0.1; | 52 const double kBitrateTolerance = 0.1; |
| 53 // Minimum required FPS throughput for the basic performance test. | 53 // Minimum required FPS throughput for the basic performance test. |
| 54 const uint32 kMinPerfFPS = 30; | 54 const uint32 kMinPerfFPS = 30; |
| 55 // Minimum (arbitrary) number of frames required to enforce bitrate requirements | |
| 56 // over. Streams shorter than this may be too short to realistically require | |
| 57 // an encoder to be able to converge to the requested bitrate over. | |
| 58 // The input stream will be looped as many times as needed in bitrate tests | |
| 59 // to reach at least this number of frames before calculating final bitrate. | |
| 60 const unsigned int kMinFramesForBitrateTests = 300; | |
| 55 | 61 |
| 56 // The syntax of multiple test streams is: | 62 // The syntax of multiple test streams is: |
| 57 // test-stream1;test-stream2;test-stream3 | 63 // test-stream1;test-stream2;test-stream3 |
| 58 // The syntax of each test stream is: | 64 // The syntax of each test stream is: |
| 59 // "in_filename:width:height:out_filename:requested_bitrate:requested_framerate | 65 // "in_filename:width:height:out_filename:requested_bitrate:requested_framerate |
| 60 // :requested_subsequent_bitrate:requested_subsequent_framerate" | 66 // :requested_subsequent_bitrate:requested_subsequent_framerate" |
| 61 // - |in_filename| must be an I420 (YUV planar) raw stream | 67 // - |in_filename| must be an I420 (YUV planar) raw stream |
| 62 // (see http://www.fourcc.org/yuv.php#IYUV). | 68 // (see http://www.fourcc.org/yuv.php#IYUV). |
| 63 // - |width| and |height| are in pixels. | 69 // - |width| and |height| are in pixels. |
| 64 // - |profile| to encode into (values of media::VideoCodecProfile). | 70 // - |profile| to encode into (values of media::VideoCodecProfile). |
| 65 // - |out_filename| filename to save the encoded stream to (optional). | 71 // - |out_filename| filename to save the encoded stream to (optional). |
| 66 // Output stream is saved for the simple encode test only. | 72 // Output stream is saved for the simple encode test only. |
| 67 // Further parameters are optional (need to provide preceding positional | 73 // Further parameters are optional (need to provide preceding positional |
| 68 // parameters if a specific subsequent parameter is required): | 74 // parameters if a specific subsequent parameter is required): |
| 69 // - |requested_bitrate| requested bitrate in bits per second. | 75 // - |requested_bitrate| requested bitrate in bits per second. |
| 70 // - |requested_framerate| requested initial framerate. | 76 // - |requested_framerate| requested initial framerate. |
| 71 // - |requested_subsequent_bitrate| bitrate to switch to in the middle of the | 77 // - |requested_subsequent_bitrate| bitrate to switch to in the middle of the |
| 72 // stream. | 78 // stream. |
| 73 // - |requested_subsequent_framerate| framerate to switch to in the middle | 79 // - |requested_subsequent_framerate| framerate to switch to in the middle |
| 74 // of the stream. | 80 // of the stream. |
| 75 // Bitrate is only forced for tests that test bitrate. | 81 // Bitrate is only forced for tests that test bitrate. |
| 76 const char* g_default_in_filename = "sync_192p20_frames.yuv"; | 82 const char* g_default_in_filename = "bear_192p40_frames.yuv"; |
|
Ami GONE FROM CHROMIUM
2014/05/16 18:00:50
why this change?
Pawel Osciak
2014/05/16 22:49:15
Sync has a lot of black background and not as much
| |
| 77 const char* g_default_in_parameters = ":320:192:1:out.h264:200000"; | 83 const char* g_default_in_parameters = ":320:192:1:out.h264:200000"; |
| 78 base::FilePath::StringType* g_test_stream_data; | 84 base::FilePath::StringType* g_test_stream_data; |
| 79 | 85 |
| 80 struct TestStream { | 86 struct TestStream { |
| 81 TestStream() | 87 TestStream() |
| 82 : requested_bitrate(0), | 88 : requested_bitrate(0), |
| 83 requested_framerate(0), | 89 requested_framerate(0), |
| 84 requested_subsequent_bitrate(0), | 90 requested_subsequent_bitrate(0), |
| 85 requested_subsequent_framerate(0) {} | 91 requested_subsequent_framerate(0) {} |
| 86 ~TestStream() {} | 92 ~TestStream() {} |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 191 if (test_stream->requested_subsequent_framerate == 0) | 197 if (test_stream->requested_subsequent_framerate == 0) |
| 192 test_stream->requested_subsequent_framerate = 1; | 198 test_stream->requested_subsequent_framerate = 1; |
| 193 } | 199 } |
| 194 } | 200 } |
| 195 | 201 |
| 196 enum ClientState { | 202 enum ClientState { |
| 197 CS_CREATED, | 203 CS_CREATED, |
| 198 CS_ENCODER_SET, | 204 CS_ENCODER_SET, |
| 199 CS_INITIALIZED, | 205 CS_INITIALIZED, |
| 200 CS_ENCODING, | 206 CS_ENCODING, |
| 201 CS_FINISHING, | |
| 202 CS_FINISHED, | 207 CS_FINISHED, |
| 203 CS_ERROR, | 208 CS_ERROR, |
| 204 }; | 209 }; |
| 205 | 210 |
| 206 // Performs basic, codec-specific sanity checks on the stream buffers passed | 211 // Performs basic, codec-specific sanity checks on the stream buffers passed |
| 207 // to ProcessStreamBuffer(): whether we've seen keyframes before non-keyframes, | 212 // to ProcessStreamBuffer(): whether we've seen keyframes before non-keyframes, |
| 208 // correct sequences of H.264 NALUs (SPS before PPS and before slices), etc. | 213 // correct sequences of H.264 NALUs (SPS before PPS and before slices), etc. |
| 209 // Calls given FrameFoundCallback when a complete frame is found while | 214 // Calls given FrameFoundCallback when a complete frame is found while |
| 210 // processing. | 215 // processing. |
| 211 class StreamValidator { | 216 class StreamValidator { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 371 // Called when encoder is done with a VideoFrame. | 376 // Called when encoder is done with a VideoFrame. |
| 372 void InputNoLongerNeededCallback(int32 input_id); | 377 void InputNoLongerNeededCallback(int32 input_id); |
| 373 | 378 |
| 374 // Ensure encoder has at least as many inputs as it asked for | 379 // Ensure encoder has at least as many inputs as it asked for |
| 375 // via RequireBitstreamBuffers(). | 380 // via RequireBitstreamBuffers(). |
| 376 void FeedEncoderWithInputs(); | 381 void FeedEncoderWithInputs(); |
| 377 | 382 |
| 378 // Provide the encoder with a new output buffer. | 383 // Provide the encoder with a new output buffer. |
| 379 void FeedEncoderWithOutput(base::SharedMemory* shm); | 384 void FeedEncoderWithOutput(base::SharedMemory* shm); |
| 380 | 385 |
| 381 // Feed the encoder with num_required_input_buffers_ of black frames to force | |
| 382 // it to encode and return all inputs that came before this, effectively | |
| 383 // flushing it. | |
| 384 void FlushEncoder(); | |
| 385 | |
| 386 // Called on finding a complete frame (with |keyframe| set to true for | 386 // Called on finding a complete frame (with |keyframe| set to true for |
| 387 // keyframes) in the stream, to perform codec-independent, per-frame checks | 387 // keyframes) in the stream, to perform codec-independent, per-frame checks |
| 388 // and accounting. Returns false once we have collected all frames we needed. | 388 // and accounting. Returns false once we have collected all frames we needed. |
| 389 bool HandleEncodedFrame(bool keyframe); | 389 bool HandleEncodedFrame(bool keyframe); |
| 390 | 390 |
| 391 // Verify that stream bitrate has been close to current_requested_bitrate_, | 391 // Verify that stream bitrate has been close to current_requested_bitrate_, |
| 392 // assuming current_framerate_ since the last time VerifyStreamProperties() | 392 // assuming current_framerate_ since the last time VerifyStreamProperties() |
| 393 // was called. Fail the test if |force_bitrate_| is true and the bitrate | 393 // was called. Fail the test if |force_bitrate_| is true and the bitrate |
| 394 // is not within kBitrateTolerance. | 394 // is not within kBitrateTolerance. |
| 395 void VerifyStreamProperties(); | 395 void VerifyStreamProperties(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 415 int32 next_input_id_; | 415 int32 next_input_id_; |
| 416 | 416 |
| 417 // Ids for output BitstreamBuffers. | 417 // Ids for output BitstreamBuffers. |
| 418 typedef std::map<int32, base::SharedMemory*> IdToSHM; | 418 typedef std::map<int32, base::SharedMemory*> IdToSHM; |
| 419 ScopedVector<base::SharedMemory> output_shms_; | 419 ScopedVector<base::SharedMemory> output_shms_; |
| 420 IdToSHM output_buffers_at_client_; | 420 IdToSHM output_buffers_at_client_; |
| 421 int32 next_output_buffer_id_; | 421 int32 next_output_buffer_id_; |
| 422 | 422 |
| 423 // Current offset into input stream. | 423 // Current offset into input stream. |
| 424 off_t pos_in_input_stream_; | 424 off_t pos_in_input_stream_; |
| 425 // Calculated from input_coded_size_, in bytes. | 425 // Byte size of an input frame. |
| 426 size_t input_buffer_size_; | 426 size_t input_buffer_size_; |
| 427 gfx::Size input_coded_size_; | 427 gfx::Size input_coded_size_; |
| 428 // Requested by encoder. | 428 // Requested by encoder. |
| 429 unsigned int num_required_input_buffers_; | 429 unsigned int num_required_input_buffers_; |
| 430 size_t output_buffer_size_; | 430 size_t output_buffer_size_; |
| 431 | 431 |
| 432 // Precalculated number of frames in the stream. | 432 // Precalculated number of frames in the stream. |
| 433 unsigned int num_frames_in_stream_; | 433 unsigned int num_frames_in_stream_; |
| 434 | 434 |
| 435 // Number of frames to encode. This may differ from num_frames_in_stream_ if | |
| 436 // we need more frames for bitrate tests. | |
| 437 unsigned int num_frames_to_encode_; | |
| 438 | |
| 435 // Number of encoded frames we've got from the encoder thus far. | 439 // Number of encoded frames we've got from the encoder thus far. |
| 436 unsigned int num_encoded_frames_; | 440 unsigned int num_encoded_frames_; |
| 437 | 441 |
| 438 // Frames since last bitrate verification. | 442 // Frames since last bitrate verification. |
| 439 unsigned int num_frames_since_last_check_; | 443 unsigned int num_frames_since_last_check_; |
| 440 | 444 |
| 441 // True if received a keyframe while processing current bitstream buffer. | 445 // True if received a keyframe while processing current bitstream buffer. |
| 442 bool seen_keyframe_in_this_buffer_; | 446 bool seen_keyframe_in_this_buffer_; |
| 443 | 447 |
| 444 // True if we are to save the encoded stream to a file. | 448 // True if we are to save the encoded stream to a file. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 461 | 465 |
| 462 // Byte size of the encoded stream (for bitrate calculation) since last | 466 // Byte size of the encoded stream (for bitrate calculation) since last |
| 463 // time we checked bitrate. | 467 // time we checked bitrate. |
| 464 size_t encoded_stream_size_since_last_check_; | 468 size_t encoded_stream_size_since_last_check_; |
| 465 | 469 |
| 466 // If true, verify performance at the end of the test. | 470 // If true, verify performance at the end of the test. |
| 467 bool test_perf_; | 471 bool test_perf_; |
| 468 | 472 |
| 469 scoped_ptr<StreamValidator> validator_; | 473 scoped_ptr<StreamValidator> validator_; |
| 470 | 474 |
| 471 // The time when the encoder has initialized. | 475 // The time when the encoding started. |
| 472 base::TimeTicks encoder_initialized_time_; | 476 base::TimeTicks encode_start_time_; |
| 473 | 477 |
| 474 // The time when the last encoded frame is ready. | 478 // The time when the last encoded frame is ready. |
| 475 base::TimeTicks last_frame_ready_time_; | 479 base::TimeTicks last_frame_ready_time_; |
| 476 | 480 |
| 477 // All methods of this class should be run on the same thread. | 481 // All methods of this class should be run on the same thread. |
| 478 base::ThreadChecker thread_checker_; | 482 base::ThreadChecker thread_checker_; |
| 479 }; | 483 }; |
| 480 | 484 |
| 481 VEAClient::VEAClient(const TestStream& test_stream, | 485 VEAClient::VEAClient(const TestStream& test_stream, |
| 482 ClientStateNotification<ClientState>* note, | 486 ClientStateNotification<ClientState>* note, |
| 483 bool save_to_file, | 487 bool save_to_file, |
| 484 unsigned int keyframe_period, | 488 unsigned int keyframe_period, |
| 485 bool force_bitrate, | 489 bool force_bitrate, |
| 486 bool test_perf) | 490 bool test_perf) |
| 487 : state_(CS_CREATED), | 491 : state_(CS_CREATED), |
| 488 test_stream_(test_stream), | 492 test_stream_(test_stream), |
| 489 note_(note), | 493 note_(note), |
| 490 next_input_id_(1), | 494 next_input_id_(1), |
| 491 next_output_buffer_id_(0), | 495 next_output_buffer_id_(0), |
| 492 pos_in_input_stream_(0), | 496 pos_in_input_stream_(0), |
| 493 input_buffer_size_(0), | 497 input_buffer_size_(0), |
| 494 num_required_input_buffers_(0), | 498 num_required_input_buffers_(0), |
| 495 output_buffer_size_(0), | 499 output_buffer_size_(0), |
| 496 num_frames_in_stream_(0), | 500 num_frames_in_stream_(0), |
| 501 num_frames_to_encode_(0), | |
| 497 num_encoded_frames_(0), | 502 num_encoded_frames_(0), |
| 498 num_frames_since_last_check_(0), | 503 num_frames_since_last_check_(0), |
| 499 seen_keyframe_in_this_buffer_(false), | 504 seen_keyframe_in_this_buffer_(false), |
| 500 save_to_file_(save_to_file), | 505 save_to_file_(save_to_file), |
| 501 keyframe_period_(keyframe_period), | 506 keyframe_period_(keyframe_period), |
| 502 keyframe_requested_at_(kMaxFrameNum), | 507 keyframe_requested_at_(kMaxFrameNum), |
| 503 force_bitrate_(force_bitrate), | 508 force_bitrate_(force_bitrate), |
| 504 current_requested_bitrate_(0), | 509 current_requested_bitrate_(0), |
| 505 current_framerate_(0), | 510 current_framerate_(0), |
| 506 encoded_stream_size_since_last_check_(0), | 511 encoded_stream_size_since_last_check_(0), |
| 507 test_perf_(test_perf) { | 512 test_perf_(test_perf) { |
| 508 if (keyframe_period_) | 513 if (keyframe_period_) |
| 509 CHECK_LT(kMaxKeyframeDelay, keyframe_period_); | 514 CHECK_LT(kMaxKeyframeDelay, keyframe_period_); |
| 510 | 515 |
| 511 validator_ = StreamValidator::Create( | 516 validator_ = StreamValidator::Create( |
| 512 test_stream_.requested_profile, | 517 test_stream_.requested_profile, |
| 513 base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this))); | 518 base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this))); |
| 514 | 519 |
| 515 CHECK(validator_.get()); | 520 CHECK(validator_.get()); |
| 516 | 521 |
| 517 if (save_to_file_) { | 522 if (save_to_file_) { |
| 518 CHECK(!test_stream_.out_filename.empty()); | 523 CHECK(!test_stream_.out_filename.empty()); |
| 519 base::FilePath out_filename(test_stream_.out_filename); | 524 base::FilePath out_filename(test_stream_.out_filename); |
| 520 // This creates or truncates out_filename. | 525 // This creates or truncates out_filename. |
| 521 // Without it, AppendToFile() will not work. | 526 // Without it, AppendToFile() will not work. |
| 522 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); | 527 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0)); |
| 523 } | 528 } |
| 524 | 529 |
| 530 input_buffer_size_ = | |
| 531 media::VideoFrame::AllocationSize(kInputFormat, test_stream.size); | |
| 532 CHECK_GT(input_buffer_size_, 0UL); | |
| 533 | |
| 534 // Calculate the number of frames in the input stream by dividing its length | |
| 535 // in bytes by frame size in bytes. | |
| 536 CHECK_EQ(test_stream_.input_file.length() % input_buffer_size_, 0) | |
| 537 << "Stream byte size is not a product of calculated frame byte size"; | |
| 538 num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_; | |
| 539 CHECK_GT(num_frames_in_stream_, 0UL); | |
| 540 CHECK_LE(num_frames_in_stream_, kMaxFrameNum); | |
| 541 | |
| 542 // We may need to loop over the stream more than once if more frames than | |
| 543 // provided is required for bitrate tests. | |
| 544 if (force_bitrate_ && num_frames_in_stream_ < kMinFramesForBitrateTests) { | |
| 545 DVLOG(1) << "Stream too short for bitrate test (" << num_frames_in_stream_ | |
| 546 << " frames), will loop it to reach " << kMinFramesForBitrateTests | |
| 547 << " frames"; | |
| 548 num_frames_to_encode_ = kMinFramesForBitrateTests; | |
| 549 } else { | |
| 550 num_frames_to_encode_ = num_frames_in_stream_; | |
| 551 } | |
| 552 | |
| 525 thread_checker_.DetachFromThread(); | 553 thread_checker_.DetachFromThread(); |
| 526 } | 554 } |
| 527 | 555 |
| 528 VEAClient::~VEAClient() { CHECK(!has_encoder()); } | 556 VEAClient::~VEAClient() { CHECK(!has_encoder()); } |
| 529 | 557 |
| 530 void VEAClient::CreateEncoder() { | 558 void VEAClient::CreateEncoder() { |
| 531 DCHECK(thread_checker_.CalledOnValidThread()); | 559 DCHECK(thread_checker_.CalledOnValidThread()); |
| 532 CHECK(!has_encoder()); | 560 CHECK(!has_encoder()); |
| 533 | 561 |
| 534 scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); | 562 scoped_ptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); |
| 535 encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); | 563 encoder_.reset(new V4L2VideoEncodeAccelerator(device.Pass())); |
| 536 SetState(CS_ENCODER_SET); | 564 SetState(CS_ENCODER_SET); |
| 537 | 565 |
| 538 DVLOG(1) << "Profile: " << test_stream_.requested_profile | 566 DVLOG(1) << "Profile: " << test_stream_.requested_profile |
| 539 << ", initial bitrate: " << test_stream_.requested_bitrate; | 567 << ", initial bitrate: " << test_stream_.requested_bitrate; |
| 540 if (!encoder_->Initialize(kInputFormat, | 568 if (!encoder_->Initialize(kInputFormat, |
| 541 test_stream_.size, | 569 test_stream_.size, |
| 542 test_stream_.requested_profile, | 570 test_stream_.requested_profile, |
| 543 test_stream_.requested_bitrate, | 571 test_stream_.requested_bitrate, |
| 544 this)) { | 572 this)) { |
| 545 DLOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed"; | 573 DLOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed"; |
| 546 SetState(CS_ERROR); | 574 SetState(CS_ERROR); |
| 547 return; | 575 return; |
| 548 } | 576 } |
| 549 | 577 |
| 550 SetStreamParameters(test_stream_.requested_bitrate, | 578 SetStreamParameters(test_stream_.requested_bitrate, |
| 551 test_stream_.requested_framerate); | 579 test_stream_.requested_framerate); |
| 552 SetState(CS_INITIALIZED); | 580 SetState(CS_INITIALIZED); |
| 553 encoder_initialized_time_ = base::TimeTicks::Now(); | |
| 554 } | 581 } |
| 555 | 582 |
| 556 void VEAClient::DestroyEncoder() { | 583 void VEAClient::DestroyEncoder() { |
| 557 DCHECK(thread_checker_.CalledOnValidThread()); | 584 DCHECK(thread_checker_.CalledOnValidThread()); |
| 558 if (!has_encoder()) | 585 if (!has_encoder()) |
| 559 return; | 586 return; |
| 560 encoder_.release()->Destroy(); | 587 encoder_.release()->Destroy(); |
| 561 } | 588 } |
| 562 | 589 |
| 563 double VEAClient::frames_per_second() { | 590 double VEAClient::frames_per_second() { |
| 564 base::TimeDelta duration = last_frame_ready_time_ - encoder_initialized_time_; | 591 base::TimeDelta duration = last_frame_ready_time_ - encode_start_time_; |
| 565 return num_encoded_frames_ / duration.InSecondsF(); | 592 return num_encoded_frames_ / duration.InSecondsF(); |
| 566 } | 593 } |
| 567 | 594 |
| 568 void VEAClient::RequireBitstreamBuffers(unsigned int input_count, | 595 void VEAClient::RequireBitstreamBuffers(unsigned int input_count, |
| 569 const gfx::Size& input_coded_size, | 596 const gfx::Size& input_coded_size, |
| 570 size_t output_size) { | 597 size_t output_size) { |
| 571 DCHECK(thread_checker_.CalledOnValidThread()); | 598 DCHECK(thread_checker_.CalledOnValidThread()); |
| 572 ASSERT_EQ(state_, CS_INITIALIZED); | 599 ASSERT_EQ(state_, CS_INITIALIZED); |
| 573 SetState(CS_ENCODING); | 600 SetState(CS_ENCODING); |
| 574 | 601 |
| 575 // TODO(posciak): For now we only support input streams that meet encoder | 602 // TODO(posciak): For now we only support input streams that meet encoder |
| 576 // size requirements exactly (i.e. coded size == visible size). | 603 // size requirements exactly (i.e. coded size == visible size), so that we |
| 604 // can simply mmap the stream file and feed the encoder directly with chunks | |
| 605 // of that, instead of memcpying from mmapped file into a separate set of | |
| 606 // input buffers that would meet the coded size and alignment requirements. | |
| 607 // If/when this is changed, the ARM-specific alignment check below should be | |
| 608 // redone as well. | |
| 577 input_coded_size_ = input_coded_size; | 609 input_coded_size_ = input_coded_size; |
| 578 ASSERT_EQ(input_coded_size_, test_stream_.size); | 610 ASSERT_EQ(input_coded_size_, test_stream_.size); |
| 579 | 611 #if defined(ARCH_CPU_ARMEL) |
| 580 input_buffer_size_ = media::VideoFrame::AllocationSize(kInputFormat, | |
| 581 input_coded_size_); | |
| 582 CHECK_GT(input_buffer_size_, 0UL); | |
| 583 | |
| 584 // ARM performs CPU cache management with CPU cache line granularity. We thus | 612 // ARM performs CPU cache management with CPU cache line granularity. We thus |
| 585 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned). | 613 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned). |
| 586 // Otherwise newer kernels will refuse to accept them, and on older kernels | 614 // Otherwise newer kernels will refuse to accept them, and on older kernels |
| 587 // we'll be treating ourselves to random corruption. | 615 // we'll be treating ourselves to random corruption. |
| 588 // Since we are just mmapping and passing chunks of the input file, to ensure | 616 // Since we are just mmapping and passing chunks of the input file, to ensure |
| 589 // alignment, if the starting virtual addresses of the frames in it were not | 617 // alignment, if the starting virtual addresses of the frames in it were not |
| 590 // 64 byte-aligned, we'd have to use a separate set of input buffers and copy | 618 // 64 byte-aligned, we'd have to use a separate set of input buffers and copy |
| 591 // the frames into them before sending to the encoder. It would have been an | 619 // the frames into them before sending to the encoder. It would have been an |
| 592 // overkill here though, because, for now at least, we only test resolutions | 620 // overkill here though, because, for now at least, we only test resolutions |
| 593 // that result in proper alignment, and it would have also interfered with | 621 // that result in proper alignment, and it would have also interfered with |
| 594 // performance testing. So just assert that the frame size is a multiple of | 622 // performance testing. So just assert that the frame size is a multiple of |
| 595 // 64 bytes. This ensures all frames start at 64-byte boundary, because | 623 // 64 bytes. This ensures all frames start at 64-byte boundary, because |
| 596 // MemoryMappedFile should be mmapp()ed at virtual page start as well. | 624 // MemoryMappedFile should be mmapp()ed at virtual page start as well. |
| 597 ASSERT_EQ(input_buffer_size_ & 63, 0) | 625 ASSERT_EQ(input_buffer_size_ & 63, 0) |
| 598 << "Frame size has to be a multiple of 64 bytes"; | 626 << "Frame size has to be a multiple of 64 bytes"; |
| 599 ASSERT_EQ(reinterpret_cast<off_t>(test_stream_.input_file.data()) & 63, 0) | 627 ASSERT_EQ(reinterpret_cast<off_t>(test_stream_.input_file.data()) & 63, 0) |
| 600 << "Mapped file should be mapped at a 64 byte boundary"; | 628 << "Mapped file should be mapped at a 64 byte boundary"; |
| 629 #endif | |
| 601 | 630 |
| 602 num_required_input_buffers_ = input_count; | 631 num_required_input_buffers_ = input_count; |
| 603 ASSERT_GT(num_required_input_buffers_, 0UL); | 632 ASSERT_GT(num_required_input_buffers_, 0UL); |
| 604 | 633 |
| 605 num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_; | |
| 606 CHECK_GT(num_frames_in_stream_, 0UL); | |
| 607 CHECK_LE(num_frames_in_stream_, kMaxFrameNum); | |
| 608 CHECK_EQ(num_frames_in_stream_ * input_buffer_size_, | |
| 609 test_stream_.input_file.length()); | |
| 610 | |
| 611 output_buffer_size_ = output_size; | 634 output_buffer_size_ = output_size; |
| 612 ASSERT_GT(output_buffer_size_, 0UL); | 635 ASSERT_GT(output_buffer_size_, 0UL); |
| 613 | 636 |
| 614 for (unsigned int i = 0; i < kNumOutputBuffers; ++i) { | 637 for (unsigned int i = 0; i < kNumOutputBuffers; ++i) { |
| 615 base::SharedMemory* shm = new base::SharedMemory(); | 638 base::SharedMemory* shm = new base::SharedMemory(); |
| 616 CHECK(shm->CreateAndMapAnonymous(output_buffer_size_)); | 639 CHECK(shm->CreateAndMapAnonymous(output_buffer_size_)); |
| 617 output_shms_.push_back(shm); | 640 output_shms_.push_back(shm); |
| 618 FeedEncoderWithOutput(shm); | 641 FeedEncoderWithOutput(shm); |
| 619 } | 642 } |
| 620 | 643 |
| 644 encode_start_time_ = base::TimeTicks::Now(); | |
| 621 FeedEncoderWithInputs(); | 645 FeedEncoderWithInputs(); |
| 622 } | 646 } |
| 623 | 647 |
| 624 void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id, | 648 void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id, |
| 625 size_t payload_size, | 649 size_t payload_size, |
| 626 bool key_frame) { | 650 bool key_frame) { |
| 627 DCHECK(thread_checker_.CalledOnValidThread()); | 651 DCHECK(thread_checker_.CalledOnValidThread()); |
| 628 ASSERT_LE(payload_size, output_buffer_size_); | 652 ASSERT_LE(payload_size, output_buffer_size_); |
| 629 | 653 |
| 630 IdToSHM::iterator it = output_buffers_at_client_.find(bitstream_buffer_id); | 654 IdToSHM::iterator it = output_buffers_at_client_.find(bitstream_buffer_id); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 return; | 748 return; |
| 725 | 749 |
| 726 if (state_ != CS_ENCODING) | 750 if (state_ != CS_ENCODING) |
| 727 return; | 751 return; |
| 728 | 752 |
| 729 while (inputs_at_client_.size() < | 753 while (inputs_at_client_.size() < |
| 730 num_required_input_buffers_ + kNumExtraInputFrames) { | 754 num_required_input_buffers_ + kNumExtraInputFrames) { |
| 731 size_t bytes_left = test_stream_.input_file.length() - pos_in_input_stream_; | 755 size_t bytes_left = test_stream_.input_file.length() - pos_in_input_stream_; |
| 732 if (bytes_left < input_buffer_size_) { | 756 if (bytes_left < input_buffer_size_) { |
| 733 DCHECK_EQ(bytes_left, 0UL); | 757 DCHECK_EQ(bytes_left, 0UL); |
| 734 FlushEncoder(); | 758 // Rewind if at the end of stream and we are still encoding. |
| 735 return; | 759 // This is to flush the encoder with additional frames from the beginning |
| 760 // of the stream, or if the stream is shorter that the number of frames | |
| 761 // we require for bitrate tests. | |
| 762 pos_in_input_stream_ = 0; | |
| 763 continue; | |
| 736 } | 764 } |
| 737 | 765 |
| 738 bool force_keyframe = false; | 766 bool force_keyframe = false; |
| 739 if (keyframe_period_ && next_input_id_ % keyframe_period_ == 0) { | 767 if (keyframe_period_ && next_input_id_ % keyframe_period_ == 0) { |
| 740 keyframe_requested_at_ = next_input_id_; | 768 keyframe_requested_at_ = next_input_id_; |
| 741 force_keyframe = true; | 769 force_keyframe = true; |
| 742 } | 770 } |
| 743 | 771 |
| 744 scoped_refptr<media::VideoFrame> video_frame = | 772 scoped_refptr<media::VideoFrame> video_frame = |
| 745 PrepareInputFrame(pos_in_input_stream_); | 773 PrepareInputFrame(pos_in_input_stream_); |
| 746 pos_in_input_stream_ += input_buffer_size_; | 774 pos_in_input_stream_ += input_buffer_size_; |
| 747 | 775 |
| 748 encoder_->Encode(video_frame, force_keyframe); | 776 encoder_->Encode(video_frame, force_keyframe); |
| 749 } | 777 } |
| 750 } | 778 } |
| 751 | 779 |
| 752 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { | 780 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { |
| 753 if (!has_encoder()) | 781 if (!has_encoder()) |
| 754 return; | 782 return; |
| 755 | 783 |
| 756 if (state_ != CS_ENCODING && state_ != CS_FINISHING) | 784 if (state_ != CS_ENCODING) |
| 757 return; | 785 return; |
| 758 | 786 |
| 759 base::SharedMemoryHandle dup_handle; | 787 base::SharedMemoryHandle dup_handle; |
| 760 CHECK(shm->ShareToProcess(base::Process::Current().handle(), &dup_handle)); | 788 CHECK(shm->ShareToProcess(base::Process::Current().handle(), &dup_handle)); |
| 761 | 789 |
| 762 media::BitstreamBuffer bitstream_buffer( | 790 media::BitstreamBuffer bitstream_buffer( |
| 763 next_output_buffer_id_++, dup_handle, output_buffer_size_); | 791 next_output_buffer_id_++, dup_handle, output_buffer_size_); |
| 764 CHECK(output_buffers_at_client_.insert(std::make_pair(bitstream_buffer.id(), | 792 CHECK(output_buffers_at_client_.insert(std::make_pair(bitstream_buffer.id(), |
| 765 shm)).second); | 793 shm)).second); |
| 766 encoder_->UseOutputBitstreamBuffer(bitstream_buffer); | 794 encoder_->UseOutputBitstreamBuffer(bitstream_buffer); |
| 767 } | 795 } |
| 768 | 796 |
| 769 void VEAClient::FlushEncoder() { | |
| 770 ASSERT_EQ(state_, CS_ENCODING); | |
| 771 SetState(CS_FINISHING); | |
| 772 | |
| 773 // Feed the encoder with an additional set of num_required_input_buffers_ | |
| 774 // to flush it, using the first frame in the input stream. The resulting | |
| 775 // encoded frames will be ignored. | |
| 776 for (unsigned int i = 0; i < num_required_input_buffers_; ++i) { | |
| 777 scoped_refptr<media::VideoFrame> frame = PrepareInputFrame(0); | |
| 778 encoder_->Encode(frame, false); | |
| 779 } | |
| 780 } | |
| 781 | |
| 782 bool VEAClient::HandleEncodedFrame(bool keyframe) { | 797 bool VEAClient::HandleEncodedFrame(bool keyframe) { |
| 783 // This would be a bug in the test, which should not ignore false | 798 // This would be a bug in the test, which should not ignore false |
| 784 // return value from this method. | 799 // return value from this method. |
| 785 CHECK_LE(num_encoded_frames_, num_frames_in_stream_); | 800 CHECK_LE(num_encoded_frames_, num_frames_to_encode_); |
| 786 | 801 |
| 787 ++num_encoded_frames_; | 802 ++num_encoded_frames_; |
| 788 ++num_frames_since_last_check_; | 803 ++num_frames_since_last_check_; |
| 789 | 804 |
| 790 last_frame_ready_time_ = base::TimeTicks::Now(); | 805 last_frame_ready_time_ = base::TimeTicks::Now(); |
| 791 if (keyframe) { | 806 if (keyframe) { |
| 792 // Got keyframe, reset keyframe detection regardless of whether we | 807 // Got keyframe, reset keyframe detection regardless of whether we |
| 793 // got a frame in time or not. | 808 // got a frame in time or not. |
| 794 keyframe_requested_at_ = kMaxFrameNum; | 809 keyframe_requested_at_ = kMaxFrameNum; |
| 795 seen_keyframe_in_this_buffer_ = true; | 810 seen_keyframe_in_this_buffer_ = true; |
| 796 } | 811 } |
| 797 | 812 |
| 798 // Because the keyframe behavior requirements are loose, we give | 813 // Because the keyframe behavior requirements are loose, we give |
| 799 // the encoder more freedom here. It could either deliver a keyframe | 814 // the encoder more freedom here. It could either deliver a keyframe |
| 800 // immediately after we requested it, which could be for a frame number | 815 // immediately after we requested it, which could be for a frame number |
| 801 // before the one we requested it for (if the keyframe request | 816 // before the one we requested it for (if the keyframe request |
| 802 // is asynchronous, i.e. not bound to any concrete frame, and because | 817 // is asynchronous, i.e. not bound to any concrete frame, and because |
| 803 // the pipeline can be deeper than one frame), at that frame, or after. | 818 // the pipeline can be deeper than one frame), at that frame, or after. |
| 804 // So the only constraints we put here is that we get a keyframe not | 819 // So the only constraints we put here is that we get a keyframe not |
| 805 // earlier than we requested one (in time), and not later than | 820 // earlier than we requested one (in time), and not later than |
| 806 // kMaxKeyframeDelay frames after the frame, for which we requested | 821 // kMaxKeyframeDelay frames after the frame, for which we requested |
| 807 // it, comes back encoded. | 822 // it, comes back encoded. |
| 808 EXPECT_LE(num_encoded_frames_, keyframe_requested_at_ + kMaxKeyframeDelay); | 823 EXPECT_LE(num_encoded_frames_, keyframe_requested_at_ + kMaxKeyframeDelay); |
| 809 | 824 |
| 810 if (num_encoded_frames_ == num_frames_in_stream_ / 2) { | 825 if (num_encoded_frames_ == num_frames_to_encode_ / 2) { |
| 811 VerifyStreamProperties(); | 826 VerifyStreamProperties(); |
| 812 if (test_stream_.requested_subsequent_bitrate != | 827 if (test_stream_.requested_subsequent_bitrate != |
| 813 current_requested_bitrate_ || | 828 current_requested_bitrate_ || |
| 814 test_stream_.requested_subsequent_framerate != current_framerate_) { | 829 test_stream_.requested_subsequent_framerate != current_framerate_) { |
| 815 SetStreamParameters(test_stream_.requested_subsequent_bitrate, | 830 SetStreamParameters(test_stream_.requested_subsequent_bitrate, |
| 816 test_stream_.requested_subsequent_framerate); | 831 test_stream_.requested_subsequent_framerate); |
| 817 } | 832 } |
| 818 } else if (num_encoded_frames_ == num_frames_in_stream_) { | 833 } else if (num_encoded_frames_ == num_frames_to_encode_) { |
| 819 VerifyPerf(); | 834 VerifyPerf(); |
| 820 VerifyStreamProperties(); | 835 VerifyStreamProperties(); |
| 821 SetState(CS_FINISHED); | 836 SetState(CS_FINISHED); |
| 822 return false; | 837 return false; |
| 823 } | 838 } |
| 824 | 839 |
| 825 return true; | 840 return true; |
| 826 } | 841 } |
| 827 | 842 |
| 828 void VEAClient::VerifyPerf() { | 843 void VEAClient::VerifyPerf() { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 911 base::Bind(&VEAClient::CreateEncoder, | 926 base::Bind(&VEAClient::CreateEncoder, |
| 912 base::Unretained(clients.back()))); | 927 base::Unretained(clients.back()))); |
| 913 encoder_threads.push_back(encoder_thread); | 928 encoder_threads.push_back(encoder_thread); |
| 914 } | 929 } |
| 915 | 930 |
| 916 // Wait all the encoders to finish. | 931 // Wait all the encoders to finish. |
| 917 for (int i = 0; i < num_concurrent_encoders; i++) { | 932 for (int i = 0; i < num_concurrent_encoders; i++) { |
| 918 ASSERT_EQ(notes[i]->Wait(), CS_ENCODER_SET); | 933 ASSERT_EQ(notes[i]->Wait(), CS_ENCODER_SET); |
| 919 ASSERT_EQ(notes[i]->Wait(), CS_INITIALIZED); | 934 ASSERT_EQ(notes[i]->Wait(), CS_INITIALIZED); |
| 920 ASSERT_EQ(notes[i]->Wait(), CS_ENCODING); | 935 ASSERT_EQ(notes[i]->Wait(), CS_ENCODING); |
| 921 ASSERT_EQ(notes[i]->Wait(), CS_FINISHING); | |
| 922 ASSERT_EQ(notes[i]->Wait(), CS_FINISHED); | 936 ASSERT_EQ(notes[i]->Wait(), CS_FINISHED); |
| 923 encoder_threads[i]->message_loop()->PostTask( | 937 encoder_threads[i]->message_loop()->PostTask( |
| 924 FROM_HERE, | 938 FROM_HERE, |
| 925 base::Bind(&VEAClient::DestroyEncoder, base::Unretained(clients[i]))); | 939 base::Bind(&VEAClient::DestroyEncoder, base::Unretained(clients[i]))); |
| 926 encoder_threads[i]->Stop(); | 940 encoder_threads[i]->Stop(); |
| 927 } | 941 } |
| 928 } | 942 } |
| 929 | 943 |
| 930 INSTANTIATE_TEST_CASE_P( | 944 INSTANTIATE_TEST_CASE_P( |
| 931 SimpleEncode, | 945 SimpleEncode, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 test_stream_data->assign(it->second.c_str()); | 1018 test_stream_data->assign(it->second.c_str()); |
| 1005 continue; | 1019 continue; |
| 1006 } | 1020 } |
| 1007 if (it->first == "v" || it->first == "vmodule") | 1021 if (it->first == "v" || it->first == "vmodule") |
| 1008 continue; | 1022 continue; |
| 1009 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; | 1023 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second; |
| 1010 } | 1024 } |
| 1011 | 1025 |
| 1012 return RUN_ALL_TESTS(); | 1026 return RUN_ALL_TESTS(); |
| 1013 } | 1027 } |
| OLD | NEW |