/***************************************************************************
                          ADM_vp3.cpp  -  description
                             -------------------
    begin                : Sat Sep 28 2002
    copyright            : (C) 2002 by mean
    email                : fixounet@free.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <math.h>


#include "ADM_vp32/ADM_vp3.h"

#include "ADM_library/default.h"

#include "ADM_colorspace/colorspace.h"

#include "ADM_codecs/ADM_codec.h"
#include "ADM_codecs/ADM_vp3.h"

#include "ADM_toolkit/toolkit.hxx"
#include <ADM_assert.h>
#include "ADM_dialog/DIA_enter.h"

/*
   	Initialize codec
*/

decoderVP3::decoderVP3 (uint32_t w, uint32_t h):decoders (w, h)
{
  _handle = NULL;
  StartDecoder (&_handle, w, h);
  _handle->PostProcessEnabled = 1;
  _handle->PostProcessingLevel = 6;
}

decoderVP3::~decoderVP3 ()
{
  StopDecoder (&_handle);

}

void
decoderVP3::setParam (void)
{
  int value = 0;
  value = _handle->PostProcessingLevel;
  if (DIA_GetIntegerValue
      (&value, 0, 9, "Post Processing level", "Enter PostProc"))
    {
      _handle->PostProcessingLevel = (int) floor (value);
      printf (" New VP3 postprocessing value : %d\n",
	      _handle->PostProcessingLevel);
    }
  return;
}

/*
   	Uncompress frame, set flags if needed
*/
uint8_t
  decoderVP3::uncompress (uint8_t * in, ADMImage * out, uint32_t len,
			  uint32_t * flag)
{
  UNUSED_ARG (flag);
  if (DecodeFrameToYUV (_handle, (char *) in, len, _w, _h))
    {
      fprintf (stderr, "DecodeFrameToYUV error\n");
      return 0;
    }
  // now unpack to out
//              memset(out+_w*_h,128,(_w*_h)>>1);

  uint8_t *ti, *to;
  uint8_t *ti2, *to2;

  uint32_t stride;

  to = out->data + (_w * _h) - _w;

  if (_handle->PostProcessingLevel)
    {
      ti = &(_handle->PostProcessBuffer[_handle->ReconYDataOffset]);
    }
  else
    {
      ti = &(_handle->LastFrameRecon[_handle->ReconYDataOffset]);
    }

  stride = _handle->Configuration.YStride;

  // luma
  for (uint32_t y = _h; y > 0; y--)
    {
      memcpy (to, ti, _w);
      to -= _w;
      ti += stride;
    }

  to2 = out->data + _w * _h;
  to = to2 + ((_w * _h) >> 2);
  memset (to, 128, _w >> 1);
  memset (to2, 128, _w >> 1);

  to += ((_w * _h) >> 2) - (_w >> 1);
  to2 += ((_w * _h) >> 2) - (_w >> 1);
  if (_handle->PostProcessingLevel)
    {
      ti = &(_handle->PostProcessBuffer[_handle->ReconUDataOffset]);
      ti2 = &(_handle->PostProcessBuffer[_handle->ReconVDataOffset]);

    }
  else
    {
      ti = &(_handle->LastFrameRecon[_handle->ReconUDataOffset]);
      ti2 = &(_handle->LastFrameRecon[_handle->ReconVDataOffset]);
    }
  stride = _handle->Configuration.UVStride;

  // chorma u &v
  for (uint32_t y = _h >> 1; y > 0; y--)
    {
      memcpy (to, ti, _w >> 1);
      memcpy (to2, ti2, _w >> 1);

      to -= _w >> 1;
      ti += stride;
      to2 -= _w >> 1;
      ti2 += stride;

    }

  return 1;
}
