// Copyright (c) 2012 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/ffmpeg_glue.h"

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/synchronization/lock.h"
#include "media/base/container_names.h"
#include "media/ffmpeg/ffmpeg_common.h"

namespace media {

// Internal buffer size used by AVIO for reading.
// TODO(dalecurtis): Experiment with this buffer size and measure impact on
// performance.  Currently we want to use 32kb to preserve existing behavior
// with the previous URLProtocol based approach.
enum { kBufferSize = 32 * 1024 };

static int AVIOReadOperation(void* opaque, uint8_t* buf, int buf_size) {
  FFmpegURLProtocol* protocol = reinterpret_cast<FFmpegURLProtocol*>(opaque);
  int result = protocol->Read(buf_size, buf);
  if (result < 0)
    result = AVERROR(EIO);
  return result;
}

static int64_t AVIOSeekOperation(void* opaque, int64_t offset, int whence) {
  FFmpegURLProtocol* protocol = reinterpret_cast<FFmpegURLProtocol*>(opaque);
  int64_t new_offset = AVERROR(EIO);
  switch (whence) {
    case SEEK_SET:
      if (protocol->SetPosition(offset))
        protocol->GetPosition(&new_offset);
      break;

    case SEEK_CUR:
      int64_t pos;
      if (!protocol->GetPosition(&pos))
        break;
      if (protocol->SetPosition(pos + offset))
        protocol->GetPosition(&new_offset);
      break;

    case SEEK_END:
      int64_t size;
      if (!protocol->GetSize(&size))
        break;
      if (protocol->SetPosition(size + offset))
        protocol->GetPosition(&new_offset);
      break;

    case AVSEEK_SIZE:
      protocol->GetSize(&new_offset);
      break;

    default:
      NOTREACHED();
  }
  if (new_offset < 0)
    new_offset = AVERROR(EIO);
  return new_offset;
}

static int LockManagerOperation(void** lock, enum AVLockOp op) {
  switch (op) {
    case AV_LOCK_CREATE:
      *lock = new base::Lock();
      return 0;

    case AV_LOCK_OBTAIN:
      static_cast<base::Lock*>(*lock)->Acquire();
      return 0;

    case AV_LOCK_RELEASE:
      static_cast<base::Lock*>(*lock)->Release();
      return 0;

    case AV_LOCK_DESTROY:
      delete static_cast<base::Lock*>(*lock);
      *lock = nullptr;
      return 0;
  }
  return 1;
}

// FFmpeg must only be initialized once, so use a LazyInstance to ensure this.
class FFmpegInitializer {
 public:
  bool initialized() { return initialized_; }

 private:
  friend struct base::DefaultLazyInstanceTraits<FFmpegInitializer>;

  FFmpegInitializer()
      : initialized_(false) {
    // Register our protocol glue code with FFmpeg.
    if (av_lockmgr_register(&LockManagerOperation) != 0)
      return;

    // Now register the rest of FFmpeg.
    av_register_all();

    initialized_ = true;
  }

  ~FFmpegInitializer() {
    NOTREACHED() << "FFmpegInitializer should be leaky!";
  }

  bool initialized_;

  DISALLOW_COPY_AND_ASSIGN(FFmpegInitializer);
};

static base::LazyInstance<FFmpegInitializer>::Leaky g_lazy_instance =
    LAZY_INSTANCE_INITIALIZER;
void FFmpegGlue::InitializeFFmpeg() {
  // Get() will invoke the FFmpegInitializer constructor once.
  CHECK(g_lazy_instance.Get().initialized());
}

FFmpegGlue::FFmpegGlue(FFmpegURLProtocol* protocol)
    : open_called_(false) {
  InitializeFFmpeg();

  // Initialize an AVIOContext using our custom read and seek operations.  Don't
  // keep pointers to the buffer since FFmpeg may reallocate it on the fly.  It
  // will be cleaned up
  format_context_ = avformat_alloc_context();
  avio_context_.reset(avio_alloc_context(
      static_cast<unsigned char*>(av_malloc(kBufferSize)), kBufferSize, 0,
      protocol, &AVIOReadOperation, nullptr, &AVIOSeekOperation));

  // Ensure FFmpeg only tries to seek on resources we know to be seekable.
  avio_context_->seekable =
      protocol->IsStreaming() ? 0 : AVIO_SEEKABLE_NORMAL;

  // Ensure writing is disabled.
  avio_context_->write_flag = 0;

  // Tell the format context about our custom IO context.  avformat_open_input()
  // will set the AVFMT_FLAG_CUSTOM_IO flag for us, but do so here to ensure an
  // early error state doesn't cause FFmpeg to free our resources in error.
  format_context_->flags |= AVFMT_FLAG_CUSTOM_IO;

  // Enable fast, but inaccurate seeks for MP3.
  format_context_->flags |= AVFMT_FLAG_FAST_SEEK;

  format_context_->pb = avio_context_.get();
}

bool FFmpegGlue::OpenContext() {
  DCHECK(!open_called_) << "OpenContext() shouldn't be called twice.";

  // If avformat_open_input() is called we have to take a slightly different
  // destruction path to avoid double frees.
  open_called_ = true;

  // Attempt to recognize the container by looking at the first few bytes of the
  // stream. The stream position is left unchanged.
  std::unique_ptr<std::vector<uint8_t>> buffer(new std::vector<uint8_t>(8192));

  int64_t pos = AVIOSeekOperation(avio_context_.get()->opaque, 0, SEEK_CUR);
  AVIOSeekOperation(avio_context_.get()->opaque, 0, SEEK_SET);
  int numRead = AVIOReadOperation(
      avio_context_.get()->opaque, buffer.get()->data(), buffer.get()->size());
  AVIOSeekOperation(avio_context_.get()->opaque, pos, SEEK_SET);
  if (numRead > 0) {
    // < 0 means Read failed
    container_names::MediaContainerName container =
        container_names::DetermineContainer(buffer.get()->data(), numRead);
    UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedContainer", container);
  }

  // By passing nullptr for the filename (second parameter) we are telling
  // FFmpeg to use the AVIO context we setup from the AVFormatContext structure.
  return avformat_open_input(&format_context_, nullptr, nullptr, nullptr) == 0;
}

FFmpegGlue::~FFmpegGlue() {
  // In the event of avformat_open_input() failure, FFmpeg may sometimes free
  // our AVFormatContext behind the scenes, but leave the buffer alive.  It will
  // helpfully set |format_context_| to nullptr in this case.
  if (!format_context_) {
    av_free(avio_context_->buffer);
    return;
  }

  // If avformat_open_input() hasn't been called, we should simply free the
  // AVFormatContext and buffer instead of using avformat_close_input().
  if (!open_called_) {
    avformat_free_context(format_context_);
    av_free(avio_context_->buffer);
    return;
  }

  avformat_close_input(&format_context_);
  av_free(avio_context_->buffer);
}

}  // namespace media
