// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/raspi/shared/open_max/video_decoder.h"

#include "starboard/time.h"

namespace starboard {
namespace raspi {
namespace shared {
namespace open_max {

namespace {

using std::placeholders::_1;

const size_t kResourcePoolSize = 26;
// TODO: Make this configurable inside SbPlayerCreate().
const SbTimeMonotonic kUpdateInterval = 5 * kSbTimeMillisecond;

}  // namespace

VideoDecoder::VideoDecoder(SbMediaVideoCodec video_codec)
    : resource_pool_(new DispmanxResourcePool(kResourcePoolSize)),
      eos_written_(false),
      thread_(kSbThreadInvalid),
      request_thread_termination_(false) {
  SB_DCHECK(video_codec == kSbMediaVideoCodecH264);
  update_job_ = std::bind(&VideoDecoder::Update, this);
  update_job_token_ = Schedule(update_job_, kUpdateInterval);
}

VideoDecoder::~VideoDecoder() {
  if (SbThreadIsValid(thread_)) {
    {
      ScopedLock scoped_lock(mutex_);
      request_thread_termination_ = true;
    }
    SbThreadJoin(thread_, NULL);
  }
  RemoveJobByToken(update_job_token_);
}

void VideoDecoder::Initialize(const DecoderStatusCB& decoder_status_cb,
                              const ErrorCB& error_cb) {
  SB_DCHECK(decoder_status_cb);
  SB_DCHECK(!decoder_status_cb_);
  SB_DCHECK(error_cb);
  SB_DCHECK(!error_cb_);

  decoder_status_cb_ = decoder_status_cb;
  error_cb_ = error_cb;

  SB_DCHECK(!SbThreadIsValid(thread_));
  thread_ = SbThreadCreate(0, kSbThreadPriorityHigh, kSbThreadNoAffinity, true,
                           "omx_video_decoder", &VideoDecoder::ThreadEntryPoint,
                           this);
  SB_DCHECK(SbThreadIsValid(thread_));
}

void VideoDecoder::WriteInputBuffer(
    const scoped_refptr<InputBuffer>& input_buffer) {
  SB_DCHECK(input_buffer);
  SB_DCHECK(decoder_status_cb_);

  queue_.Put(new Event(input_buffer));
  if (!TryToDeliverOneFrame()) {
    SbThreadSleep(kSbTimeMillisecond);
    // Call the callback with NULL frame to ensure that the host know that more
    // data is expected.
    decoder_status_cb_(kNeedMoreInput, NULL);
  }
}

void VideoDecoder::WriteEndOfStream() {
  queue_.Put(new Event(Event::kWriteEOS));
  eos_written_ = true;
}

void VideoDecoder::Reset() {
  queue_.Put(new Event(Event::kReset));
}

void VideoDecoder::Update() {
  if (eos_written_) {
    TryToDeliverOneFrame();
  }
  update_job_token_ = Schedule(update_job_, kUpdateInterval);
}

bool VideoDecoder::TryToDeliverOneFrame() {
  scoped_refptr<VideoFrame> frame;
  {
    ScopedLock scoped_lock(mutex_);
    if (filled_buffers_.empty()) {
      return false;
    }
    OMX_BUFFERHEADERTYPE* buffer = filled_buffers_.front();
    frame = CreateFrame(buffer);
    if (!frame) {
      return false;
    }

    SB_DCHECK(!filled_buffers_.empty());
    filled_buffers_.pop();
    freed_buffers_.push(buffer);
  }
  decoder_status_cb_(kNeedMoreInput, frame);
  return true;
}

// static
void* VideoDecoder::ThreadEntryPoint(void* context) {
  VideoDecoder* decoder = reinterpret_cast<VideoDecoder*>(context);
  decoder->RunLoop();
  return NULL;
}

void VideoDecoder::RunLoop() {
  bool stream_ended = false;
  bool eos_written = false;
  OpenMaxVideoDecodeComponent component;

  component.Start();

  scoped_refptr<InputBuffer> current_buffer;
  int offset = 0;

  for (;;) {
    OMX_BUFFERHEADERTYPE* buffer = NULL;
    {
      ScopedLock scoped_lock(mutex_);

      if (request_thread_termination_) {
        break;
      }
      if (!freed_buffers_.empty()) {
        buffer = freed_buffers_.front();
        freed_buffers_.pop();
      }
    }
    if (buffer != NULL) {
      component.DropOutputBuffer(buffer);
    }

    if (OMX_BUFFERHEADERTYPE* buffer = component.GetOutputBuffer()) {
      ScopedLock scoped_lock(mutex_);
      filled_buffers_.push(buffer);
    }

    if (current_buffer) {
      int size = static_cast<int>(current_buffer->size());
      while (offset < size) {
        int written = component.WriteData(
            current_buffer->data() + offset, size - offset,
            OpenMaxComponent::kDataNonEOS, current_buffer->timestamp());
        SB_DCHECK(written >= 0);
        offset += written;
        if (written == 0) {
          break;
        }
      }
      if (offset == size) {
        current_buffer = NULL;
        offset = 0;
      } else {
        SbThreadSleep(kSbTimeMillisecond);
        continue;
      }
    }

    if (stream_ended && !eos_written) {
      eos_written = component.WriteEOS();
    }

    Event* event = queue_.GetTimed(kSbTimeMillisecond);
    if (event == NULL) {
      continue;
    }

    if (event->type == Event::kWriteInputBuffer) {
      if (stream_ended) {
        SB_LOG(ERROR)
            << "WriteInputFrame() was called after WriteEndOfStream().";
      } else {
        offset = 0;
        current_buffer = event->input_buffer;
      }
    } else if (event->type == Event::kWriteEOS) {
      SB_DCHECK(!stream_ended);
      eos_written = component.WriteEOS();
      stream_ended = true;
    } else if (event->type == Event::kReset) {
      ScopedLock scoped_lock(mutex_);

      while (!freed_buffers_.empty()) {
        component.DropOutputBuffer(freed_buffers_.front());
        freed_buffers_.pop();
      }

      while (!filled_buffers_.empty()) {
        component.DropOutputBuffer(filled_buffers_.front());
        filled_buffers_.pop();
      }

      component.Flush();
      stream_ended = false;
      eos_written = false;
    } else {
      SB_NOTREACHED() << "event type " << event->type;
    }
    delete event;
  }

  while (Event* event = queue_.GetTimed(0)) {
    delete event;
  }

  ScopedLock scoped_lock(mutex_);
  while (!freed_buffers_.empty()) {
    component.DropOutputBuffer(freed_buffers_.front());
    freed_buffers_.pop();
  }

  while (!filled_buffers_.empty()) {
    component.DropOutputBuffer(filled_buffers_.front());
    filled_buffers_.pop();
  }
}

scoped_refptr<VideoDecoder::VideoFrame> VideoDecoder::CreateFrame(
    const OMX_BUFFERHEADERTYPE* buffer) {
  scoped_refptr<VideoFrame> frame;
  if (buffer->nFlags & OMX_BUFFERFLAG_EOS) {
    frame = VideoFrame::CreateEOSFrame();
  } else {
    OMX_VIDEO_PORTDEFINITIONTYPE* video_definition =
        reinterpret_cast<OMX_VIDEO_PORTDEFINITIONTYPE*>(buffer->pAppPrivate);
    DispmanxYUV420Resource* resource = resource_pool_->Alloc(
        video_definition->nStride, video_definition->nSliceHeight,
        video_definition->nFrameWidth, video_definition->nFrameHeight);
    if (!resource) {
      return NULL;
    }

    resource->WriteData(buffer->pBuffer);

    SbTime timestamp = ((buffer->nTimeStamp.nHighPart * 0x100000000ull) +
                        buffer->nTimeStamp.nLowPart);

    resource_pool_->AddRef();
    frame = new DispmanxVideoFrame(
        timestamp, resource,
        std::bind(&DispmanxResourcePool::DisposeDispmanxYUV420Resource,
                  resource_pool_, _1));
  }
  return frame;
}

}  // namespace open_max
}  // namespace shared
}  // namespace raspi
}  // namespace starboard
