// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/fuchsia/video/fuchsia_video_decoder.h"

#include <fuchsia/mediacodec/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <lib/sys/cpp/component_context.h>

#include <memory>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/fuchsia/koid.h"
#include "base/fuchsia/process_context.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/notreached.h"
#include "base/process/process_handle.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/test/test_context_support.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/config/gpu_feature_info.h"
#include "media/base/test_data_util.h"
#include "media/base/test_helpers.h"
#include "media/base/video_decoder.h"
#include "media/base/video_frame.h"
#include "media/mojo/mojom/fuchsia_media.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/client_native_pixmap_factory.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_pixmap_handle.h"

namespace media {

namespace {

class TestBufferCollection {
 public:
  TestBufferCollection(zx::eventpair handle, zx::channel collection_token)
      : handle_(std::move(handle)) {
    sysmem_allocator_ = base::ComponentContextForProcess()
                            ->svc()
                            ->Connect<fuchsia::sysmem::Allocator>();
    sysmem_allocator_.set_error_handler([](zx_status_t status) {
      ZX_LOG(FATAL, status)
          << "The fuchsia.sysmem.Allocator channel was terminated.";
    });
    sysmem_allocator_->SetDebugClientInfo("CrTestBufferCollection",
                                          base::GetCurrentProcId());

    sysmem_allocator_->BindSharedCollection(
        fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken>(
            std::move(collection_token)),
        buffers_collection_.NewRequest());

    fuchsia::sysmem::BufferCollectionConstraints buffer_constraints;
    buffer_constraints.usage.cpu = fuchsia::sysmem::cpuUsageRead;
    zx_status_t status = buffers_collection_->SetConstraints(
        /*has_constraints=*/true, std::move(buffer_constraints));
    ZX_CHECK(status == ZX_OK, status) << "BufferCollection::SetConstraints()";
  }

  TestBufferCollection(const TestBufferCollection&) = delete;
  TestBufferCollection& operator=(const TestBufferCollection&) = delete;

  ~TestBufferCollection() { buffers_collection_->Close(); }

  size_t GetNumBuffers() {
    if (!buffer_collection_info_) {
      zx_status_t wait_status;
      fuchsia::sysmem::BufferCollectionInfo_2 info;
      zx_status_t status =
          buffers_collection_->WaitForBuffersAllocated(&wait_status, &info);
      ZX_CHECK(status == ZX_OK, status)
          << "BufferCollection::WaitForBuffersAllocated()";
      ZX_CHECK(wait_status == ZX_OK, wait_status)
          << "BufferCollection::WaitForBuffersAllocated()";
      buffer_collection_info_ = std::move(info);
    }
    return buffer_collection_info_->buffer_count;
  }

 private:
  zx::eventpair handle_;

  fuchsia::sysmem::AllocatorPtr sysmem_allocator_;
  fuchsia::sysmem::BufferCollectionSyncPtr buffers_collection_;

  absl::optional<fuchsia::sysmem::BufferCollectionInfo_2>
      buffer_collection_info_;
};

class TestSharedImageInterface : public gpu::SharedImageInterface {
 public:
  TestSharedImageInterface() = default;
  ~TestSharedImageInterface() override = default;

  gpu::Mailbox CreateSharedImage(viz::SharedImageFormat format,
                                 const gfx::Size& size,
                                 const gfx::ColorSpace& color_space,
                                 GrSurfaceOrigin surface_origin,
                                 SkAlphaType alpha_type,
                                 uint32_t usage,
                                 base::StringPiece debug_label,
                                 gpu::SurfaceHandle surface_handle) override {
    ADD_FAILURE();
    return gpu::Mailbox();
  }

  gpu::Mailbox CreateSharedImage(
      viz::SharedImageFormat format,
      const gfx::Size& size,
      const gfx::ColorSpace& color_space,
      GrSurfaceOrigin surface_origin,
      SkAlphaType alpha_type,
      uint32_t usage,
      base::StringPiece debug_label,
      base::span<const uint8_t> pixel_data) override {
    ADD_FAILURE();
    return gpu::Mailbox();
  }

  gpu::Mailbox CreateSharedImage(
      viz::SharedImageFormat format,
      const gfx::Size& size,
      const gfx::ColorSpace& color_space,
      GrSurfaceOrigin surface_origin,
      SkAlphaType alpha_type,
      uint32_t usage,
      base::StringPiece debug_label,
      gfx::GpuMemoryBufferHandle buffer_handle) override {
    ADD_FAILURE();
    return gpu::Mailbox();
  }

  gpu::Mailbox CreateSharedImage(
      gfx::GpuMemoryBuffer* gpu_memory_buffer,
      gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
      gfx::BufferPlane plane,
      const gfx::ColorSpace& color_space,
      GrSurfaceOrigin surface_origin,
      SkAlphaType alpha_type,
      uint32_t usage,
      base::StringPiece debug_label) override {
    gfx::GpuMemoryBufferHandle handle = gpu_memory_buffer->CloneHandle();
    CHECK_EQ(handle.type, gfx::GpuMemoryBufferType::NATIVE_PIXMAP);

    zx_koid_t id = base::GetRelatedKoid(
                       handle.native_pixmap_handle.buffer_collection_handle)
                       .value();
    auto collection_it = sysmem_buffer_collections_.find(id);
    CHECK(collection_it != sysmem_buffer_collections_.end());
    CHECK_LT(handle.native_pixmap_handle.buffer_index,
             collection_it->second->GetNumBuffers());

    auto result = gpu::Mailbox::GenerateForSharedImage();
    mailboxes_.insert(result);
    return result;
  }

  void UpdateSharedImage(const gpu::SyncToken& sync_token,
                         const gpu::Mailbox& mailbox) override {
    ADD_FAILURE();
  }
  void UpdateSharedImage(const gpu::SyncToken& sync_token,
                         std::unique_ptr<gfx::GpuFence> acquire_fence,
                         const gpu::Mailbox& mailbox) override {
    ADD_FAILURE();
  }

  void AddReferenceToSharedImage(const gpu::SyncToken& sync_token,
                                 const gpu::Mailbox& mailbox,
                                 uint32_t usage) override {
    ADD_FAILURE();
  }

  void DestroySharedImage(const gpu::SyncToken& sync_token,
                          const gpu::Mailbox& mailbox) override {
    CHECK_EQ(mailboxes_.erase(mailbox), 1U);
  }

  SwapChainMailboxes CreateSwapChain(viz::SharedImageFormat format,
                                     const gfx::Size& size,
                                     const gfx::ColorSpace& color_space,
                                     GrSurfaceOrigin surface_origin,
                                     SkAlphaType alpha_type,
                                     uint32_t usage) override {
    ADD_FAILURE();
    return SwapChainMailboxes();
  }
  void PresentSwapChain(const gpu::SyncToken& sync_token,
                        const gpu::Mailbox& mailbox) override {
    ADD_FAILURE();
  }

  void RegisterSysmemBufferCollection(zx::eventpair handle,
                                      zx::channel token,
                                      gfx::BufferFormat format,
                                      gfx::BufferUsage usage,
                                      bool register_with_image_pipe) override {
    EXPECT_EQ(format, gfx::BufferFormat::YUV_420_BIPLANAR);
    EXPECT_EQ(usage, gfx::BufferUsage::GPU_READ);
    zx_koid_t id = base::GetKoid(handle).value();
    std::unique_ptr<TestBufferCollection>& collection =
        sysmem_buffer_collections_[id];
    EXPECT_FALSE(collection);
    collection = std::make_unique<TestBufferCollection>(std::move(handle),
                                                        std::move(token));
  }

  gpu::SyncToken GenVerifiedSyncToken() override {
    gpu::SyncToken token(gpu::CommandBufferNamespace::GPU_IO,
                         gpu::CommandBufferId(33), 1);
    token.SetVerifyFlush();
    return token;
  }

  gpu::SyncToken GenUnverifiedSyncToken() override {
    ADD_FAILURE();
    return gpu::SyncToken();
  }

  void WaitSyncToken(const gpu::SyncToken& sync_token) override {
    ADD_FAILURE();
  }

  void Flush() override { ADD_FAILURE(); }

  scoped_refptr<gfx::NativePixmap> GetNativePixmap(
      const gpu::Mailbox& mailbox) override {
    return nullptr;
  }

 private:
  base::flat_map<zx_koid_t, std::unique_ptr<TestBufferCollection>>
      sysmem_buffer_collections_;

  base::flat_set<gpu::Mailbox> mailboxes_;
};

class TestRasterContextProvider
    : public base::RefCountedThreadSafe<TestRasterContextProvider>,
      public viz::RasterContextProvider {
 public:
  TestRasterContextProvider() {}

  TestRasterContextProvider(TestRasterContextProvider&) = delete;
  TestRasterContextProvider& operator=(TestRasterContextProvider&) = delete;

  void SetOnDestroyedClosure(base::OnceClosure on_destroyed) {
    on_destroyed_ = std::move(on_destroyed);
  }

  // viz::RasterContextProvider implementation;
  void AddRef() const override {
    base::RefCountedThreadSafe<TestRasterContextProvider>::AddRef();
  }
  void Release() const override {
    base::RefCountedThreadSafe<TestRasterContextProvider>::Release();
  }
  gpu::ContextResult BindToCurrentSequence() override {
    ADD_FAILURE();
    return gpu::ContextResult::kFatalFailure;
  }
  void AddObserver(viz::ContextLostObserver* obs) override { ADD_FAILURE(); }
  void RemoveObserver(viz::ContextLostObserver* obs) override { ADD_FAILURE(); }
  base::Lock* GetLock() override {
    ADD_FAILURE();
    return nullptr;
  }
  viz::ContextCacheController* CacheController() override {
    ADD_FAILURE();
    return nullptr;
  }
  gpu::ContextSupport* ContextSupport() override {
    return &gpu_context_support_;
  }
  class GrDirectContext* GrContext() override {
    ADD_FAILURE();
    return nullptr;
  }
  gpu::SharedImageInterface* SharedImageInterface() override {
    return &shared_image_interface_;
  }
  const gpu::Capabilities& ContextCapabilities() const override {
    ADD_FAILURE();
    static gpu::Capabilities dummy_caps;
    return dummy_caps;
  }
  const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override {
    ADD_FAILURE();
    static gpu::GpuFeatureInfo dummy_feature_info;
    return dummy_feature_info;
  }
  gpu::gles2::GLES2Interface* ContextGL() override {
    ADD_FAILURE();
    return nullptr;
  }
  gpu::raster::RasterInterface* RasterInterface() override {
    ADD_FAILURE();
    return nullptr;
  }

 private:
  friend class base::RefCountedThreadSafe<TestRasterContextProvider>;

  ~TestRasterContextProvider() override {
    if (on_destroyed_)
      std::move(on_destroyed_).Run();
  }

  TestSharedImageInterface shared_image_interface_;
  viz::TestContextSupport gpu_context_support_;

  base::OnceClosure on_destroyed_;
};

class TestFuchsiaMediaCodecProvider
    : public media::mojom::FuchsiaMediaCodecProvider {
 public:
  // media::mojom::FuchsiaMediaCodecProvider implementation.
  void CreateVideoDecoder(
      media::VideoCodec codec,
      media::mojom::VideoDecoderSecureMemoryMode secure_mode,
      fidl::InterfaceRequest<fuchsia::media::StreamProcessor>
          stream_processor_request) final {
    EXPECT_TRUE(secure_mode ==
                media::mojom::VideoDecoderSecureMemoryMode::CLEAR);

    fuchsia::mediacodec::CreateDecoder_Params decoder_params;
    decoder_params.mutable_input_details()->set_format_details_version_ordinal(
        0);

    switch (codec) {
      case VideoCodec::kH264:
        decoder_params.mutable_input_details()->set_mime_type("video/h264");
        break;
      case VideoCodec::kVP9:
        decoder_params.mutable_input_details()->set_mime_type("video/vp9");
        break;

      default:
        ADD_FAILURE() << "CreateVideoDecoder() called with unexpected codec: "
                      << static_cast<int>(codec);
        return;
    }

    decoder_params.set_promise_separate_access_units_on_input(true);
    decoder_params.set_require_hw(false);

    auto decoder_factory = base::ComponentContextForProcess()
                               ->svc()
                               ->Connect<fuchsia::mediacodec::CodecFactory>();
    decoder_factory->CreateDecoder(std::move(decoder_params),
                                   std::move(stream_processor_request));
  }

  void GetSupportedVideoDecoderConfigs(
      GetSupportedVideoDecoderConfigsCallback callback) override {
    ADD_FAILURE();
  }

  mojo::Receiver<media::mojom::FuchsiaMediaCodecProvider> receiver_{this};
};

class FakeClientNativePixmap : public gfx::ClientNativePixmap {
 public:
  FakeClientNativePixmap(gfx::NativePixmapHandle handle)
      : handle_(std::move(handle)) {
    CHECK(handle_.buffer_collection_handle);
  }

  ~FakeClientNativePixmap() override = default;

  // gfx::ClientNativePixmap implementation.
  bool Map() override {
    NOTREACHED();
    return false;
  }
  void Unmap() override { NOTREACHED(); }
  size_t GetNumberOfPlanes() const override {
    NOTREACHED();
    return 0;
  }
  void* GetMemoryAddress(size_t plane) const override {
    NOTREACHED();
    return nullptr;
  }
  int GetStride(size_t plane) const override {
    NOTREACHED();
    return 0;
  }
  gfx::NativePixmapHandle CloneHandleForIPC() const override {
    return gfx::CloneHandleForIPC(handle_);
  }

 private:
  gfx::NativePixmapHandle handle_;
};

class FakeClientNativePixmapFactory : public gfx::ClientNativePixmapFactory {
 public:
  FakeClientNativePixmapFactory() = default;
  ~FakeClientNativePixmapFactory() override = default;

  std::unique_ptr<gfx::ClientNativePixmap> ImportFromHandle(
      gfx::NativePixmapHandle handle,
      const gfx::Size& size,
      gfx::BufferFormat format,
      gfx::BufferUsage usage) override {
    return std::make_unique<FakeClientNativePixmap>(std::move(handle));
  }
};

}  // namespace

class FuchsiaVideoDecoderTest : public testing::Test {
 public:
  FuchsiaVideoDecoderTest()
      : raster_context_provider_(
            base::MakeRefCounted<TestRasterContextProvider>()) {
    auto decoder = std::make_unique<FuchsiaVideoDecoder>(
        raster_context_provider_.get(),
        mojo::SharedRemote<media::mojom::FuchsiaMediaCodecProvider>(
            test_media_codec_provider_.receiver_.BindNewPipeAndPassRemote()),
        /*allow_overlays=*/false);
    decoder->SetClientNativePixmapFactoryForTests(
        std::make_unique<FakeClientNativePixmapFactory>());
    decoder_ = std::move(decoder);
  }

  FuchsiaVideoDecoderTest(const FuchsiaVideoDecoderTest&) = delete;
  FuchsiaVideoDecoderTest& operator=(const FuchsiaVideoDecoderTest&) = delete;

  ~FuchsiaVideoDecoderTest() override {
    // The decoder uses async destruction callbacks for VideoFrames, so we need
    // to run the message loop after releasing the frames to avoid memory leaks
    // (see crbug.com/1287362).
    output_frames_.clear();
    task_environment_.RunUntilIdle();
  }

  [[nodiscard]] bool InitializeDecoder(VideoDecoderConfig config) {
    base::RunLoop run_loop;
    bool init_cb_result = false;
    decoder_->Initialize(
        config, true, /*cdm_context=*/nullptr,
        base::BindRepeating(
            [](bool* init_cb_result, base::RunLoop* run_loop,
               DecoderStatus status) {
              *init_cb_result = status.is_ok();
              run_loop->Quit();
            },
            &init_cb_result, &run_loop),
        base::BindRepeating(&FuchsiaVideoDecoderTest::OnVideoFrame,
                            weak_factory_.GetWeakPtr()),
        base::DoNothing());

    run_loop.Run();
    return init_cb_result;
  }

  void ResetDecoder() {
    base::RunLoop run_loop;
    decoder_->Reset(base::BindRepeating(
        [](base::RunLoop* run_loop) { run_loop->Quit(); }, &run_loop));
    run_loop.Run();
  }

  void OnVideoFrame(scoped_refptr<VideoFrame> frame) {
    num_output_frames_++;
    CHECK(frame->HasTextures());
    output_frames_.push_back(std::move(frame));
    while (output_frames_.size() > frames_to_keep_) {
      output_frames_.pop_front();
    }
    if (run_loop_)
      run_loop_->Quit();
  }

  void DecodeBuffer(scoped_refptr<DecoderBuffer> buffer) {
    decoder_->Decode(
        buffer,
        base::BindRepeating(&FuchsiaVideoDecoderTest::OnFrameDecoded,
                            weak_factory_.GetWeakPtr(), num_input_buffers_));
    num_input_buffers_ += 1;
  }

  void ReadAndDecodeFrame(const std::string& name) {
    DecodeBuffer(ReadTestDataFile(name));
  }

  void OnFrameDecoded(size_t frame_pos, DecoderStatus status) {
    EXPECT_EQ(frame_pos, num_decoded_buffers_);
    num_decoded_buffers_ += 1;
    last_decode_status_ = std::move(status);
    if (run_loop_)
      run_loop_->Quit();
  }

  // Waits until all pending decode requests are finished.
  void WaitDecodeDone() {
    size_t target_pos = num_input_buffers_;
    while (num_decoded_buffers_ < target_pos) {
      base::RunLoop run_loop;
      run_loop_ = &run_loop;
      run_loop.Run();
      run_loop_ = nullptr;
      ASSERT_TRUE(last_decode_status_.is_ok());
    }
  }

 protected:
  base::test::SingleThreadTaskEnvironment task_environment_{
      base::test::SingleThreadTaskEnvironment::MainThreadType::IO};

  TestFuchsiaMediaCodecProvider test_media_codec_provider_;

  scoped_refptr<TestRasterContextProvider> raster_context_provider_;

  std::unique_ptr<VideoDecoder> decoder_;

  size_t num_input_buffers_ = 0;

  // Number of frames for which DecodeCB has been called. That doesn't mean
  // we've received corresponding output frames.
  size_t num_decoded_buffers_ = 0;

  std::list<scoped_refptr<VideoFrame>> output_frames_;
  size_t num_output_frames_ = 0;

  DecoderStatus last_decode_status_;
  base::RunLoop* run_loop_ = nullptr;

  // Number of frames that OnVideoFrame() should keep in |output_frames_|.
  size_t frames_to_keep_ = 2;

  base::WeakPtrFactory<FuchsiaVideoDecoderTest> weak_factory_{this};
};

scoped_refptr<DecoderBuffer> GetH264Frame(size_t frame_num) {
  static scoped_refptr<DecoderBuffer> frames[] = {
      ReadTestDataFile("h264-320x180-frame-0"),
      ReadTestDataFile("h264-320x180-frame-1"),
      ReadTestDataFile("h264-320x180-frame-2"),
      ReadTestDataFile("h264-320x180-frame-3")};
  CHECK_LT(frame_num, std::size(frames));
  return frames[frame_num];
}

TEST_F(FuchsiaVideoDecoderTest, CreateAndDestroy) {}

TEST_F(FuchsiaVideoDecoderTest, CreateInitDestroy) {
  EXPECT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
}

TEST_F(FuchsiaVideoDecoderTest, DISABLED_VP9) {
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::Normal(VideoCodec::kVP9)));

  DecodeBuffer(ReadTestDataFile("vp9-I-frame-320x240"));
  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  EXPECT_EQ(num_output_frames_, 1U);
}

TEST_F(FuchsiaVideoDecoderTest, H264) {
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));

  DecodeBuffer(GetH264Frame(0));
  DecodeBuffer(GetH264Frame(1));
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  DecodeBuffer(GetH264Frame(2));
  DecodeBuffer(GetH264Frame(3));
  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  EXPECT_EQ(num_output_frames_, 4U);
}

// Verify that the decoder can be re-initialized while there pending decode
// requests.
TEST_F(FuchsiaVideoDecoderTest, ReinitializeH264) {
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
  DecodeBuffer(GetH264Frame(0));
  DecodeBuffer(GetH264Frame(1));
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  num_output_frames_ = 0;

  // Re-initialize decoder and send the same data again.
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
  DecodeBuffer(GetH264Frame(0));
  DecodeBuffer(GetH264Frame(1));
  DecodeBuffer(GetH264Frame(2));
  DecodeBuffer(GetH264Frame(3));
  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  EXPECT_EQ(num_output_frames_, 4U);
}

// Verify that the decoder can be re-initialized after Reset().
TEST_F(FuchsiaVideoDecoderTest, ResetAndReinitializeH264) {
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
  DecodeBuffer(GetH264Frame(0));
  DecodeBuffer(GetH264Frame(1));
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  ResetDecoder();

  num_output_frames_ = 0;

  // Re-initialize decoder and send the same data again.
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
  DecodeBuffer(GetH264Frame(0));
  DecodeBuffer(GetH264Frame(1));
  DecodeBuffer(GetH264Frame(2));
  DecodeBuffer(GetH264Frame(3));
  DecodeBuffer(DecoderBuffer::CreateEOSBuffer());
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  EXPECT_EQ(num_output_frames_, 4U);
}

// Verifies that the decoder keeps reference to the RasterContextProvider.
TEST_F(FuchsiaVideoDecoderTest, RasterContextLifetime) {
  bool context_destroyed = false;
  raster_context_provider_->SetOnDestroyedClosure(base::BindLambdaForTesting(
      [&context_destroyed]() { context_destroyed = true; }));
  ASSERT_TRUE(InitializeDecoder(TestVideoConfig::NormalH264()));
  ASSERT_FALSE(context_destroyed);

  // Decoder should keep reference to RasterContextProvider.
  raster_context_provider_.reset();
  ASSERT_FALSE(context_destroyed);

  // Feed some frames to decoder to get decoded video frames.
  for (int i = 0; i < 4; ++i) {
    DecodeBuffer(GetH264Frame(i));
  }
  ASSERT_NO_FATAL_FAILURE(WaitDecodeDone());

  // Destroy the decoder. RasterContextProvider will not be destroyed since
  // it's still referenced by frames in |output_frames_|.
  decoder_.reset();
  task_environment_.RunUntilIdle();
  ASSERT_FALSE(context_destroyed);

  // RasterContextProvider reference should be dropped once all frames are
  // dropped.
  output_frames_.clear();
  task_environment_.RunUntilIdle();
  ASSERT_TRUE(context_destroyed);
}

}  // namespace media
