/*
 *  Copyright (c) 2011 The WebRTC 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 "frame_preprocessor.h"
#include "trace.h"

namespace webrtc {

VPMFramePreprocessor::VPMFramePreprocessor():
_id(0),
_contentMetrics(NULL),
_nativeHeight(0),
_nativeWidth(0),
_resampledFrame(),
_enableCA(false)
{
    _spatialResampler = new VPMSimpleSpatialResampler();
    _ca = new VPMContentAnalysis();
    _vd = new VPMVideoDecimator();
}

VPMFramePreprocessor::~VPMFramePreprocessor()
{
    Reset();
    delete _spatialResampler;
    delete _ca;
    delete _vd;
    _resampledFrame.Free(); // is this needed?
}

WebRtc_Word32
VPMFramePreprocessor::ChangeUniqueId(const WebRtc_Word32 id)
{
    _id = id;
    return VPM_OK;
}

void 
VPMFramePreprocessor::Reset()
{
    _nativeWidth = 0;
    _nativeHeight = 0;
    _ca->Release();
    _vd->Reset();
    _contentMetrics = NULL;
    _spatialResampler->Reset();
    _enableCA = false;
}
	
    
void 
VPMFramePreprocessor::EnableTemporalDecimation(bool enable)
{
    _vd->EnableTemporalDecimation(enable);
}
void
VPMFramePreprocessor::EnableContentAnalysis(bool enable)
{
    _enableCA = enable;
}

void 
VPMFramePreprocessor::SetInputFrameResampleMode(VideoFrameResampling resamplingMode)
{
    _spatialResampler->SetInputFrameResampleMode(resamplingMode);
}

    
WebRtc_Word32
VPMFramePreprocessor::SetMaxFrameRate(WebRtc_UWord32 maxFrameRate)
{
    if (maxFrameRate == 0)
    {
        return VPM_PARAMETER_ERROR;
    }
    //Max allowed frame rate
    _maxFrameRate = maxFrameRate;

    return _vd->SetMaxFrameRate(maxFrameRate);
}
    

WebRtc_Word32
VPMFramePreprocessor::SetTargetResolution(WebRtc_UWord32 width, WebRtc_UWord32 height, WebRtc_UWord32 frameRate)
{
    if ( (width == 0) || (height == 0) || (frameRate == 0))
    {
        return VPM_PARAMETER_ERROR;
    }
    WebRtc_Word32 retVal = 0;
    retVal = _spatialResampler->SetTargetFrameSize(width, height);
    if (retVal < 0)
    {
        return retVal;
    }
    retVal = _vd->SetTargetFrameRate(frameRate);
    if (retVal < 0)
    {
        return retVal;
    }

	  return VPM_OK;
}

void 
VPMFramePreprocessor::UpdateIncomingFrameRate()
{
    _vd->UpdateIncomingFrameRate();
}

WebRtc_UWord32
VPMFramePreprocessor::DecimatedFrameRate()
{
    return _vd->DecimatedFrameRate();
}


WebRtc_UWord32
VPMFramePreprocessor::DecimatedWidth() const
{
    return _spatialResampler->TargetWidth();
}


WebRtc_UWord32
VPMFramePreprocessor::DecimatedHeight() const
{
    return _spatialResampler->TargetHeight();
}


WebRtc_Word32
VPMFramePreprocessor::PreprocessFrame(const VideoFrame* frame, VideoFrame** processedFrame)
{
    if (frame == NULL || frame->Height() == 0 || frame->Width() == 0)
    {
        return VPM_PARAMETER_ERROR;
    }

    _vd->UpdateIncomingFrameRate();

    if (_vd->DropFrame())
    {
        WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, _id, "Drop frame due to frame rate");
        return 1;  // drop 1 frame
    }

    // Resizing incoming frame if needed.
    // Note that we must make a copy of it.
    // We are not allowed to resample the input frame.
    *processedFrame = NULL;
    if (_spatialResampler->ApplyResample(frame->Width(), frame->Height()))  {
      WebRtc_Word32 ret = _spatialResampler->ResampleFrame(*frame, _resampledFrame);
      if (ret != VPM_OK)
        return ret;
      *processedFrame = &_resampledFrame;
    }

    // Perform content analysis on the frame to be encoded
    if (_enableCA)
    {
        if (*processedFrame == NULL)  {
          _contentMetrics = _ca->ComputeContentMetrics(frame);
        } else {
          _contentMetrics = _ca->ComputeContentMetrics(&_resampledFrame);
        }
        // Update native values:
        _contentMetrics->nativeHeight = frame->Height();
        _contentMetrics->nativeWidth = frame->Width();
        // Max value as set by user
        _contentMetrics->nativeFrameRate = _maxFrameRate;
    }
    return VPM_OK;
}


VideoContentMetrics*
VPMFramePreprocessor::ContentMetrics() const
{
    return _contentMetrics;
}

} //namespace
