// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "encoder/win/video_sink_filter.h"

#include <dvdmedia.h>
#include <vfwmsgs.h>

#include "encoder/win/dshow_util.h"
#include "encoder/win/media_source_dshow.h"
#include "encoder/win/media_type_dshow.h"
#include "encoder/win/webm_guids.h"
#include "glog/logging.h"

namespace webmlive {

///////////////////////////////////////////////////////////////////////////////
// VideoSinkPin
//

VideoSinkPin::VideoSinkPin(TCHAR* ptr_object_name,
                           VideoSinkFilter* ptr_filter,
                           CCritSec* ptr_filter_lock,
                           HRESULT* ptr_result,
                           LPCWSTR ptr_pin_name)
    : CBaseInputPin(ptr_object_name,
                    ptr_filter,
                    ptr_filter_lock,
                    ptr_result,
                    ptr_pin_name) {
}

VideoSinkPin::~VideoSinkPin() {
}

// Returns preferred media type.
HRESULT VideoSinkPin::GetMediaType(int32 type_index,
                                   CMediaType* ptr_media_type) {
  if (type_index < 0 || !ptr_media_type) {
    return E_INVALIDARG;
  }
  if (type_index > 1) {
    return VFW_S_NO_MORE_ITEMS;
  }
  VIDEOINFOHEADER* const ptr_video_info =
      reinterpret_cast<VIDEOINFOHEADER*>(
          ptr_media_type->AllocFormatBuffer(sizeof(VIDEOINFOHEADER)));
  if (!ptr_video_info) {
    LOG(ERROR) << "VIDEOINFOHEADER alloc failed.";
    return E_OUTOFMEMORY;
  }
  ZeroMemory(ptr_video_info, sizeof(VIDEOINFOHEADER));
  ptr_video_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

  // Use empty source/dest rectangle-- the entire image is needed, and there is
  // no target subrect.
  SetRectEmpty(&ptr_video_info->rcSource);
  SetRectEmpty(&ptr_video_info->rcTarget);

  // Set values for all input types supported.
  ptr_media_type->SetType(&MEDIATYPE_Video);
  ptr_media_type->SetFormatType(&FORMAT_VideoInfo);
  ptr_media_type->SetTemporalCompression(FALSE);
  ptr_video_info->bmiHeader.biPlanes = 1;

  if (requested_config_.width != 0)
    ptr_video_info->bmiHeader.biWidth = requested_config_.width;
  if (requested_config_.height != 0)
    ptr_video_info->bmiHeader.biHeight = requested_config_.height;

  if (type_index == 0) {
    // Set sub type and format data for I420.
    ptr_video_info->bmiHeader.biCompression = MAKEFOURCC('I', '4', '2', '0');
    ptr_video_info->bmiHeader.biBitCount = kI420BitCount;
    ptr_media_type->SetSubtype(&MEDIASUBTYPE_I420);
  } else {
    // Set sub type and format data for YV12.
    ptr_video_info->bmiHeader.biCompression = MAKEFOURCC('Y', 'V', '1', '2');
    ptr_video_info->bmiHeader.biBitCount = kYV12BitCount;
    ptr_media_type->SetSubtype(&MEDIASUBTYPE_YV12);
  }

  // Set sample size.
  ptr_video_info->bmiHeader.biSizeImage = DIBSIZE(ptr_video_info->bmiHeader);
  ptr_media_type->SetSampleSize(ptr_video_info->bmiHeader.biSizeImage);
  LOG(INFO) << "\n GetMediaType type_index=" << type_index << "\n"
            << "   width=" << ptr_video_info->bmiHeader.biWidth << "\n"
            << "   height=" << ptr_video_info->bmiHeader.biHeight << "\n"
            << std::hex << "   biCompression="
            << ptr_video_info->bmiHeader.biCompression;
  return S_OK;
}

const BITMAPINFOHEADER* BitmapInfo(const GUID& format_guid,
                                   const uint8* ptr_format_blob,
                                   uint32 format_length) {
  const BITMAPINFOHEADER* ptr_header = NULL;
  if (ptr_format_blob) {
    if (format_guid == FORMAT_VideoInfo &&
        format_length >= sizeof(VIDEOINFOHEADER)) {
      const VIDEOINFOHEADER* ptr_video_info =
          reinterpret_cast<const VIDEOINFOHEADER*>(ptr_format_blob);
      ptr_header = &ptr_video_info->bmiHeader;
    } else if (format_guid == FORMAT_VideoInfo2 &&
               format_length >= sizeof(VIDEOINFOHEADER2)) {
      const VIDEOINFOHEADER2* ptr_video_info =
          reinterpret_cast<const VIDEOINFOHEADER2*>(ptr_format_blob);
      ptr_header = &ptr_video_info->bmiHeader;
    }
  }
  return ptr_header;
}

// Confirms that |ptr_media_type| is VIDEOINFOHEADER or VIDEOINFOHEADER2 and
// has a subtype of MEDIASUBTYPE_I420.
HRESULT VideoSinkPin::CheckMediaType(const CMediaType* ptr_media_type) {
  // Confirm media type is acceptable.
  const GUID* const ptr_type_guid = ptr_media_type->Type();
  if (!ptr_type_guid || *ptr_type_guid != MEDIATYPE_Video) {
    return VFW_E_TYPE_NOT_ACCEPTED;
  }

  // Confirm that subtype and formattype GUIDs can be obtained.
  const GUID* const ptr_subtype_guid = ptr_media_type->Subtype();
  const GUID* const ptr_format_guid = ptr_media_type->FormatType();
  if (!ptr_subtype_guid || !ptr_format_guid) {
      return E_INVALIDARG;
  }

  const GUID& format_guid = *ptr_format_guid;
  const GUID& subtype_guid = *ptr_subtype_guid;

  // Confirm that the subtype is acceptable.
  if (!AcceptableSubType(subtype_guid)) {
    return VFW_E_TYPE_NOT_ACCEPTED;
  }

  // Obtain access to the BITMAPINFOHEADER, and confirm that the video format
  // is acceptable.
  const uint8* ptr_format = ptr_media_type->Format();
  const uint32 format_length = ptr_media_type->FormatLength();
  const BITMAPINFOHEADER* ptr_header =
      BitmapInfo(format_guid, ptr_format, format_length);
  if (ptr_header) {
    if (FourCCToVideoFormat(ptr_header->biCompression,
                            ptr_header->biBitCount,
                            &actual_config_.format)) {
      // |ptr_media_type| contains a video frame with a pixel format that is
      // acceptable-- store format information.
      actual_config_.width = ptr_header->biWidth;
      actual_config_.height = ptr_header->biHeight;

      // Store the stride for use with |VideoFrame::Init()|-- it's needed for
      // format conversion.
      actual_config_.stride = DIBWIDTHBYTES(*ptr_header);
    }
  }

  LOG(INFO) << "\n CheckMediaType actual video settings\n"
            << "   width=" << actual_config_.width << "\n"
            << "   height=" << actual_config_.height << "\n"
            << "   stride=" << actual_config_.stride << "\n"
            << "   format=" << actual_config_.format;
  return S_OK;
}

// Calls CBaseInputPin::Receive and then passes |ptr_sample| to
// |VideoSinkFilter::OnFrameReceived|.
HRESULT VideoSinkPin::Receive(IMediaSample* ptr_sample) {
  CHECK_NOTNULL(m_pFilter);
  CHECK_NOTNULL(ptr_sample);
  VideoSinkFilter* ptr_filter = reinterpret_cast<VideoSinkFilter*>(m_pFilter);
  CAutoLock lock(&ptr_filter->filter_lock_);
  HRESULT hr = CBaseInputPin::Receive(ptr_sample);
  if (FAILED(hr)) {
    if (hr != VFW_E_WRONG_STATE) {
      // Log the error only when it is not |VFW_E_WRONG_STATE|. The filter
      // graph appears to always call |Receive()| once after |Stop()|.
      LOG(ERROR) << "CBaseInputPin::Receive failed. " << HRLOG(hr);
    }
    return hr;
  }
  hr = ptr_filter->OnFrameReceived(ptr_sample);
  if (FAILED(hr)) {
    LOG(ERROR) << "OnFrameReceived failed. " << HRLOG(hr);
  }
  return S_OK;
}

bool VideoSinkPin::AcceptableSubType(const GUID& media_sub_type) {
  return (media_sub_type == MEDIASUBTYPE_I420 ||
          media_sub_type == MEDIASUBTYPE_YV12 ||
          media_sub_type == MEDIASUBTYPE_YUY2 ||
          media_sub_type == MEDIASUBTYPE_YUYV ||
          media_sub_type == MEDIASUBTYPE_UYVY ||
          media_sub_type == MEDIASUBTYPE_RGB24 ||
          media_sub_type == MEDIASUBTYPE_RGB32);
}

// Copies |actual_config_| to |ptr_config|. Note that the filter lock is always
// held by caller, |VideoSinkFilter::config|.
HRESULT VideoSinkPin::config(VideoConfig* ptr_config) const {
  if (!ptr_config) {
    return E_POINTER;
  }
  *ptr_config = actual_config_;
  return S_OK;
}

// Sets |requested_config_| and resets |actual_config_|. Filter lock always
// held by caller, |VideoSinkFilter::set_config|.
HRESULT VideoSinkPin::set_config(const VideoConfig& config) {
  requested_config_ = config;
  actual_config_ = VideoConfig();
  return S_OK;
}

///////////////////////////////////////////////////////////////////////////////
// VideoSinkFilter
//
VideoSinkFilter::VideoSinkFilter(
    const TCHAR* ptr_filter_name,
    LPUNKNOWN ptr_iunknown,
    VideoFrameCallbackInterface* ptr_frame_callback,
    HRESULT* ptr_result)
    : CBaseFilter(ptr_filter_name,
                  ptr_iunknown,
                  &filter_lock_,
                  CLSID_VideoSinkFilter) {
  if (!ptr_frame_callback) {
    *ptr_result = E_INVALIDARG;
    return;
  }
  ptr_frame_callback_ = ptr_frame_callback;
  sink_pin_.reset(
      new (std::nothrow) VideoSinkPin(NAME("VideoSinkInputPin"),  // NOLINT
                                      this, &filter_lock_, ptr_result,
                                      L"VideoSink"));
  if (!sink_pin_) {
    *ptr_result = E_OUTOFMEMORY;
  } else {
    *ptr_result = S_OK;
  }
}

VideoSinkFilter::~VideoSinkFilter() {
}

// Locks filter and returns |VideoSinkPin::config|.
HRESULT VideoSinkFilter::config(VideoConfig* ptr_config) const {
  CAutoLock lock(&filter_lock_);
  return sink_pin_->config(ptr_config);
}

// Locks filter and returns |VideoSinkPin::set_config|.
HRESULT VideoSinkFilter::set_config(const VideoConfig& config) {
  if (m_State != State_Stopped) {
    return VFW_E_NOT_STOPPED;
  }
  CAutoLock lock(&filter_lock_);
  return sink_pin_->set_config(config);
}

// Locks filter and returns VideoSinkPin pointer wrapped by |sink_pin_|.
CBasePin* VideoSinkFilter::GetPin(int index) {
  CBasePin* ptr_pin = NULL;
  CAutoLock lock(&filter_lock_);
  if (index == 0) {
    ptr_pin = sink_pin_.get();
  }
  return ptr_pin;
}

// Lock owned by |VideoSinkPin::Receive|. Copies buffer from |ptr_sample| into
// |frame_|, and then passes |frame_| to
// |VideoFrameCallbackInterface::OnVideoFrameReceived|.
HRESULT VideoSinkFilter::OnFrameReceived(IMediaSample* ptr_sample) {
  if (!ptr_sample) {
    return E_POINTER;
  }
  BYTE* ptr_sample_buffer = NULL;
  HRESULT hr = ptr_sample->GetPointer(&ptr_sample_buffer);
  if (FAILED(hr) || !ptr_sample_buffer) {
    LOG(ERROR) << "OnFrameReceived called with empty sample.";
    hr = (hr == S_OK) ? E_FAIL : hr;
    return hr;
  }
  int64 timestamp = 0;
  int64 duration = 0;
  REFERENCE_TIME start_time = 0;
  REFERENCE_TIME end_time = 0;
  hr = ptr_sample->GetTime(&start_time, &end_time);
  if (FAILED(hr)) {
    LOG(ERROR) << "OnFrameReceived cannot get media time(s)." << HRLOG(hr);
    return hr;
  }
  timestamp = media_time_to_milliseconds(start_time);
  if (hr != VFW_S_NO_STOP_TIME) {
    duration = media_time_to_milliseconds(end_time) - timestamp;
  } else {
    LOG(WARNING) << "OnFrameReceived using time per frame for duration.";
    AM_MEDIA_TYPE media_type = {0};
    hr = sink_pin_->ConnectionMediaType(&media_type);
    if (FAILED(hr)) {
      LOG(ERROR) << "OnFrameReceived pin has no media type: " << HRLOG(hr);
      return hr;
    }
    VideoMediaType video_format;
    if (video_format.Init(media_type)) {
      LOG(ERROR) << "OnFrameReceived cannot Init VideoMediaType.";
      return E_FAIL;
    }
    duration = media_time_to_milliseconds(video_format.avg_time_per_frame());
  }

  // TODO(tomfinegan): Write an allocator that retrieves frames from
  //                   |WebmEncoder::EncoderThread| and avoid this extra copy.

  const int status = frame_.Init(sink_pin_->actual_config_,
                                 true,  // always "keyframes"
                                 timestamp,
                                 duration,
                                 ptr_sample_buffer,
                                 ptr_sample->GetActualDataLength());
  if (status) {
    LOG(ERROR) << "OnFrameReceived frame init failed: " << status;
    return E_FAIL;
  }
  LOG(INFO) << "OnFrameReceived received a frame:"
            << " width="  << sink_pin_->actual_config_.width
            << " height=" << sink_pin_->actual_config_.height
            << " format=" << sink_pin_->actual_config_.format
            << " stride=" << sink_pin_->actual_config_.stride
            << " timestamp(sec)=" << (timestamp / 1000.0)
            << " timestamp="      << timestamp
            << " duration(sec)= " << (duration / 1000.0)
            << " duration= "      << duration
            << " size=" << frame_.buffer_length();
  int frame_status = ptr_frame_callback_->OnVideoFrameReceived(&frame_);
  if (frame_status && frame_status != VideoFrameCallbackInterface::kDropped) {
    LOG(ERROR) << "OnVideoFrameReceived failed, status=" << frame_status;
  }
  return S_OK;
}

}  // namespace webmlive
