// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <Python.h>
#include <X11/Xlib.h>
#include <va/va.h>
#include <va/va_x11.h>

static PyObject *VaapiError;

namespace {

struct DisplayBundle {
  Display *x11_display;
  VADisplay va_display;
};

static void destroy_display_bundle(PyObject* object) {
  DisplayBundle* bundle = (DisplayBundle*) PyCapsule_GetPointer(object, NULL);
  vaTerminate(bundle->va_display);
  XCloseDisplay(bundle->x11_display);
  delete bundle;
}

static PyObject* va_create_display(PyObject* self, PyObject* args) {
  const char* display_name;
  if (!PyArg_ParseTuple(args, "s", &display_name))
    return NULL;

  Display *x11_display = XOpenDisplay(display_name);

  if (x11_display == NULL) {
    PyErr_SetString(VaapiError, "Cannot connect X server!");
    return NULL;
  }

  VADisplay va_display = vaGetDisplay(x11_display);
  if (!vaDisplayIsValid(va_display)) {
    PyErr_SetString(VaapiError, "Cannot get a valid display");
    return NULL;
  }

  int major_ver, minor_ver;

  VAStatus va_status = vaInitialize(va_display, &major_ver, &minor_ver);
  if (va_status != VA_STATUS_SUCCESS) {
    PyErr_SetString(VaapiError, "vaInitialize fail");
    return NULL;
  }

  DisplayBundle* bundle = new DisplayBundle();
  bundle->x11_display = x11_display;
  bundle->va_display = va_display;

  return PyCapsule_New(bundle, NULL, destroy_display_bundle);
}

static VADisplay get_va_display(PyObject* object) {
  if (!PyCapsule_CheckExact(object)) {
    PyErr_SetString(VaapiError, "invalid display object");
    return NULL;
  }

  DisplayBundle* bundle = (DisplayBundle*) PyCapsule_GetPointer(object, NULL);

  if (bundle == NULL)
    return NULL;

  return bundle->va_display;
}

static PyObject* va_query_profiles(PyObject* self, PyObject* args) {
  PyObject* bundle;
  if (!PyArg_ParseTuple(args, "O", &bundle))
    return NULL;

  VADisplay va_display = get_va_display(bundle);

  if (va_display == NULL)
    return NULL;

  int num_profiles = vaMaxNumProfiles(va_display);
  VAProfile *profile = new VAProfile[num_profiles];

  VAStatus status = vaQueryConfigProfiles(va_display, profile, &num_profiles);

  if (status != VA_STATUS_SUCCESS) {
    delete [] profile;
    PyErr_SetString(VaapiError, "vaQueryConfigProfiles fail");
    return NULL;
  }

  PyObject *result = PyList_New(0);
  for (int i = 0; i < num_profiles; ++i) {
    size_t value = static_cast<size_t>(profile[i]);
    PyList_Append(result, PyInt_FromSize_t(value));
  }
  delete [] profile;
  return result;
}

static PyObject* va_query_entrypoints(PyObject* self, PyObject* args) {
  PyObject* bundle;
  int profile;
  if (!PyArg_ParseTuple(args, "Oi", &bundle, &profile))
    return NULL;

  VADisplay va_display = get_va_display(bundle);
  if (va_display == NULL) 
    return NULL;

  int num_entrypoints = vaMaxNumEntrypoints(va_display);
  VAEntrypoint* entrypoint = new VAEntrypoint[num_entrypoints];

  VAStatus status = vaQueryConfigEntrypoints(va_display,
                                             static_cast<VAProfile>(profile),
                                             entrypoint,
                                             &num_entrypoints);
  if (status != VA_STATUS_SUCCESS) {
    PyErr_SetString(VaapiError, "vaQueryConfigEntryPoints fail");
    return NULL;
  }

  PyObject *result = PyList_New(0);
  for (int i = 0; i < num_entrypoints; ++i) {
    size_t value = static_cast<size_t>(entrypoint[i]);
    PyList_Append(result, PyInt_FromSize_t(value));
  }
  return result;
}

static PyObject* va_get_rt_format(PyObject* self, PyObject* args) {
  PyObject* bundle;
  int profile;
  int entrypoint;
  if (!PyArg_ParseTuple(args, "Oii", &bundle, &profile, &entrypoint))
    return NULL;

  VADisplay va_display = get_va_display(bundle);
  if (va_display == NULL) 
    return NULL;

  VAConfigAttrib attrib;
  attrib.type = VAConfigAttribRTFormat;
  VAStatus status = vaGetConfigAttributes(va_display,
                                          static_cast<VAProfile>(profile),
                                          static_cast<VAEntrypoint>(entrypoint),
                                          &attrib,
                                          1);
  if (status != VA_STATUS_SUCCESS) {
    PyErr_SetString(VaapiError, "vaGetConfgAttributes fail");
    return NULL;
  }

  return PyInt_FromSize_t(attrib.value);
}

/*
 * Bind Python function names to our C functions
 */
static PyMethodDef vaapi_methods[] = {
    {"create_display", va_create_display, METH_VARARGS},
    {"query_profiles", va_query_profiles, METH_VARARGS},
    {"query_entrypoints", va_query_entrypoints, METH_VARARGS},
    {"get_rt_format", va_get_rt_format, METH_VARARGS},
    {NULL, NULL}
};

} // end of namespace

/*
 * Python calls this to let us initialize our module
 */
PyMODINIT_FUNC initvaapi() {
  PyObject *m = Py_InitModule("vaapi", vaapi_methods);
  if (m == NULL)
    return;

  VaapiError = PyErr_NewException("vaapi.error", NULL, NULL);
  Py_INCREF(VaapiError);
  PyModule_AddObject(m, "error", VaapiError);
}
