910e62b5创建于 1月15日历史提交
// Copyright 2019 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/gpu/chromeos/image_processor_backend.h"

#include <memory>
#include <ostream>
#include <sstream>

#include "base/functional/bind.h"
#include "base/notimplemented.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "media/gpu/chromeos/video_frame_resource.h"
#include "media/gpu/macros.h"

namespace media {

namespace {

template <class T>
std::string VectorToString(const std::vector<T>& vec) {
  std::ostringstream result;
  std::string delim;
  result << "[";
  for (const T& v : vec) {
    result << delim << v;
    if (delim.size() == 0)
      delim = ", ";
  }
  result << "]";
  return result.str();
}

// Used to adapt FrameResourceReadyCB to FrameReadyCB. The incoming
// FrameResource gets to converted to VideoFrame and passed to |callback|.
void FrameResourceToFrameReadyCB(ImageProcessorBackend::FrameReadyCB callback,
                                 scoped_refptr<FrameResource> frame) {
  VideoFrameResource* video_frame_resource = frame->AsVideoFrameResource();
  // This callback only gets called when |frame| is a VideoFrameResource.
  CHECK(!!video_frame_resource);
  std::move(callback).Run(video_frame_resource->GetMutableVideoFrame());
}

}  // namespace

ImageProcessorBackend::PortConfig::PortConfig(const PortConfig&) = default;

ImageProcessorBackend::PortConfig::PortConfig(
    Fourcc fourcc,
    const gfx::Size& size,
    const std::vector<ColorPlaneLayout>& planes,
    const gfx::Rect& visible_rect,
    VideoFrame::StorageType storage_type)
    : fourcc(fourcc),
      size(size),
      planes(planes),
      visible_rect(visible_rect),
      storage_type(storage_type) {}

ImageProcessorBackend::PortConfig::~PortConfig() = default;

std::string ImageProcessorBackend::PortConfig::ToString() const {
  return base::StringPrintf(
      "PortConfig(format:%s, size:%s, planes: %s, visible_rect:%s, "
      "storage_types:%s)",
      fourcc.ToString().c_str(), size.ToString().c_str(),
      VectorToString(planes).c_str(), visible_rect.ToString().c_str(),
      VideoFrame::StorageTypeToString(storage_type).c_str());
}

ImageProcessorBackend::ImageProcessorBackend(
    const PortConfig& input_config,
    const PortConfig& output_config,
    OutputMode output_mode,
    ErrorCB error_cb,
    scoped_refptr<base::SequencedTaskRunner> backend_task_runner)
    : input_config_(input_config),
      output_config_(output_config),
      output_mode_(output_mode),
      error_cb_(error_cb),
      backend_task_runner_(std::move(backend_task_runner)) {
  DETACH_FROM_SEQUENCE(backend_sequence_checker_);
}

ImageProcessorBackend::~ImageProcessorBackend() = default;

void ImageProcessorBackend::Destroy() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);

  delete this;
}

void ImageProcessorBackend::Process(scoped_refptr<VideoFrame> input_frame,
                                    scoped_refptr<VideoFrame> output_frame,
                                    FrameReadyCB cb) {
  // Wraps ProcessFrame.
  DVLOGF(4);
  DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);
  ProcessFrame(VideoFrameResource::Create(std::move(input_frame)),
               VideoFrameResource::Create(std::move(output_frame)),
               base::BindOnce(&FrameResourceToFrameReadyCB, std::move(cb)));
}

void ImageProcessorBackend::ProcessLegacyFrame(
    scoped_refptr<FrameResource> frame,
    LegacyFrameResourceReadyCB cb) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);

  NOTIMPLEMENTED();
}

void ImageProcessorBackend::Reset() {
  DVLOGF(3);
  DCHECK_CALLED_ON_VALID_SEQUENCE(backend_sequence_checker_);
  // Do nothing as the default action.
}

bool ImageProcessorBackend::needs_linear_output_buffers() const {
  return false;
}

bool ImageProcessorBackend::supports_incoherent_buffers() const {
  return false;
}

}  // namespace media

namespace std {

void default_delete<media::ImageProcessorBackend>::operator()(
    media::ImageProcessorBackend* ptr) const {
  CHECK(ptr->backend_task_runner_);
  if (!ptr->backend_task_runner_->RunsTasksInCurrentSequence()) {
    // base::Unretained() is safe because ImageProcessorBackend::Destroy() *is*
    // the thing that destroys *|ptr|.
    ptr->backend_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&media::ImageProcessorBackend::Destroy,
                                  base::Unretained(ptr)));
    return;
  }
  ptr->Destroy();
}

}  // namespace std