/*  This file is part of YUView - The YUV player with advanced analytics toolset
 *   <https://github.com/IENT/YUView>
 *   Copyright (C) 2015  Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY
 *
 *   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 3 of the License, or
 *   (at your option) any later version.
 *
 *   In addition, as a special exception, the copyright holders give
 *   permission to link the code of portions of this program with the
 *   OpenSSL library under certain conditions as described in each
 *   individual source file, and distribute linked combinations including
 *   the two.
 *
 *   You must obey the GNU General Public License in all respects for all
 *   of the code used other than OpenSSL. If you modify file(s) with this
 *   exception, you may extend this exception to your version of the
 *   file(s), but you are not obligated to do so. If you do not wish to do
 *   so, delete this exception statement from your version. If you delete
 *   this exception statement from all source files in the program, then
 *   also delete it here.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "AVFrameSideDataWrapper.h"
#include <stdexcept>

namespace FFmpeg
{

namespace
{

typedef struct AVFrameSideData_54_55_56
{
  enum AVFrameSideDataType type;
  uint8_t *                data;
  int                      size;
  AVDictionary *           metadata;
  AVBufferRef *            buf;
} AVFrameSideData_54_55_56;

typedef struct AVFrameSideData_57_58
{
  enum AVFrameSideDataType type;
  uint8_t *                data;
  size_t                   size;
  AVDictionary *           metadata;
  AVBufferRef *            buf;
} AVFrameSideData_57_58;

} // namespace

AVFrameSideDataWrapper::AVFrameSideDataWrapper(AVFrameSideData *sideData, LibraryVersion libVer)
    : sideData(sideData), libVer(libVer)
{
  this->update();
}

size_t AVFrameSideDataWrapper::getNumberMotionVectors()
{
  this->update();

  if (this->type != AV_FRAME_DATA_MOTION_VECTORS)
    return 0;

  return AVMotionVectorWrapper::getNumberOfMotionVectors(this->libVer, this->size);
}

AVMotionVectorWrapper AVFrameSideDataWrapper::getMotionVector(unsigned idx)
{
  this->update();
  return AVMotionVectorWrapper(this->libVer, this->data, idx);
}

void AVFrameSideDataWrapper::update()
{
  if (this->sideData == nullptr)
    return;

  if (this->libVer.avutil.major == 54 || //
      this->libVer.avutil.major == 55 || //
      this->libVer.avutil.major == 56)
  {
    auto p     = reinterpret_cast<AVFrameSideData_54_55_56 *>(sideData);
    this->type = p->type;
    this->data = p->data;
    if (p->size > 0)
      this->size = size_t(p->size);
    this->metadata = p->metadata;
    this->buf      = p->buf;
  }
  else if (this->libVer.avutil.major == 57 || this->libVer.avutil.major == 58)
  {
    auto p         = reinterpret_cast<AVFrameSideData_57_58 *>(sideData);
    this->type     = p->type;
    this->data     = p->data;
    this->size     = p->size;
    this->metadata = p->metadata;
    this->buf      = p->buf;
  }
  else
    throw std::runtime_error("Invalid library version");
}

} // namespace FFmpeg
