/*
 * gst-plugins-bad
 * Copyright (C) 2012 Edward Hervey <edward@collabora.com>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gstvdpvideobufferpool.h"
#include "gstvdpvideomemory.h"

GST_DEBUG_CATEGORY_STATIC (gst_vdp_vidbufpool_debug);
#define GST_CAT_DEFAULT gst_vdp_vidbufpool_debug

static void gst_vdp_video_buffer_pool_finalize (GObject * object);

#define DEBUG_INIT \
    GST_DEBUG_CATEGORY_INIT (gst_vdp_vidbufpool_debug, "vdpvideopool", 0, \
    "VDPAU Video bufferpool");

#define gst_vdp_video_buffer_pool_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstVdpVideoBufferPool, gst_vdp_video_buffer_pool,
    GST_TYPE_BUFFER_POOL, DEBUG_INIT);

static const gchar **
gst_vdp_video_buffer_pool_get_options (GstBufferPool * pool)
{
  static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
    GST_BUFFER_POOL_OPTION_VDP_VIDEO_META, NULL
  };

  return options;
}

static gboolean
gst_vdp_video_buffer_pool_set_config (GstBufferPool * pool,
    GstStructure * config)
{
  GstVdpVideoBufferPool *vdppool = GST_VDP_VIDEO_BUFFER_POOL_CAST (pool);
  GstVideoInfo info;
  GstCaps *caps;

  if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
    goto wrong_config;

  if (caps == NULL)
    goto no_caps;

  /* now parse the caps from the config */
  if (!gst_video_info_from_caps (&info, caps))
    goto wrong_caps;

  GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, info.width, info.height,
      caps);

  if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_UNKNOWN)
    goto unknown_format;

  vdppool->info = info;

  /* enable metadata based on config of the pool */
  vdppool->add_videometa =
      gst_buffer_pool_config_has_option (config,
      GST_BUFFER_POOL_OPTION_VIDEO_META);

  /* parse extra alignment info */
  vdppool->add_vdpmeta = gst_buffer_pool_config_has_option (config,
      GST_BUFFER_POOL_OPTION_VDP_VIDEO_META);

  return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);

  /* ERRORS */
wrong_config:
  {
    GST_WARNING_OBJECT (pool, "invalid config");
    return FALSE;
  }
no_caps:
  {
    GST_WARNING_OBJECT (pool, "no caps in config");
    return FALSE;
  }
wrong_caps:
  {
    GST_WARNING_OBJECT (pool,
        "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
    return FALSE;
  }
unknown_format:
  {
    GST_WARNING_OBJECT (vdppool, "failed to get format from caps %"
        GST_PTR_FORMAT, caps);
    GST_ELEMENT_ERROR (vdppool, RESOURCE, WRITE,
        ("Failed to create output image buffer of %dx%d pixels",
            info.width, info.height),
        ("Invalid input caps %" GST_PTR_FORMAT, caps));
    return FALSE;
  }
}

/* This function handles GstBuffer creation */
static GstFlowReturn
gst_vdp_video_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
    GstBufferPoolAcquireParams * params)
{
  GstVdpVideoBufferPool *vdppool = GST_VDP_VIDEO_BUFFER_POOL_CAST (pool);
  GstVideoInfo *info;
  GstBuffer *buf;
  GstMemory *vdp_mem;

  info = &vdppool->info;

  if (!(buf = gst_buffer_new ()))
    goto no_buffer;

  if (!(vdp_mem = gst_vdp_video_memory_alloc (vdppool->device, info)))
    goto mem_create_failed;

  gst_buffer_append_memory (buf, vdp_mem);

  if (vdppool->add_videometa) {
    GstVideoMeta *vmeta;

    GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
    /* these are just the defaults for now */
    vmeta = gst_buffer_add_video_meta (buf, 0, GST_VIDEO_INFO_FORMAT (info),
        GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
    vmeta->map = gst_vdp_video_memory_map;
    vmeta->unmap = gst_vdp_video_memory_unmap;
  }

  *buffer = buf;

  return GST_FLOW_OK;

  /* ERROR */
no_buffer:
  {
    GST_WARNING_OBJECT (pool, "can't create image");
    return GST_FLOW_ERROR;
  }

mem_create_failed:
  {
    GST_WARNING_OBJECT (pool, "Could create GstVdpVideo Memory");
    return GST_FLOW_ERROR;
  }
}


GstBufferPool *
gst_vdp_video_buffer_pool_new (GstVdpDevice * device)
{
  GstVdpVideoBufferPool *pool;

  pool = g_object_new (GST_TYPE_VDP_VIDEO_BUFFER_POOL, NULL);
  pool->device = gst_object_ref (device);

  GST_LOG_OBJECT (pool, "new VdpVideo buffer pool %p", pool);

  return GST_BUFFER_POOL_CAST (pool);
}

static void
gst_vdp_video_buffer_pool_class_init (GstVdpVideoBufferPoolClass * klass)
{
  GObjectClass *gobject_class = (GObjectClass *) klass;
  GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;

  gobject_class->finalize = gst_vdp_video_buffer_pool_finalize;

  gstbufferpool_class->get_options = gst_vdp_video_buffer_pool_get_options;
  gstbufferpool_class->set_config = gst_vdp_video_buffer_pool_set_config;
  gstbufferpool_class->alloc_buffer = gst_vdp_video_buffer_pool_alloc;
}

static void
gst_vdp_video_buffer_pool_init (GstVdpVideoBufferPool * pool)
{

}

static void
gst_vdp_video_buffer_pool_finalize (GObject * object)
{
  GstVdpVideoBufferPool *pool = GST_VDP_VIDEO_BUFFER_POOL_CAST (object);

  GST_LOG_OBJECT (pool, "finalize VdpVideo buffer pool %p", pool);

  gst_object_unref (pool->device);

  G_OBJECT_CLASS (gst_vdp_video_buffer_pool_parent_class)->finalize (object);
}
