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
3 // found in the LICENSE file.
5 #include "base/at_exit.h"
7 #include "base/command_line.h"
8 #include "base/file_util.h"
9 #include "base/files/memory_mapped_file.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/numerics/safe_conversions.h"
12 #include "base/process/process.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_split.h"
15 #include "content/common/gpu/media/exynos_video_encode_accelerator.h"
16 #include "content/common/gpu/media/video_accelerator_unittest_helpers.h"
17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/bitstream_buffer.h"
19 #include "media/base/test_data_util.h"
20 #include "media/filters/h264_parser.h"
21 #include "media/video/video_encode_accelerator.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using media::VideoEncodeAccelerator;
29 const media::VideoFrame::Format kInputFormat = media::VideoFrame::I420;
31 // Arbitrarily chosen to add some depth to the pipeline.
32 const unsigned int kNumOutputBuffers = 4;
33 const unsigned int kNumExtraInputFrames = 4;
34 // Maximum delay between requesting a keyframe and receiving one, in frames.
35 // Arbitrarily chosen as a reasonable requirement.
36 const unsigned int kMaxKeyframeDelay = 4;
37 // Value to use as max frame number for keyframe detection.
38 const unsigned int kMaxFrameNum =
39 std::numeric_limits<unsigned int>::max() - kMaxKeyframeDelay;
40 const uint32 kDefaultBitrate = 2000000;
41 // Tolerance factor for how encoded bitrate can differ from requested bitrate.
42 const double kBitrateTolerance = 0.1;
43 const uint32 kDefaultFPS = 30;
45 // The syntax of each test stream is:
46 // "in_filename:width:height:out_filename:requested_bitrate"
47 // - |in_filename| must be an I420 (YUV planar) raw stream
48 // (see http://www.fourcc.org/yuv.php#IYUV).
49 // - |width| and |height| are in pixels.
50 // - |profile| to encode into (values of media::VideoCodecProfile).
51 // - |out_filename| filename to save the encoded stream to (optional).
52 // Output stream is saved for the simple encode test only.
53 // - |requested_bitrate| requested bitrate in bits per second (optional).
54 // Bitrate is only forced for tests that test bitrate.
55 base::FilePath::StringType test_stream_data =
56 media::GetTestDataFilePath("sync_192p20_frames.yuv").value() +
57 ":320:192:1:out.h264:200000";
60 TestStream() : requested_bitrate(0) {}
64 base::MemoryMappedFile input_file;
65 media::VideoCodecProfile requested_profile;
66 std::string out_filename;
67 unsigned int requested_bitrate;
70 static void ParseAndReadTestStreamData(base::FilePath::StringType data,
71 TestStream* test_stream) {
72 std::vector<base::FilePath::StringType> fields;
73 base::SplitString(data, ':', &fields);
74 CHECK_GE(fields.size(), 4U) << data;
75 CHECK_LE(fields.size(), 6U) << data;
77 base::FilePath::StringType filename = fields[0];
79 CHECK(base::StringToInt(fields[1], &width));
80 CHECK(base::StringToInt(fields[2], &height));
81 test_stream->size = gfx::Size(width, height);
82 CHECK(!test_stream->size.IsEmpty());
84 CHECK(base::StringToInt(fields[3], &profile));
85 CHECK_GT(profile, media::VIDEO_CODEC_PROFILE_UNKNOWN);
86 CHECK_LE(profile, media::VIDEO_CODEC_PROFILE_MAX);
87 test_stream->requested_profile =
88 static_cast<media::VideoCodecProfile>(profile);
89 if (fields.size() >= 5 && !fields[4].empty())
90 test_stream->out_filename = fields[4];
91 if (fields.size() >= 6 && !fields[5].empty())
92 CHECK(base::StringToUint(fields[5], &test_stream->requested_bitrate));
94 CHECK(test_stream->input_file.Initialize(base::FilePath(filename)));
107 // Performs basic, codec-specific sanity checks on the stream buffers passed
108 // to ProcessStreamBuffer(): whether we've seen keyframes before non-keyframes,
109 // correct sequences of H.264 NALUs (SPS before PPS and before slices), etc.
110 // Calls given FrameFoundCallback when a complete frame is found while
112 class StreamValidator {
114 // To be called when a complete frame is found while processing a stream
115 // buffer, passing true if the frame is a keyframe. Returns false if we
116 // are not interested in more frames and further processing should be aborted.
117 typedef base::Callback<bool(bool)> FrameFoundCallback;
119 virtual ~StreamValidator() {}
121 // Provide a StreamValidator instance for the given |profile|.
122 static scoped_ptr<StreamValidator> Create(media::VideoCodecProfile profile,
123 const FrameFoundCallback& frame_cb);
125 // Process and verify contents of a bitstream buffer.
126 virtual void ProcessStreamBuffer(const uint8* stream, size_t size) = 0;
129 explicit StreamValidator(const FrameFoundCallback& frame_cb)
130 : frame_cb_(frame_cb) {}
132 FrameFoundCallback frame_cb_;
135 class H264Validator : public StreamValidator {
137 explicit H264Validator(const FrameFoundCallback& frame_cb)
138 : StreamValidator(frame_cb),
143 void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE;
146 // Set to true when encoder provides us with the corresponding NALU type.
152 void H264Validator::ProcessStreamBuffer(const uint8* stream, size_t size) {
153 media::H264Parser h264_parser;
154 h264_parser.SetStream(stream, size);
157 media::H264NALU nalu;
158 media::H264Parser::Result result;
160 result = h264_parser.AdvanceToNextNALU(&nalu);
161 if (result == media::H264Parser::kEOStream)
164 ASSERT_EQ(result, media::H264Parser::kOk);
166 bool keyframe = false;
168 switch (nalu.nal_unit_type) {
169 case media::H264NALU::kIDRSlice:
170 ASSERT_TRUE(seen_sps_);
171 ASSERT_TRUE(seen_pps_);
172 seen_idr_ = keyframe = true;
174 case media::H264NALU::kNonIDRSlice:
175 ASSERT_TRUE(seen_idr_);
176 if (!frame_cb_.Run(keyframe))
180 case media::H264NALU::kSPS:
184 case media::H264NALU::kPPS:
185 ASSERT_TRUE(seen_sps_);
195 class VP8Validator : public StreamValidator {
197 explicit VP8Validator(const FrameFoundCallback& frame_cb)
198 : StreamValidator(frame_cb),
199 seen_keyframe_(false) {}
201 void ProcessStreamBuffer(const uint8* stream, size_t size) OVERRIDE;
204 // Have we already got a keyframe in the stream?
208 void VP8Validator::ProcessStreamBuffer(const uint8* stream, size_t size) {
209 bool keyframe = !(stream[0] & 0x01);
211 seen_keyframe_ = true;
213 EXPECT_TRUE(seen_keyframe_);
215 frame_cb_.Run(keyframe);
216 // TODO(posciak): We could be getting more frames in the buffer, but there is
217 // no simple way to detect this. We'd need to parse the frames and go through
218 // partition numbers/sizes. For now assume one frame per buffer.
222 scoped_ptr<StreamValidator> StreamValidator::Create(
223 media::VideoCodecProfile profile,
224 const FrameFoundCallback& frame_cb) {
225 scoped_ptr<StreamValidator> validator;
227 if (profile >= media::H264PROFILE_MIN &&
228 profile <= media::H264PROFILE_MAX) {
229 validator.reset(new H264Validator(frame_cb));
230 } else if (profile >= media::VP8PROFILE_MIN &&
231 profile <= media::VP8PROFILE_MAX) {
232 validator.reset(new VP8Validator(frame_cb));
234 LOG(FATAL) << "Unsupported profile: " << profile;
237 return validator.Pass();
240 class VEAClient : public VideoEncodeAccelerator::Client {
242 VEAClient(const TestStream& test_stream,
243 ClientStateNotification<ClientState>* note,
245 unsigned int keyframe_period,
247 virtual ~VEAClient();
248 void CreateEncoder();
249 void DestroyEncoder();
251 // VideoDecodeAccelerator::Client implementation.
252 void NotifyInitializeDone() OVERRIDE;
253 void RequireBitstreamBuffers(unsigned int input_count,
254 const gfx::Size& input_coded_size,
255 size_t output_buffer_size) OVERRIDE;
256 void BitstreamBufferReady(int32 bitstream_buffer_id,
258 bool key_frame) OVERRIDE;
259 void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE;
262 bool has_encoder() { return encoder_.get(); }
264 void SetState(ClientState new_state);
265 // Called before starting encode to set initial configuration of the encoder.
266 void SetInitialConfiguration();
267 // Called when encoder is done with a VideoFrame.
268 void InputNoLongerNeededCallback(int32 input_id);
269 // Ensure encoder has at least as many inputs as it asked for
270 // via RequireBitstreamBuffers().
271 void FeedEncoderWithInputs();
272 // Provide the encoder with a new output buffer.
273 void FeedEncoderWithOutput(base::SharedMemory* shm);
274 // Feed the encoder with num_required_input_buffers_ of black frames to force
275 // it to encode and return all inputs that came before this, effectively
279 // Called on finding a complete frame (with |keyframe| set to true for
280 // keyframes) in the stream, to perform codec-independent, per-frame checks
281 // and accounting. Returns false once we have collected all frames we needed.
282 bool HandleEncodedFrame(bool keyframe);
284 // Perform any checks required at the end of the stream, called after
285 // receiving the last frame from the encoder.
286 void ChecksAtFinish();
288 // Prepare and return a frame wrapping the data at |position| bytes in
289 // the input stream, ready to be sent to encoder.
290 scoped_refptr<media::VideoFrame> PrepareInputFrame(off_t position);
293 scoped_ptr<VideoEncodeAccelerator> encoder_;
295 const TestStream& test_stream_;
296 ClientStateNotification<ClientState>* note_;
298 // Ids assigned to VideoFrames (start at 1 for easy comparison with
299 // num_encoded_frames_).
300 std::set<int32> inputs_at_client_;
301 int32 next_input_id_;
303 // Ids for output BitstreamBuffers.
304 typedef std::map<int32, base::SharedMemory*> IdToSHM;
305 ScopedVector<base::SharedMemory> output_shms_;
306 IdToSHM output_buffers_at_client_;
307 int32 next_output_buffer_id_;
309 // Current offset into input stream.
310 off_t pos_in_input_stream_;
311 // Calculated from input_coded_size_, in bytes.
312 size_t input_buffer_size_;
313 gfx::Size input_coded_size_;
314 // Requested by encoder.
315 unsigned int num_required_input_buffers_;
316 size_t output_buffer_size_;
318 // Precalculated number of frames in the stream.
319 unsigned int num_frames_in_stream_;
320 // Number of encoded frames we've got from the encoder thus far.
321 unsigned int num_encoded_frames_;
323 // True if received a keyframe while processing current bitstream buffer.
324 bool seen_keyframe_in_this_buffer_;
326 // True if we are to save the encoded stream to a file.
329 // Request a keyframe every keyframe_period_ frames.
330 const unsigned int keyframe_period_;
332 // Frame number for which we requested a keyframe.
333 unsigned int keyframe_requested_at_;
335 // True if we are asking encoder for a particular bitrate.
338 // Byte size of the encoded stream (for bitrate calculation).
339 size_t encoded_stream_size_;
341 scoped_ptr<StreamValidator> validator_;
343 // All methods of this class should be run on the same thread.
344 base::ThreadChecker thread_checker_;
347 VEAClient::VEAClient(const TestStream& test_stream,
348 ClientStateNotification<ClientState>* note,
350 unsigned int keyframe_period,
352 : state_(CS_CREATED),
353 test_stream_(test_stream),
356 next_output_buffer_id_(0),
357 pos_in_input_stream_(0),
358 input_buffer_size_(0),
359 num_required_input_buffers_(0),
360 output_buffer_size_(0),
361 num_frames_in_stream_(0),
362 num_encoded_frames_(0),
363 seen_keyframe_in_this_buffer_(false),
364 save_to_file_(save_to_file),
365 keyframe_period_(keyframe_period),
366 keyframe_requested_at_(kMaxFrameNum),
367 force_bitrate_(force_bitrate),
368 encoded_stream_size_(0) {
369 if (keyframe_period_)
370 CHECK_LT(kMaxKeyframeDelay, keyframe_period_);
372 validator_ = StreamValidator::Create(
373 test_stream_.requested_profile,
374 base::Bind(&VEAClient::HandleEncodedFrame, base::Unretained(this)));
376 CHECK(validator_.get());
379 CHECK(!test_stream_.out_filename.empty());
380 base::FilePath out_filename(test_stream_.out_filename);
381 // This creates or truncates out_filename.
382 // Without it, AppendToFile() will not work.
383 EXPECT_EQ(0, base::WriteFile(out_filename, NULL, 0));
386 thread_checker_.DetachFromThread();
389 VEAClient::~VEAClient() { CHECK(!has_encoder()); }
391 void VEAClient::CreateEncoder() {
392 DCHECK(thread_checker_.CalledOnValidThread());
393 CHECK(!has_encoder());
395 encoder_.reset(new ExynosVideoEncodeAccelerator());
397 SetState(CS_ENCODER_SET);
398 DVLOG(1) << "Profile: " << test_stream_.requested_profile
399 << ", requested bitrate: " << test_stream_.requested_bitrate;
400 encoder_->Initialize(kInputFormat,
402 test_stream_.requested_profile,
403 test_stream_.requested_bitrate,
407 void VEAClient::DestroyEncoder() {
408 DCHECK(thread_checker_.CalledOnValidThread());
411 encoder_.release()->Destroy();
414 void VEAClient::NotifyInitializeDone() {
415 DCHECK(thread_checker_.CalledOnValidThread());
416 SetInitialConfiguration();
417 SetState(CS_INITIALIZED);
420 void VEAClient::RequireBitstreamBuffers(unsigned int input_count,
421 const gfx::Size& input_coded_size,
422 size_t output_size) {
423 DCHECK(thread_checker_.CalledOnValidThread());
424 ASSERT_EQ(state_, CS_INITIALIZED);
425 SetState(CS_ENCODING);
427 // TODO(posciak): For now we only support input streams that meet encoder
428 // size requirements exactly (i.e. coded size == visible size).
429 input_coded_size_ = input_coded_size;
430 ASSERT_EQ(input_coded_size_, test_stream_.size);
432 input_buffer_size_ = media::VideoFrame::AllocationSize(kInputFormat,
434 CHECK_GT(input_buffer_size_, 0UL);
436 // ARM performs CPU cache management with CPU cache line granularity. We thus
437 // need to ensure our buffers are CPU cache line-aligned (64 byte-aligned).
438 // Otherwise newer kernels will refuse to accept them, and on older kernels
439 // we'll be treating ourselves to random corruption.
440 // Since we are just mmapping and passing chunks of the input file, to ensure
441 // alignment, if the starting virtual addresses of the frames in it were not
442 // 64 byte-aligned, we'd have to use a separate set of input buffers and copy
443 // the frames into them before sending to the encoder. It would have been an
444 // overkill here though, because, for now at least, we only test resolutions
445 // that result in proper alignment, and it would have also interfered with
446 // performance testing. So just assert that the frame size is a multiple of
447 // 64 bytes. This ensures all frames start at 64-byte boundary, because
448 // MemoryMappedFile should be mmapp()ed at virtual page start as well.
449 ASSERT_EQ(input_buffer_size_ & 63, 0)
450 << "Frame size has to be a multiple of 64 bytes";
451 ASSERT_EQ(reinterpret_cast<off_t>(test_stream_.input_file.data()) & 63, 0)
452 << "Mapped file should be mapped at a 64 byte boundary";
454 num_required_input_buffers_ = input_count;
455 ASSERT_GT(num_required_input_buffers_, 0UL);
457 num_frames_in_stream_ = test_stream_.input_file.length() / input_buffer_size_;
458 CHECK_GT(num_frames_in_stream_, 0UL);
459 CHECK_LE(num_frames_in_stream_, kMaxFrameNum);
460 CHECK_EQ(num_frames_in_stream_ * input_buffer_size_,
461 test_stream_.input_file.length());
463 output_buffer_size_ = output_size;
464 ASSERT_GT(output_buffer_size_, 0UL);
466 for (unsigned int i = 0; i < kNumOutputBuffers; ++i) {
467 base::SharedMemory* shm = new base::SharedMemory();
468 CHECK(shm->CreateAndMapAnonymous(output_buffer_size_));
469 output_shms_.push_back(shm);
470 FeedEncoderWithOutput(shm);
473 FeedEncoderWithInputs();
476 void VEAClient::BitstreamBufferReady(int32 bitstream_buffer_id,
479 DCHECK(thread_checker_.CalledOnValidThread());
480 ASSERT_LE(payload_size, output_buffer_size_);
482 IdToSHM::iterator it = output_buffers_at_client_.find(bitstream_buffer_id);
483 ASSERT_NE(it, output_buffers_at_client_.end());
484 base::SharedMemory* shm = it->second;
485 output_buffers_at_client_.erase(it);
487 if (state_ == CS_FINISHED)
490 encoded_stream_size_ += payload_size;
492 const uint8* stream_ptr = static_cast<const uint8*>(shm->memory());
493 if (payload_size > 0)
494 validator_->ProcessStreamBuffer(stream_ptr, payload_size);
496 EXPECT_EQ(key_frame, seen_keyframe_in_this_buffer_);
497 seen_keyframe_in_this_buffer_ = false;
500 int size = base::checked_cast<int>(payload_size);
501 EXPECT_EQ(base::AppendToFile(
502 base::FilePath::FromUTF8Unsafe(test_stream_.out_filename),
503 static_cast<char*>(shm->memory()),
508 FeedEncoderWithOutput(shm);
511 void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) {
512 DCHECK(thread_checker_.CalledOnValidThread());
516 void VEAClient::SetState(ClientState new_state) {
517 note_->Notify(new_state);
521 void VEAClient::SetInitialConfiguration() {
522 if (force_bitrate_) {
523 CHECK_GT(test_stream_.requested_bitrate, 0UL);
524 encoder_->RequestEncodingParametersChange(test_stream_.requested_bitrate,
529 void VEAClient::InputNoLongerNeededCallback(int32 input_id) {
530 std::set<int32>::iterator it = inputs_at_client_.find(input_id);
531 ASSERT_NE(it, inputs_at_client_.end());
532 inputs_at_client_.erase(it);
533 FeedEncoderWithInputs();
536 scoped_refptr<media::VideoFrame> VEAClient::PrepareInputFrame(off_t position) {
537 CHECK_LE(position + input_buffer_size_, test_stream_.input_file.length());
540 const_cast<uint8*>(test_stream_.input_file.data() + position);
542 scoped_refptr<media::VideoFrame> frame =
543 media::VideoFrame::WrapExternalYuvData(
546 gfx::Rect(test_stream_.size),
548 input_coded_size_.width(),
549 input_coded_size_.width() / 2,
550 input_coded_size_.width() / 2,
552 frame_data + input_coded_size_.GetArea(),
553 frame_data + (input_coded_size_.GetArea() * 5 / 4),
555 media::BindToCurrentLoop(
556 base::Bind(&VEAClient::InputNoLongerNeededCallback,
557 base::Unretained(this),
560 CHECK(inputs_at_client_.insert(next_input_id_).second);
566 void VEAClient::FeedEncoderWithInputs() {
570 if (state_ != CS_ENCODING)
573 while (inputs_at_client_.size() <
574 num_required_input_buffers_ + kNumExtraInputFrames) {
575 size_t bytes_left = test_stream_.input_file.length() - pos_in_input_stream_;
576 if (bytes_left < input_buffer_size_) {
577 DCHECK_EQ(bytes_left, 0UL);
582 bool force_keyframe = false;
583 if (keyframe_period_ && next_input_id_ % keyframe_period_ == 0) {
584 keyframe_requested_at_ = next_input_id_;
585 force_keyframe = true;
588 scoped_refptr<media::VideoFrame> video_frame =
589 PrepareInputFrame(pos_in_input_stream_);
590 pos_in_input_stream_ += input_buffer_size_;
592 encoder_->Encode(video_frame, force_keyframe);
596 void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) {
600 if (state_ != CS_ENCODING && state_ != CS_FINISHING)
603 base::SharedMemoryHandle dup_handle;
604 CHECK(shm->ShareToProcess(base::Process::Current().handle(), &dup_handle));
606 media::BitstreamBuffer bitstream_buffer(
607 next_output_buffer_id_++, dup_handle, output_buffer_size_);
608 CHECK(output_buffers_at_client_.insert(std::make_pair(bitstream_buffer.id(),
610 encoder_->UseOutputBitstreamBuffer(bitstream_buffer);
613 void VEAClient::FlushEncoder() {
614 ASSERT_EQ(state_, CS_ENCODING);
615 SetState(CS_FINISHING);
617 // Feed the encoder with an additional set of num_required_input_buffers_
618 // to flush it, using the first frame in the input stream. The resulting
619 // encoded frames will be ignored.
620 for (unsigned int i = 0; i < num_required_input_buffers_; ++i) {
621 scoped_refptr<media::VideoFrame> frame = PrepareInputFrame(0);
622 encoder_->Encode(frame, false);
626 bool VEAClient::HandleEncodedFrame(bool keyframe) {
627 // This would be a bug in the test, which should not ignore false
628 // return value from this method.
629 CHECK_LE(num_encoded_frames_, num_frames_in_stream_);
631 ++num_encoded_frames_;
633 // Got keyframe, reset keyframe detection regardless of whether we
634 // got a frame in time or not.
635 keyframe_requested_at_ = kMaxFrameNum;
636 seen_keyframe_in_this_buffer_ = true;
639 // Because the keyframe behavior requirements are loose, we give
640 // the encoder more freedom here. It could either deliver a keyframe
641 // immediately after we requested it, which could be for a frame number
642 // before the one we requested it for (if the keyframe request
643 // is asynchronous, i.e. not bound to any concrete frame, and because
644 // the pipeline can be deeper than one frame), at that frame, or after.
645 // So the only constraints we put here is that we get a keyframe not
646 // earlier than we requested one (in time), and not later than
647 // kMaxKeyframeDelay frames after the frame, for which we requested
648 // it, comes back encoded.
649 EXPECT_LE(num_encoded_frames_, keyframe_requested_at_ + kMaxKeyframeDelay);
651 if (num_encoded_frames_ == num_frames_in_stream_) {
653 SetState(CS_FINISHED);
660 void VEAClient::ChecksAtFinish() {
661 unsigned int bitrate =
662 encoded_stream_size_ * 8 * kDefaultFPS / num_frames_in_stream_;
663 DVLOG(1) << "Final bitrate: " << bitrate
664 << " num frames: " << num_frames_in_stream_;
665 if (force_bitrate_) {
667 test_stream_.requested_bitrate,
668 kBitrateTolerance * test_stream_.requested_bitrate);
673 // - If true, save output to file (provided an output filename was supplied).
674 // - Force a keyframe every n frames.
675 // - Force bitrate; the actual required value is provided as a property
676 // of the input stream, because it depends on stream type/resolution/etc.
677 class VideoEncodeAcceleratorTest
678 : public ::testing::TestWithParam<Tuple3<bool, int, bool> > {};
680 TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) {
681 const unsigned int keyframe_period = GetParam().b;
682 const bool force_bitrate = GetParam().c;
684 TestStream test_stream;
685 ParseAndReadTestStreamData(test_stream_data, &test_stream);
687 // Disregard save_to_file if we didn't get an output filename.
688 const bool save_to_file = GetParam().a && !test_stream.out_filename.empty();
690 if (test_stream.requested_bitrate == 0)
691 test_stream.requested_bitrate = kDefaultBitrate;
693 base::Thread encoder_thread("EncoderThread");
694 encoder_thread.Start();
696 ClientStateNotification<ClientState> note;
697 scoped_ptr<VEAClient> client(new VEAClient(test_stream,
703 encoder_thread.message_loop()->PostTask(
705 base::Bind(&VEAClient::CreateEncoder, base::Unretained(client.get())));
707 ASSERT_EQ(note.Wait(), CS_ENCODER_SET);
708 ASSERT_EQ(note.Wait(), CS_INITIALIZED);
709 ASSERT_EQ(note.Wait(), CS_ENCODING);
710 ASSERT_EQ(note.Wait(), CS_FINISHING);
711 ASSERT_EQ(note.Wait(), CS_FINISHED);
713 encoder_thread.message_loop()->PostTask(
715 base::Bind(&VEAClient::DestroyEncoder, base::Unretained(client.get())));
717 encoder_thread.Stop();
720 INSTANTIATE_TEST_CASE_P(SimpleEncode,
721 VideoEncodeAcceleratorTest,
722 ::testing::Values(MakeTuple(true, 0, false)));
724 INSTANTIATE_TEST_CASE_P(ForceKeyframes,
725 VideoEncodeAcceleratorTest,
726 ::testing::Values(MakeTuple(false, 10, false)));
728 INSTANTIATE_TEST_CASE_P(ForceBitrate,
729 VideoEncodeAcceleratorTest,
730 ::testing::Values(MakeTuple(false, 0, true)));
732 // TODO(posciak): more tests:
733 // - async FeedEncoderWithOutput
734 // - out-of-order return of outputs to encoder
735 // - dynamic, runtime bitrate changes
736 // - multiple encoders
737 // - multiple encoders + decoders
738 // - mid-stream encoder_->Destroy()
741 } // namespace content
743 int main(int argc, char** argv) {
744 testing::InitGoogleTest(&argc, argv); // Removes gtest-specific args.
745 CommandLine::Init(argc, argv);
747 // Needed to enable DVLOG through --vmodule.
748 logging::LoggingSettings settings;
749 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
750 CHECK(logging::InitLogging(settings));
752 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
755 CommandLine::SwitchMap switches = cmd_line->GetSwitches();
756 for (CommandLine::SwitchMap::const_iterator it = switches.begin();
757 it != switches.end();
759 if (it->first == "test_stream_data") {
760 content::test_stream_data = it->second.c_str();
763 if (it->first == "v" || it->first == "vmodule")
765 LOG(FATAL) << "Unexpected switch: " << it->first << ":" << it->second;
768 base::ShadowingAtExitManager at_exit_manager;
770 return RUN_ALL_TESTS();