| Index: media/gpu/video_encode_accelerator_unittest.cc
|
| diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc
|
| index f7e2e58dc3f535f63702bfb0844bc262bde54150..4e0dd6ad8ec14bcdf064266d6eb131e9d8a9b3d5 100644
|
| --- a/media/gpu/video_encode_accelerator_unittest.cc
|
| +++ b/media/gpu/video_encode_accelerator_unittest.cc
|
| @@ -203,8 +203,6 @@
|
| return std::numeric_limits<size_t>::max() / sizeof(T);
|
| }
|
| };
|
| -typedef std::vector<char, AlignedAllocator<char, kPlatformBufferAlignment>>
|
| - AlignedCharVector;
|
|
|
| struct TestStream {
|
| TestStream()
|
| @@ -227,7 +225,8 @@
|
| // A vector used to prepare aligned input buffers of |in_filename|. This
|
| // makes sure starting addresses of YUV planes are aligned to
|
| // kPlatformBufferAlignment bytes.
|
| - AlignedCharVector aligned_in_file_data;
|
| + std::vector<char, AlignedAllocator<char, kPlatformBufferAlignment>>
|
| + aligned_in_file_data;
|
|
|
| // Byte size of a frame of |aligned_in_file_data|.
|
| size_t aligned_buffer_size;
|
| @@ -875,37 +874,7 @@
|
| << "difference = " << difference << " > decode similarity threshold";
|
| }
|
|
|
| -// Base class for all VEA Clients in this file
|
| -class VEAClientBase : public VideoEncodeAccelerator::Client {
|
| - public:
|
| - ~VEAClientBase() override { LOG_ASSERT(!has_encoder()); }
|
| - void NotifyError(VideoEncodeAccelerator::Error error) override {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - SetState(CS_ERROR);
|
| - }
|
| -
|
| - protected:
|
| - VEAClientBase(ClientStateNotification<ClientState>* note)
|
| - : note_(note), next_output_buffer_id_(0) {}
|
| -
|
| - bool has_encoder() { return encoder_.get(); }
|
| -
|
| - virtual void SetState(ClientState new_state) = 0;
|
| -
|
| - std::unique_ptr<VideoEncodeAccelerator> encoder_;
|
| -
|
| - // Used to notify another thread about the state. VEAClientBase does not own
|
| - // this.
|
| - ClientStateNotification<ClientState>* note_;
|
| -
|
| - // All methods of this class should be run on the same thread.
|
| - base::ThreadChecker thread_checker_;
|
| -
|
| - ScopedVector<base::SharedMemory> output_shms_;
|
| - int32_t next_output_buffer_id_;
|
| -};
|
| -
|
| -class VEAClient : public VEAClientBase {
|
| +class VEAClient : public VideoEncodeAccelerator::Client {
|
| public:
|
| VEAClient(TestStream* test_stream,
|
| ClientStateNotification<ClientState>* note,
|
| @@ -917,6 +886,7 @@
|
| bool mid_stream_framerate_switch,
|
| bool verify_output,
|
| bool verify_output_timestamp);
|
| + ~VEAClient() override;
|
| void CreateEncoder();
|
| void DestroyEncoder();
|
|
|
| @@ -931,17 +901,19 @@
|
| size_t payload_size,
|
| bool key_frame,
|
| base::TimeDelta timestamp) override;
|
| + void NotifyError(VideoEncodeAccelerator::Error error) override;
|
|
|
| private:
|
| void BitstreamBufferReadyOnMainThread(int32_t bitstream_buffer_id,
|
| size_t payload_size,
|
| bool key_frame,
|
| base::TimeDelta timestamp);
|
| + bool has_encoder() { return encoder_.get(); }
|
|
|
| // Return the number of encoded frames per second.
|
| double frames_per_second();
|
|
|
| - void SetState(ClientState new_state) override;
|
| + void SetState(ClientState new_state);
|
|
|
| // Set current stream parameters to given |bitrate| at |framerate|.
|
| void SetStreamParameters(unsigned int bitrate, unsigned int framerate);
|
| @@ -1006,8 +978,12 @@
|
| void VerifyOutputTimestamp(base::TimeDelta timestamp);
|
|
|
| ClientState state_;
|
| + std::unique_ptr<VideoEncodeAccelerator> encoder_;
|
|
|
| TestStream* test_stream_;
|
| +
|
| + // Used to notify another thread about the state. VEAClient does not own this.
|
| + ClientStateNotification<ClientState>* note_;
|
|
|
| // Ids assigned to VideoFrames.
|
| std::set<int32_t> inputs_at_client_;
|
| @@ -1023,7 +999,9 @@
|
|
|
| // Ids for output BitstreamBuffers.
|
| typedef std::map<int32_t, base::SharedMemory*> IdToSHM;
|
| + ScopedVector<base::SharedMemory> output_shms_;
|
| IdToSHM output_buffers_at_client_;
|
| + int32_t next_output_buffer_id_;
|
|
|
| // Current offset into input stream.
|
| off_t pos_in_input_stream_;
|
| @@ -1090,6 +1068,9 @@
|
|
|
| // The time when the last encoded frame is ready.
|
| base::TimeTicks last_frame_ready_time_;
|
| +
|
| + // All methods of this class should be run on the same thread.
|
| + base::ThreadChecker thread_checker_;
|
|
|
| // Requested bitrate in bits per second.
|
| unsigned int requested_bitrate_;
|
| @@ -1141,10 +1122,11 @@
|
| bool mid_stream_framerate_switch,
|
| bool verify_output,
|
| bool verify_output_timestamp)
|
| - : VEAClientBase(note),
|
| - state_(CS_CREATED),
|
| + : state_(CS_CREATED),
|
| test_stream_(test_stream),
|
| + note_(note),
|
| next_input_id_(0),
|
| + next_output_buffer_id_(0),
|
| pos_in_input_stream_(0),
|
| num_required_input_buffers_(0),
|
| output_buffer_size_(0),
|
| @@ -1198,6 +1180,10 @@
|
| thread_checker_.DetachFromThread();
|
| }
|
|
|
| +VEAClient::~VEAClient() {
|
| + LOG_ASSERT(!has_encoder());
|
| +}
|
| +
|
| void VEAClient::CreateEncoder() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| LOG_ASSERT(!has_encoder());
|
| @@ -1416,6 +1402,11 @@
|
| FROM_HERE, base::Bind(&VEAClient::BitstreamBufferReadyOnMainThread,
|
| base::Unretained(this), bitstream_buffer_id,
|
| payload_size, key_frame, timestamp));
|
| +}
|
| +
|
| +void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + SetState(CS_ERROR);
|
| }
|
|
|
| void VEAClient::BitstreamBufferReadyOnMainThread(int32_t bitstream_buffer_id,
|
| @@ -1768,119 +1759,13 @@
|
| reinterpret_cast<char*>(&header), sizeof(header)));
|
| }
|
|
|
| -// Base class for simple VEA Clients
|
| -class SimpleVEAClientBase : public VEAClientBase {
|
| - public:
|
| - void CreateEncoder();
|
| - void DestroyEncoder();
|
| -
|
| - // VideoDecodeAccelerator::Client implementation.
|
| - void RequireBitstreamBuffers(unsigned int input_count,
|
| - const gfx::Size& input_coded_size,
|
| - size_t output_buffer_size) override;
|
| -
|
| - protected:
|
| - SimpleVEAClientBase(ClientStateNotification<ClientState>* note,
|
| - const int width,
|
| - const int height);
|
| -
|
| - void SetState(ClientState new_state) override;
|
| -
|
| - // Provide the encoder with a new output buffer.
|
| - void FeedEncoderWithOutput(base::SharedMemory* shm, size_t output_size);
|
| -
|
| - const int width_;
|
| - const int height_;
|
| - const int bitrate_;
|
| - const int fps_;
|
| -};
|
| -
|
| -SimpleVEAClientBase::SimpleVEAClientBase(
|
| - ClientStateNotification<ClientState>* note,
|
| - const int width,
|
| - const int height)
|
| - : VEAClientBase(note),
|
| - width_(width),
|
| - height_(height),
|
| - bitrate_(200000),
|
| - fps_(30) {
|
| - thread_checker_.DetachFromThread();
|
| -}
|
| -
|
| -void SimpleVEAClientBase::CreateEncoder() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - LOG_ASSERT(!has_encoder());
|
| - LOG_ASSERT(g_env->test_streams_.size());
|
| -
|
| - std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
|
| - CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
|
| - CreateMFVEA()};
|
| -
|
| - gfx::Size visible_size(width_, height_);
|
| - for (auto& encoder : encoders) {
|
| - if (!encoder)
|
| - continue;
|
| - encoder_ = std::move(encoder);
|
| - if (encoder_->Initialize(kInputFormat, visible_size,
|
| - g_env->test_streams_[0]->requested_profile,
|
| - bitrate_, this)) {
|
| - encoder_->RequestEncodingParametersChange(bitrate_, fps_);
|
| - SetState(CS_INITIALIZED);
|
| - return;
|
| - }
|
| - }
|
| - encoder_.reset();
|
| - LOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed";
|
| - SetState(CS_ERROR);
|
| -}
|
| -
|
| -void SimpleVEAClientBase::DestroyEncoder() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!has_encoder())
|
| - return;
|
| - // Clear the objects that should be destroyed on the same thread as creation.
|
| - encoder_.reset();
|
| -}
|
| -
|
| -void SimpleVEAClientBase::SetState(ClientState new_state) {
|
| - DVLOG(4) << "Changing state to " << new_state;
|
| - note_->Notify(new_state);
|
| -}
|
| -
|
| -void SimpleVEAClientBase::RequireBitstreamBuffers(
|
| - unsigned int input_count,
|
| - const gfx::Size& input_coded_size,
|
| - size_t output_size) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - SetState(CS_ENCODING);
|
| - ASSERT_GT(output_size, 0UL);
|
| -
|
| - for (unsigned int i = 0; i < kNumOutputBuffers; ++i) {
|
| - base::SharedMemory* shm = new base::SharedMemory();
|
| - LOG_ASSERT(shm->CreateAndMapAnonymous(output_size));
|
| - output_shms_.push_back(shm);
|
| - FeedEncoderWithOutput(shm, output_size);
|
| - }
|
| -}
|
| -
|
| -void SimpleVEAClientBase::FeedEncoderWithOutput(base::SharedMemory* shm,
|
| - size_t output_size) {
|
| - if (!has_encoder())
|
| - return;
|
| -
|
| - base::SharedMemoryHandle dup_handle;
|
| - LOG_ASSERT(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle));
|
| -
|
| - BitstreamBuffer bitstream_buffer(next_output_buffer_id_++, dup_handle,
|
| - output_size);
|
| - encoder_->UseOutputBitstreamBuffer(bitstream_buffer);
|
| -}
|
| -
|
| // This client is only used to make sure the encoder does not return an encoded
|
| // frame before getting any input.
|
| -class VEANoInputClient : public SimpleVEAClientBase {
|
| +class VEANoInputClient : public VideoEncodeAccelerator::Client {
|
| public:
|
| explicit VEANoInputClient(ClientStateNotification<ClientState>* note);
|
| + ~VEANoInputClient() override;
|
| + void CreateEncoder();
|
| void DestroyEncoder();
|
|
|
| // VideoDecodeAccelerator::Client implementation.
|
| @@ -1891,19 +1776,81 @@
|
| size_t payload_size,
|
| bool key_frame,
|
| base::TimeDelta timestamp) override;
|
| + void NotifyError(VideoEncodeAccelerator::Error error) override;
|
|
|
| private:
|
| + bool has_encoder() { return encoder_.get(); }
|
| +
|
| + void SetState(ClientState new_state);
|
| +
|
| + // Provide the encoder with a new output buffer.
|
| + void FeedEncoderWithOutput(base::SharedMemory* shm, size_t output_size);
|
| +
|
| + std::unique_ptr<VideoEncodeAccelerator> encoder_;
|
| +
|
| + // Used to notify another thread about the state. VEAClient does not own this.
|
| + ClientStateNotification<ClientState>* note_;
|
| +
|
| + // All methods of this class should be run on the same thread.
|
| + base::ThreadChecker thread_checker_;
|
| +
|
| + // Ids for output BitstreamBuffers.
|
| + ScopedVector<base::SharedMemory> output_shms_;
|
| + int32_t next_output_buffer_id_;
|
| +
|
| // The timer used to monitor the encoder doesn't return an output buffer in
|
| // a period of time.
|
| std::unique_ptr<base::Timer> timer_;
|
| };
|
|
|
| VEANoInputClient::VEANoInputClient(ClientStateNotification<ClientState>* note)
|
| - : SimpleVEAClientBase(note, 320, 240) {}
|
| + : note_(note), next_output_buffer_id_(0) {
|
| + thread_checker_.DetachFromThread();
|
| +}
|
| +
|
| +VEANoInputClient::~VEANoInputClient() {
|
| + LOG_ASSERT(!has_encoder());
|
| +}
|
| +
|
| +void VEANoInputClient::CreateEncoder() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + LOG_ASSERT(!has_encoder());
|
| + LOG_ASSERT(g_env->test_streams_.size());
|
| +
|
| + const int kDefaultWidth = 320;
|
| + const int kDefaultHeight = 240;
|
| + const int kDefaultBitrate = 200000;
|
| + const int kDefaultFps = 30;
|
| +
|
| + std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
|
| + CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
|
| + CreateMFVEA()};
|
| +
|
| + // The test case is no input. Use default visible size, bitrate, and fps.
|
| + gfx::Size visible_size(kDefaultWidth, kDefaultHeight);
|
| + for (auto& encoder : encoders) {
|
| + if (!encoder)
|
| + continue;
|
| + encoder_ = std::move(encoder);
|
| + if (encoder_->Initialize(kInputFormat, visible_size,
|
| + g_env->test_streams_[0]->requested_profile,
|
| + kDefaultBitrate, this)) {
|
| + encoder_->RequestEncodingParametersChange(kDefaultBitrate, kDefaultFps);
|
| + SetState(CS_INITIALIZED);
|
| + return;
|
| + }
|
| + }
|
| + encoder_.reset();
|
| + LOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed";
|
| + SetState(CS_ERROR);
|
| +}
|
|
|
| void VEANoInputClient::DestroyEncoder() {
|
| - SimpleVEAClientBase::DestroyEncoder();
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (!has_encoder())
|
| + return;
|
| // Clear the objects that should be destroyed on the same thread as creation.
|
| + encoder_.reset();
|
| timer_.reset();
|
| }
|
|
|
| @@ -1911,9 +1858,16 @@
|
| unsigned int input_count,
|
| const gfx::Size& input_coded_size,
|
| size_t output_size) {
|
| - SimpleVEAClientBase::RequireBitstreamBuffers(input_count, input_coded_size,
|
| - output_size);
|
| -
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + SetState(CS_ENCODING);
|
| + ASSERT_GT(output_size, 0UL);
|
| +
|
| + for (unsigned int i = 0; i < kNumOutputBuffers; ++i) {
|
| + base::SharedMemory* shm = new base::SharedMemory();
|
| + LOG_ASSERT(shm->CreateAndMapAnonymous(output_size));
|
| + output_shms_.push_back(shm);
|
| + FeedEncoderWithOutput(shm, output_size);
|
| + }
|
| // Timer is used to make sure there is no output frame in 100ms.
|
| timer_.reset(new base::Timer(FROM_HERE,
|
| base::TimeDelta::FromMilliseconds(100),
|
| @@ -1931,79 +1885,27 @@
|
| SetState(CS_ERROR);
|
| }
|
|
|
| -// This client is only used to test input frame with the size of U and V planes
|
| -// unaligned to cache line.
|
| -// To have both width and height divisible by 16 but not 32 will make the size
|
| -// of U/V plane (width * height / 4) unaligned to 128-byte cache line.
|
| -class VEACacheLineUnalignedInputClient : public SimpleVEAClientBase {
|
| - public:
|
| - explicit VEACacheLineUnalignedInputClient(
|
| - ClientStateNotification<ClientState>* note);
|
| -
|
| - // VideoDecodeAccelerator::Client implementation.
|
| - void RequireBitstreamBuffers(unsigned int input_count,
|
| - const gfx::Size& input_coded_size,
|
| - size_t output_buffer_size) override;
|
| - void BitstreamBufferReady(int32_t bitstream_buffer_id,
|
| - size_t payload_size,
|
| - bool key_frame,
|
| - base::TimeDelta timestamp) override;
|
| -
|
| - private:
|
| - // Feed the encoder with one input frame.
|
| - void FeedEncoderWithOneInput(const gfx::Size& input_coded_size);
|
| -};
|
| -
|
| -VEACacheLineUnalignedInputClient::VEACacheLineUnalignedInputClient(
|
| - ClientStateNotification<ClientState>* note)
|
| - : SimpleVEAClientBase(note, 368, 368) {
|
| -} // 368 is divisible by 16 but not 32
|
| -
|
| -void VEACacheLineUnalignedInputClient::RequireBitstreamBuffers(
|
| - unsigned int input_count,
|
| - const gfx::Size& input_coded_size,
|
| - size_t output_size) {
|
| - SimpleVEAClientBase::RequireBitstreamBuffers(input_count, input_coded_size,
|
| - output_size);
|
| -
|
| - FeedEncoderWithOneInput(input_coded_size);
|
| -}
|
| -
|
| -void VEACacheLineUnalignedInputClient::BitstreamBufferReady(
|
| - int32_t bitstream_buffer_id,
|
| - size_t payload_size,
|
| - bool key_frame,
|
| - base::TimeDelta timestamp) {
|
| +void VEANoInputClient::NotifyError(VideoEncodeAccelerator::Error error) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| - // It's enough to encode just one frame. If plane size is not aligned,
|
| - // VideoEncodeAccelerator::Encode will fail.
|
| - SetState(CS_FINISHED);
|
| -}
|
| -
|
| -void VEACacheLineUnalignedInputClient::FeedEncoderWithOneInput(
|
| - const gfx::Size& input_coded_size) {
|
| + SetState(CS_ERROR);
|
| +}
|
| +
|
| +void VEANoInputClient::SetState(ClientState new_state) {
|
| + DVLOG(4) << "Changing state to " << new_state;
|
| + note_->Notify(new_state);
|
| +}
|
| +
|
| +void VEANoInputClient::FeedEncoderWithOutput(base::SharedMemory* shm,
|
| + size_t output_size) {
|
| if (!has_encoder())
|
| return;
|
|
|
| - AlignedCharVector aligned_plane[] = {
|
| - AlignedCharVector(
|
| - VideoFrame::PlaneSize(kInputFormat, 0, input_coded_size).GetArea()),
|
| - AlignedCharVector(
|
| - VideoFrame::PlaneSize(kInputFormat, 1, input_coded_size).GetArea()),
|
| - AlignedCharVector(
|
| - VideoFrame::PlaneSize(kInputFormat, 2, input_coded_size).GetArea())};
|
| - uint8_t* frame_data_y = reinterpret_cast<uint8_t*>(&aligned_plane[0][0]);
|
| - uint8_t* frame_data_u = reinterpret_cast<uint8_t*>(&aligned_plane[1][0]);
|
| - uint8_t* frame_data_v = reinterpret_cast<uint8_t*>(&aligned_plane[2][0]);
|
| -
|
| - scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData(
|
| - kInputFormat, input_coded_size, gfx::Rect(input_coded_size),
|
| - input_coded_size, input_coded_size.width(), input_coded_size.width() / 2,
|
| - input_coded_size.width() / 2, frame_data_y, frame_data_u, frame_data_v,
|
| - base::TimeDelta().FromMilliseconds(base::Time::kMillisecondsPerSecond /
|
| - fps_));
|
| -
|
| - encoder_->Encode(video_frame, false);
|
| + base::SharedMemoryHandle dup_handle;
|
| + LOG_ASSERT(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle));
|
| +
|
| + BitstreamBuffer bitstream_buffer(next_output_buffer_id_++, dup_handle,
|
| + output_size);
|
| + encoder_->UseOutputBitstreamBuffer(bitstream_buffer);
|
| }
|
|
|
| // Test parameters:
|
| @@ -2089,51 +1991,6 @@
|
| encoder_thread.Stop();
|
| }
|
|
|
| -// Test parameters:
|
| -// - Test type
|
| -// 0: No input test
|
| -// 1: Cache line-unaligned test
|
| -class VideoEncodeAcceleratorSimpleTest : public ::testing::TestWithParam<int> {
|
| -};
|
| -
|
| -template <class TestClient>
|
| -void SimpleTestFunc() {
|
| - std::unique_ptr<ClientStateNotification<ClientState>> note(
|
| - new ClientStateNotification<ClientState>());
|
| - std::unique_ptr<TestClient> client(new TestClient(note.get()));
|
| - base::Thread encoder_thread("EncoderThread");
|
| - ASSERT_TRUE(encoder_thread.Start());
|
| -
|
| - encoder_thread.task_runner()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&TestClient::CreateEncoder, base::Unretained(client.get())));
|
| -
|
| - // Encoder must pass through states in this order.
|
| - enum ClientState state_transitions[] = {CS_INITIALIZED, CS_ENCODING,
|
| - CS_FINISHED};
|
| -
|
| - for (const auto& state : state_transitions) {
|
| - EXPECT_EQ(state, note->Wait());
|
| - }
|
| -
|
| - encoder_thread.task_runner()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&TestClient::DestroyEncoder, base::Unretained(client.get())));
|
| -
|
| - // This ensures all tasks have finished.
|
| - encoder_thread.Stop();
|
| -}
|
| -
|
| -TEST_P(VideoEncodeAcceleratorSimpleTest, TestSimpleEncode) {
|
| - const int test_type = GetParam();
|
| - ASSERT_LT(test_type, 2) << "Invalid test type=" << test_type;
|
| -
|
| - if (test_type == 0)
|
| - SimpleTestFunc<VEANoInputClient>();
|
| - else if (test_type == 1)
|
| - SimpleTestFunc<VEACacheLineUnalignedInputClient>();
|
| -}
|
| -
|
| #if defined(OS_CHROMEOS)
|
| INSTANTIATE_TEST_CASE_P(
|
| SimpleEncode,
|
| @@ -2192,13 +2049,32 @@
|
| ::testing::Values(
|
| std::make_tuple(1, false, 0, false, false, false, false, false, true)));
|
|
|
| -INSTANTIATE_TEST_CASE_P(NoInputTest,
|
| - VideoEncodeAcceleratorSimpleTest,
|
| - ::testing::Values(0));
|
| -
|
| -INSTANTIATE_TEST_CASE_P(CacheLineUnalignedInputTest,
|
| - VideoEncodeAcceleratorSimpleTest,
|
| - ::testing::Values(1));
|
| +TEST(VEANoInputTest, CheckOutput) {
|
| + std::unique_ptr<ClientStateNotification<ClientState>> note(
|
| + new ClientStateNotification<ClientState>());
|
| + std::unique_ptr<VEANoInputClient> client(new VEANoInputClient(note.get()));
|
| + base::Thread encoder_thread("EncoderThread");
|
| + ASSERT_TRUE(encoder_thread.Start());
|
| +
|
| + encoder_thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&VEANoInputClient::CreateEncoder,
|
| + base::Unretained(client.get())));
|
| +
|
| + // Encoder must pass through states in this order.
|
| + enum ClientState state_transitions[] = {CS_INITIALIZED, CS_ENCODING,
|
| + CS_FINISHED};
|
| +
|
| + for (const auto& state : state_transitions) {
|
| + ASSERT_EQ(state, note->Wait());
|
| + }
|
| +
|
| + encoder_thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&VEANoInputClient::DestroyEncoder,
|
| + base::Unretained(client.get())));
|
| +
|
| + // This ensures all tasks have finished.
|
| + encoder_thread.Stop();
|
| +}
|
|
|
| #elif defined(OS_MACOSX) || defined(OS_WIN)
|
| INSTANTIATE_TEST_CASE_P(
|
|
|