Skip to content

Commit

Permalink
added: CRenderCapture binding for python from pull request 448, fixes x…
Browse files Browse the repository at this point in the history
  • Loading branch information
durchflieger authored and bobo1on1 committed Sep 30, 2011
1 parent 6aee4af commit 54e4ca5
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 0 deletions.
2 changes: 2 additions & 0 deletions project/VS2010Express/XBMC.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\pyplaylist.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\pyrendercapture.cpp" />
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonAddon.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug (OpenGL)|Win32'">..\..\project\BuildDependencies\include\python;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
Expand Down Expand Up @@ -1429,6 +1430,7 @@
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\player.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyjsonrpc.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyplaylist.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyrendercapture.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonAddon.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\PythonPlayer.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyutil.h" />
Expand Down
6 changes: 6 additions & 0 deletions project/VS2010Express/XBMC.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -2550,6 +2550,9 @@
<ClCompile Include="..\..\xbmc\peripherals\dialogs\GUIDialogPeripheralSettings.cpp">
<Filter>peripherals\dialogs</Filter>
</ClCompile>
<ClCompile Include="..\..\xbmc\interfaces\python\xbmcmodule\pyrendercapture.cpp">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
Expand Down Expand Up @@ -5114,6 +5117,9 @@
<ClInclude Include="..\..\xbmc\peripherals\dialogs\GUIDialogPeripheralSettings.h">
<Filter>peripherals\dialogs</Filter>
</ClInclude>
<ClInclude Include="..\..\xbmc\interfaces\python\xbmcmodule\pyrendercapture.h">
<Filter>interfaces\python\xbmcmodule</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
Expand Down
14 changes: 14 additions & 0 deletions xbmc/cores/VideoRenderers/RenderCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ CRenderCaptureGL::~CRenderCaptureGL()
delete[] m_pixels;
}

int CRenderCaptureGL::GetCaptureFormat()
{
#ifdef HAS_GLES
return CAPTUREFORMAT_RGBA;
#else
return CAPTUREFORMAT_BGRA;
#endif
}

void CRenderCaptureGL::BeginRender()
{
if (!m_asyncChecked)
Expand Down Expand Up @@ -235,6 +244,11 @@ CRenderCaptureDX::~CRenderCaptureDX()
g_Windowing.Unregister(this);
}

int CRenderCaptureDX::GetCaptureFormat()
{
return CAPTUREFORMAT_BGRA;
}

void CRenderCaptureDX::BeginRender()
{
LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
Expand Down
7 changes: 7 additions & 0 deletions xbmc/cores/VideoRenderers/RenderCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ enum ECAPTURESTATE
#define CAPTUREFLAG_CONTINUOUS 0x01 //after a render is done, render a new one immediately
#define CAPTUREFLAG_IMMEDIATELY 0x02 //read out immediately after render, this can cause a busy wait

#define CAPTUREFORMAT_BGRA 0x01
#define CAPTUREFORMAT_RGBA 0x02

class CRenderCaptureBase
{
public:
Expand Down Expand Up @@ -176,6 +179,8 @@ class CRenderCaptureGL : public CRenderCaptureBase
CRenderCaptureGL();
~CRenderCaptureGL();

int GetCaptureFormat();

void BeginRender();
void EndRender();
void ReadOut();
Expand Down Expand Up @@ -204,6 +209,8 @@ class CRenderCaptureDX : public CRenderCaptureBase, public ID3DResource
CRenderCaptureDX();
~CRenderCaptureDX();

int GetCaptureFormat();

void BeginRender();
void EndRender();
void ReadOut();
Expand Down
1 change: 1 addition & 0 deletions xbmc/interfaces/python/xbmcmodule/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SRCS=action.cpp \
listitem.cpp \
player.cpp \
pyplaylist.cpp \
pyrendercapture.cpp \
PythonAddon.cpp \
PythonPlayer.cpp \
pyutil.cpp \
Expand Down
226 changes: 226 additions & 0 deletions xbmc/interfaces/python/xbmcmodule/pyrendercapture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/*
* Copyright (C) 2011 Team XBMC
* http://www.xbmc.org
*
* 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, or (at your option)
* any later version.
*
* 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 XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#include "pyutil.h"
#include "pythreadstate.h"
#include "pyrendercapture.h"
#include "cores/VideoRenderers/RenderManager.h"

#ifdef __cplusplus
extern "C" {
#endif

namespace PYXBMC
{
PyObject* RenderCapture_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
RenderCapture *self = (RenderCapture*)type->tp_alloc(type, 0);
if (!self)
return NULL;

self->capture = g_renderManager.AllocRenderCapture();
if (!self->capture)
{
self->ob_type->tp_free((PyObject*)self);
return PyErr_NoMemory();
}

return (PyObject*)self;
}

void RenderCapture_Dealloc(RenderCapture* self)
{
g_renderManager.ReleaseRenderCapture(self->capture);
self->ob_type->tp_free((PyObject*)self);
}

// RenderCapture_GetWidth
PyDoc_STRVAR(getWidth__doc__,
"getWidth() -- returns width of captured image.\n");

PyObject* RenderCapture_GetWidth(RenderCapture *self, PyObject *args)
{
return Py_BuildValue((char*)"i", (int)self->capture->GetWidth());
}

// RenderCapture_GetHeight
PyDoc_STRVAR(getHeight__doc__,
"getHeight() -- returns height of captured image.\n");

PyObject* RenderCapture_GetHeight(RenderCapture *self, PyObject *args)
{
return Py_BuildValue((char*)"i", (int)self->capture->GetHeight());
}

// RenderCapture_GetCaptureState
PyDoc_STRVAR(getCaptureState__doc__,
"getCaptureState() -- returns processing state of capture request.\n"
"\n"
"The returned value could be compared against the following constants:\n"
"xbmc.CAPTURE_STATE_WORKING : Capture request in progress.\n"
"xbmc.CAPTURE_STATE_DONE : Capture request done. The image could be retrieved with getImage()\n"
"xbmc.CAPTURE_STATE_FAILED : Capture request failed.\n");

PyObject* RenderCapture_GetCaptureState(RenderCapture *self, PyObject *args)
{
return Py_BuildValue((char*)"i", (int)self->capture->GetUserState());
}

// RenderCapture_GetAspectRatio
PyDoc_STRVAR(getAspectRatio__doc__,
"getAspectRatio() -- returns aspect ratio of currently displayed video.\n");

PyObject* RenderCapture_GetAspectRatio(RenderCapture *self, PyObject *args)
{
return Py_BuildValue((char*)"f", g_renderManager.GetAspectRatio());
}

// RenderCapture_PixelFormat
PyDoc_STRVAR(getImageFormat__doc__,
"getImageFormat() -- returns format of captured image: 'BGRA' or 'RGBA'.\n");

PyObject* RenderCapture_GetImageFormat(RenderCapture *self, PyObject *args)
{
if (self->capture->GetCaptureFormat() == CAPTUREFORMAT_BGRA)
return Py_BuildValue((char*)"s", "BGRA");
else if (self->capture->GetCaptureFormat() == CAPTUREFORMAT_RGBA)
return Py_BuildValue((char*)"s", "RGBA");

Py_INCREF(Py_None);
return Py_None;
}

// RenderCapture_GetImage
PyDoc_STRVAR(getImage__doc__,
"getImage() -- returns captured image as a bytearray.\n"
"\n"
"The size of the image is getWidth() * getHeight() * 4\n");

PyObject* RenderCapture_GetImage(RenderCapture *self, PyObject *args)
{
if (self->capture->GetUserState() != CAPTURESTATE_DONE)
{
PyErr_SetString(PyExc_SystemError, "illegal user state");
return NULL;
}

Py_ssize_t size = self->capture->GetWidth() * self->capture->GetHeight() * 4;
return PyByteArray_FromStringAndSize((const char *)self->capture->GetPixels(), size);
}

// RenderCapture_Capture
PyDoc_STRVAR(capture__doc__,
"capture(width, height [, flags]) -- issue capture request.\n"
"\n"
"width : Width capture image should be rendered to\n"
"height : Height capture image should should be rendered to\n"
"flags : Optional. Flags that control the capture processing.\n"
"\n"
"The value for 'flags' could be or'ed from the following constants:\n"
"xbmc.CAPTURE_FLAG_CONTINUOUS : after a capture is done, issue a new capture request immediately\n"
"xbmc.CAPTURE_FLAG_IMMEDIATELY : read out immediately when capture() is called, this can cause a busy wait\n");

PyObject* RenderCapture_Capture(RenderCapture *self, PyObject *args)
{
if (self->capture->GetUserState() != CAPTURESTATE_DONE && self->capture->GetUserState() != CAPTURESTATE_FAILED)
{
PyErr_SetString(PyExc_SystemError, "illegal user state");
return NULL;
}

int width, height, flags = 0;
if (!PyArg_ParseTuple(args, "ii|i", &width, &height, &flags))
return NULL;

CPyThreadState threadstate;
g_renderManager.Capture(self->capture, (unsigned int)width, (unsigned int)height, flags);
threadstate.Restore();

Py_INCREF(Py_None);
return Py_None;
}

// RenderCapture_WaitForCaptureStateChangeEvent
PyDoc_STRVAR(waitForCaptureStateChangeEvent__doc__,
"waitForCaptureStateChangeEvent([msecs]) -- wait for capture state change event.\n"
"\n"
"msecs : Milliseconds to wait. Waits forever if not specified.\n"
"\n"
"The method will return 1 if the Event was triggered. Otherwise it will return 0.\n");

PyObject* RenderCapture_WaitForCaptureStateChangeEvent(RenderCapture *self, PyObject *args)
{
bool rc;
int msecs = 0;
if (!PyArg_ParseTuple(args, "|i", &msecs))
return NULL;

CPyThreadState threadstate;
if (msecs)
rc = self->capture->GetEvent().WaitMSec((unsigned int)msecs);
else
rc = self->capture->GetEvent().Wait();
threadstate.Restore();

return Py_BuildValue((char*)"i", (rc ? 1: 0));
}


PyMethodDef RenderCapture_methods[] = {
{(char*)"getWidth", (PyCFunction)RenderCapture_GetWidth, METH_VARARGS, getWidth__doc__},
{(char*)"getHeight", (PyCFunction)RenderCapture_GetHeight, METH_VARARGS, getHeight__doc__},
{(char*)"getCaptureState", (PyCFunction)RenderCapture_GetCaptureState, METH_VARARGS, getCaptureState__doc__},
{(char*)"getAspectRatio", (PyCFunction)RenderCapture_GetAspectRatio, METH_VARARGS, getAspectRatio__doc__},
{(char*)"getImageFormat", (PyCFunction)RenderCapture_GetImageFormat, METH_VARARGS, getImageFormat__doc__},
{(char*)"getImage", (PyCFunction)RenderCapture_GetImage, METH_VARARGS, getImage__doc__},
{(char*)"capture", (PyCFunction)RenderCapture_Capture, METH_VARARGS, capture__doc__},
{(char*)"waitForCaptureStateChangeEvent", (PyCFunction)RenderCapture_WaitForCaptureStateChangeEvent, METH_VARARGS, waitForCaptureStateChangeEvent__doc__},
{NULL, NULL, 0, NULL}
};

PyDoc_STRVAR(RenderCapture__doc__,
"RenderCapture class.\n"
"\n"
"Capture images of abitrary size of the currently displayed video stream.\n");

// Restore code and data sections to normal.

PyTypeObject RenderCapture_Type;

void initRenderCapture_Type()
{
PyXBMCInitializeTypeObject(&RenderCapture_Type);

RenderCapture_Type.tp_name = (char*)"xbmc.RenderCapture";
RenderCapture_Type.tp_basicsize = sizeof(RenderCapture);
RenderCapture_Type.tp_dealloc = (destructor)RenderCapture_Dealloc;
RenderCapture_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
RenderCapture_Type.tp_doc = RenderCapture__doc__;
RenderCapture_Type.tp_methods = RenderCapture_methods;
RenderCapture_Type.tp_base = 0;
RenderCapture_Type.tp_new = RenderCapture_New;
}
}

#ifdef __cplusplus
}
#endif

45 changes: 45 additions & 0 deletions xbmc/interfaces/python/xbmcmodule/pyrendercapture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2011 Team XBMC
* http://www.xbmc.org
*
* 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, or (at your option)
* any later version.
*
* 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 XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#pragma once

#include <Python.h>

#include "cores/VideoRenderers/RenderCapture.h"

#ifdef __cplusplus
extern "C" {
#endif

namespace PYXBMC
{
typedef struct {
PyObject_HEAD
CRenderCapture* capture;
} RenderCapture;

extern PyTypeObject RenderCapture_Type;
void initRenderCapture_Type();
}

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 54e4ca5

Please sign in to comment.