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

#include "media/filters/offloading_video_decoder.h"

#include "base/bind_helpers.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/atomic_flag.h"
#include "base/task_scheduler/post_task.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_frame.h"

namespace media {

// Helper class which manages cancellation of Decode() after Reset() and makes
// it easier to destruct on the proper thread.
class CancellationHelper {
 public:
  CancellationHelper(std::unique_ptr<OffloadableVideoDecoder> decoder)
      : cancellation_flag_(std::make_unique<base::AtomicFlag>()),
        decoder_(std::move(decoder)) {}

  // Safe to call from any thread.
  void Cancel() { cancellation_flag_->Set(); }

  void Decode(scoped_refptr<DecoderBuffer> buffer,
              const VideoDecoder::DecodeCB& decode_cb) {
    if (cancellation_flag_->IsSet()) {
      decode_cb.Run(DecodeStatus::ABORTED);
      return;
    }

    decoder_->Decode(std::move(buffer), decode_cb);
  }

  void Reset(const base::Closure& reset_cb) {
    // OffloadableVideoDecoders are required to have a synchronous Reset(), so
    // we don't need to wait for the Reset to complete. Despite this, we don't
    // want to run |reset_cb| before we've reset the cancellation flag or the
    // client may end up issuing another Reset() before this code runs.
    decoder_->Reset(base::DoNothing());
    cancellation_flag_.reset(new base::AtomicFlag());
    reset_cb.Run();
  }

  OffloadableVideoDecoder* decoder() const { return decoder_.get(); }

 private:
  std::unique_ptr<base::AtomicFlag> cancellation_flag_;
  std::unique_ptr<OffloadableVideoDecoder> decoder_;

  DISALLOW_COPY_AND_ASSIGN(CancellationHelper);
};

OffloadingVideoDecoder::OffloadingVideoDecoder(
    int min_offloading_width,
    std::vector<VideoCodec> supported_codecs,
    std::unique_ptr<OffloadableVideoDecoder> decoder)
    : min_offloading_width_(min_offloading_width),
      supported_codecs_(std::move(supported_codecs)),
      helper_(std::make_unique<CancellationHelper>(std::move(decoder))),
      weak_factory_(this) {
  DETACH_FROM_THREAD(thread_checker_);
}

OffloadingVideoDecoder::~OffloadingVideoDecoder() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // The |helper_| must always be destroyed on the |offload_task_runner_| since
  // we may still have tasks posted to it.
  if (offload_task_runner_)
    offload_task_runner_->DeleteSoon(FROM_HERE, std::move(helper_));
}

std::string OffloadingVideoDecoder::GetDisplayName() const {
  // This call is expected to be static and safe to call from any thread.
  return helper_->decoder()->GetDisplayName();
}

void OffloadingVideoDecoder::Initialize(
    const VideoDecoderConfig& config,
    bool low_delay,
    CdmContext* cdm_context,
    const InitCB& init_cb,
    const OutputCB& output_cb,
    const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(config.IsValidConfig());

  const bool disable_offloading =
      config.is_encrypted() ||
      config.coded_size().width() < min_offloading_width_ ||
      std::find(supported_codecs_.begin(), supported_codecs_.end(),
                config.codec()) == supported_codecs_.end();

  if (initialized_) {
    initialized_ = false;

    // We're transitioning from offloading to no offloading, so detach from the
    // offloading thread so we can run on the media thread.
    if (disable_offloading && offload_task_runner_) {
      offload_task_runner_->PostTaskAndReply(
          FROM_HERE,
          base::BindOnce(&OffloadableVideoDecoder::Detach,
                         base::Unretained(helper_->decoder())),
          // We must trampoline back trough OffloadingVideoDecoder because it's
          // possible for this class to be destroyed during Initialize().
          base::BindOnce(&OffloadingVideoDecoder::Initialize,
                         weak_factory_.GetWeakPtr(), config, low_delay,
                         cdm_context, init_cb, output_cb,
                         waiting_for_decryption_key_cb));
      return;
    }

    // We're transitioning from no offloading to offloading, so detach from the
    // media thread so we can run on the offloading thread.
    if (!disable_offloading && !offload_task_runner_)
      helper_->decoder()->Detach();
  }

  DCHECK(!initialized_);
  initialized_ = true;

  // Offloaded decoders expect asynchronous execution of callbacks; even if we
  // aren't currently using the offload thread.
  InitCB bound_init_cb = BindToCurrentLoop(init_cb);
  OutputCB bound_output_cb = BindToCurrentLoop(output_cb);

  // If we're not offloading just pass through to the wrapped decoder.
  if (disable_offloading) {
    offload_task_runner_ = nullptr;
    helper_->decoder()->Initialize(config, low_delay, cdm_context,
                                   bound_init_cb, bound_output_cb,
                                   waiting_for_decryption_key_cb);
    return;
  }

  if (!offload_task_runner_) {
    offload_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
        {base::TaskPriority::USER_BLOCKING});
  }

  offload_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&OffloadableVideoDecoder::Initialize,
                     base::Unretained(helper_->decoder()), config, low_delay,
                     cdm_context, bound_init_cb, bound_output_cb,
                     waiting_for_decryption_key_cb));
}

void OffloadingVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
                                    const DecodeCB& decode_cb) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(buffer);
  DCHECK(!decode_cb.is_null());

  DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb);
  if (!offload_task_runner_) {
    helper_->decoder()->Decode(std::move(buffer), bound_decode_cb);
    return;
  }

  offload_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CancellationHelper::Decode,
                                base::Unretained(helper_.get()),
                                std::move(buffer), bound_decode_cb));
}

void OffloadingVideoDecoder::Reset(const base::Closure& reset_cb) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  base::Closure bound_reset_cb = BindToCurrentLoop(reset_cb);
  if (!offload_task_runner_) {
    helper_->Reset(bound_reset_cb);
  } else {
    helper_->Cancel();
    offload_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&CancellationHelper::Reset,
                       base::Unretained(helper_.get()), bound_reset_cb));
  }
}

int OffloadingVideoDecoder::GetMaxDecodeRequests() const {
  // If we're offloading, try to parallelize decodes as well. Take care when
  // adjusting this number as it may dramatically increase memory usage and
  // reduce seek times. See http://crbug.com/731841.
  //
  // The current value of 2 was determined via experimental adjustment until a
  // 4K60 VP9 playback dropped zero frames.
  return offload_task_runner_ ? 2 : 1;
}

}  // namespace media
