summaryrefslogtreecommitdiff
path: root/Xext/xvmc.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:57 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:57 +0000
commit9508a382f8a9f241dab097d921b6d290c1c3a776 (patch)
treefa456480bae7040c3f971a70b390f2d091c680b5 /Xext/xvmc.c
parentded6147bfb5d75ff1e67c858040a628b61bc17d1 (diff)
Initial revision
Diffstat (limited to 'Xext/xvmc.c')
-rw-r--r--Xext/xvmc.c674
1 files changed, 674 insertions, 0 deletions
diff --git a/Xext/xvmc.c b/Xext/xvmc.c
new file mode 100644
index 000000000..7e99e11a5
--- /dev/null
+++ b/Xext/xvmc.c
@@ -0,0 +1,674 @@
+/* $XFree86: xc/programs/Xserver/Xext/xvmc.c,v 1.7 2001/11/18 23:55:48 mvojkovi Exp $ */
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#include "Xfuncproto.h"
+#include "xvdix.h"
+#include "XvMC.h"
+#include "Xvproto.h"
+#include "XvMCproto.h"
+#include "xvmcext.h"
+
+int XvMCScreenIndex = -1;
+
+unsigned long XvMCGeneration = 0;
+
+int XvMCReqCode;
+int XvMCEventBase;
+int XvMCErrorBase;
+
+unsigned long XvMCRTContext;
+unsigned long XvMCRTSurface;
+unsigned long XvMCRTSubpicture;
+
+typedef struct {
+ int num_adaptors;
+ XvMCAdaptorPtr adaptors;
+ CloseScreenProcPtr CloseScreen;
+} XvMCScreenRec, *XvMCScreenPtr;
+
+#define XVMC_GET_PRIVATE(pScreen) \
+ (XvMCScreenPtr)((pScreen)->devPrivates[XvMCScreenIndex].ptr)
+
+
+static int
+XvMCDestroyContextRes(pointer data, XID id)
+{
+ XvMCContextPtr pContext = (XvMCContextPtr)data;
+
+ pContext->refcnt--;
+
+ if(!pContext->refcnt) {
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext);
+ xfree(pContext);
+ }
+
+ return Success;
+}
+
+static int
+XvMCDestroySurfaceRes(pointer data, XID id)
+{
+ XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data;
+ XvMCContextPtr pContext = pSurface->context;
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface);
+ xfree(pSurface);
+
+ XvMCDestroyContextRes((pointer)pContext, pContext->context_id);
+
+ return Success;
+}
+
+
+static int
+XvMCDestroySubpictureRes(pointer data, XID id)
+{
+ XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data;
+ XvMCContextPtr pContext = pSubpict->context;
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict);
+ xfree(pSubpict);
+
+ XvMCDestroyContextRes((pointer)pContext, pContext->context_id);
+
+ return Success;
+}
+
+static void
+XvMCResetProc (ExtensionEntry *extEntry)
+{
+}
+
+
+static int
+ProcXvMCQueryVersion(ClientPtr client)
+{
+ xvmcQueryVersionReply rep;
+ /* REQUEST(xvmcQueryVersionReq); */
+ REQUEST_SIZE_MATCH(xvmcQueryVersionReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.major = XvMCVersion;
+ rep.minor = XvMCRevision;
+ WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep);
+ return Success;
+}
+
+
+static int
+ProcXvMCListSurfaceTypes(ClientPtr client)
+{
+ XvPortPtr pPort;
+ int i;
+ XvMCScreenPtr pScreenPriv;
+ xvmcListSurfaceTypesReply rep;
+ xvmcSurfaceInfo info;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface;
+ REQUEST(xvmcListSurfaceTypesReq);
+ REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq);
+
+ if(!(pPort = LOOKUP_PORT(stuff->port, client))) {
+ client->errorValue = stuff->port;
+ return _XvBadPort;
+ }
+
+ if(XvMCScreenIndex >= 0) { /* any adaptors at all */
+ ScreenPtr pScreen = pPort->pAdaptor->pScreen;
+ if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+ }
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.num = (adaptor) ? adaptor->num_surfaces : 0;
+ rep.length = rep.num * sizeof(xvmcSurfaceInfo) >> 2;
+
+ WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep);
+
+ for(i = 0; i < rep.num; i++) {
+ surface = adaptor->surfaces[i];
+ info.surface_type_id = surface->surface_type_id;
+ info.chroma_format = surface->chroma_format;
+ info.max_width = surface->max_width;
+ info.max_height = surface->max_height;
+ info.subpicture_max_width = surface->subpicture_max_width;
+ info.subpicture_max_height = surface->subpicture_max_height;
+ info.mc_type = surface->mc_type;
+ info.flags = surface->flags;
+ WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info);
+ }
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateContext(ClientPtr client)
+{
+ XvPortPtr pPort;
+ CARD32 *data = NULL;
+ int dwords = 0;
+ int i, result, adapt_num = -1;
+ ScreenPtr pScreen;
+ XvMCContextPtr pContext;
+ XvMCScreenPtr pScreenPriv;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface = NULL;
+ xvmcCreateContextReply rep;
+ REQUEST(xvmcCreateContextReq);
+ REQUEST_SIZE_MATCH(xvmcCreateContextReq);
+
+ if(!(pPort = LOOKUP_PORT(stuff->port, client))) {
+ client->errorValue = stuff->port;
+ return _XvBadPort;
+ }
+
+ pScreen = pPort->pAdaptor->pScreen;
+
+ if(XvMCScreenIndex < 0) /* no XvMC adaptors */
+ return BadMatch;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */
+ return BadMatch;
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ adapt_num = i;
+ break;
+ }
+ }
+
+ if(adapt_num < 0) /* none this port */
+ return BadMatch;
+
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ /* adaptor doesn't support this suface_type_id */
+ if(!surface) return BadMatch;
+
+
+ if((stuff->width > surface->max_width) ||
+ (stuff->height > surface->max_height))
+ return BadValue;
+
+ if(!(pContext = xalloc(sizeof(XvMCContextRec)))) {
+ return BadAlloc;
+ }
+
+
+ pContext->pScreen = pScreen;
+ pContext->adapt_num = adapt_num;
+ pContext->context_id = stuff->context_id;
+ pContext->surface_type_id = stuff->surface_type_id;
+ pContext->width = stuff->width;
+ pContext->height = stuff->height;
+ pContext->flags = stuff->flags;
+ pContext->refcnt = 1;
+
+ result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data);
+
+ if(result != Success) {
+ xfree(pContext);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.width_actual = pContext->width;
+ rep.height_actual = pContext->height;
+ rep.flags_return = pContext->flags;
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pContext->context_id, XvMCRTContext, pContext);
+
+ if(data)
+ xfree(data);
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroyContext(ClientPtr client)
+{
+ REQUEST(xvmcDestroyContextReq);
+ REQUEST_SIZE_MATCH(xvmcDestroyContextReq);
+
+ if(!LookupIDByType(stuff->context_id, XvMCRTContext))
+ return (XvMCBadContext + XvMCErrorBase);
+
+ FreeResource(stuff->context_id, RT_NONE);
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateSurface(ClientPtr client)
+{
+ CARD32 *data = NULL;
+ int dwords = 0;
+ int result;
+ XvMCContextPtr pContext;
+ XvMCSurfacePtr pSurface;
+ XvMCScreenPtr pScreenPriv;
+ xvmcCreateSurfaceReply rep;
+ REQUEST(xvmcCreateSurfaceReq);
+ REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq);
+
+ if(!(pContext = LookupIDByType(stuff->context_id, XvMCRTContext)))
+ return (XvMCBadContext + XvMCErrorBase);
+
+ pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ if(!(pSurface = xalloc(sizeof(XvMCSurfaceRec))))
+ return BadAlloc;
+
+ pSurface->surface_id = stuff->surface_id;
+ pSurface->surface_type_id = pContext->surface_type_id;
+ pSurface->context = pContext;
+
+ result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)(
+ pSurface, &dwords, &data);
+
+ if(result != Success) {
+ xfree(pSurface);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pSurface->surface_id, XvMCRTSurface, pSurface);
+
+ if(data)
+ xfree(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySurface(ClientPtr client)
+{
+ REQUEST(xvmcDestroySurfaceReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq);
+
+ if(!LookupIDByType(stuff->surface_id, XvMCRTSurface))
+ return (XvMCBadSurface + XvMCErrorBase);
+
+ FreeResource(stuff->surface_id, RT_NONE);
+
+ return Success;
+}
+
+static int
+ProcXvMCCreateSubpicture(ClientPtr client)
+{
+ Bool image_supported = FALSE;
+ CARD32 *data = NULL;
+ int i, result, dwords = 0;
+ XvMCContextPtr pContext;
+ XvMCSubpicturePtr pSubpicture;
+ XvMCScreenPtr pScreenPriv;
+ xvmcCreateSubpictureReply rep;
+ XvMCAdaptorPtr adaptor;
+ XvMCSurfaceInfoPtr surface = NULL;
+ REQUEST(xvmcCreateSubpictureReq);
+ REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq);
+
+ if(!(pContext = LookupIDByType(stuff->context_id, XvMCRTContext)))
+ return (XvMCBadContext + XvMCErrorBase);
+
+ pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen);
+
+ adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]);
+
+ /* find which surface this context supports */
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ if(!surface) return BadMatch;
+
+ /* make sure this surface supports that xvimage format */
+ if(!surface->compatible_subpictures) return BadMatch;
+
+ for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) {
+ if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) {
+ image_supported = TRUE;
+ break;
+ }
+ }
+
+ if(!image_supported) return BadMatch;
+
+ /* make sure the size is OK */
+ if((stuff->width > surface->subpicture_max_width) ||
+ (stuff->height > surface->subpicture_max_height))
+ return BadValue;
+
+ if(!(pSubpicture = xalloc(sizeof(XvMCSubpictureRec))))
+ return BadAlloc;
+
+ pSubpicture->subpicture_id = stuff->subpicture_id;
+ pSubpicture->xvimage_id = stuff->xvimage_id;
+ pSubpicture->width = stuff->width;
+ pSubpicture->height = stuff->height;
+ pSubpicture->num_palette_entries = 0; /* overwritten by DDX */
+ pSubpicture->entry_bytes = 0; /* overwritten by DDX */
+ pSubpicture->component_order[0] = 0; /* overwritten by DDX */
+ pSubpicture->component_order[1] = 0;
+ pSubpicture->component_order[2] = 0;
+ pSubpicture->component_order[3] = 0;
+ pSubpicture->context = pContext;
+
+ result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)(
+ pSubpicture, &dwords, &data);
+
+ if(result != Success) {
+ xfree(pSubpicture);
+ return result;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.width_actual = pSubpicture->width;
+ rep.height_actual = pSubpicture->height;
+ rep.num_palette_entries = pSubpicture->num_palette_entries;
+ rep.entry_bytes = pSubpicture->entry_bytes;
+ rep.component_order[0] = pSubpicture->component_order[0];
+ rep.component_order[1] = pSubpicture->component_order[1];
+ rep.component_order[2] = pSubpicture->component_order[2];
+ rep.component_order[3] = pSubpicture->component_order[3];
+ rep.length = dwords;
+
+ WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep);
+ if(dwords)
+ WriteToClient(client, dwords << 2, (char*)data);
+ AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture);
+
+ if(data)
+ xfree(data);
+
+ pContext->refcnt++;
+
+ return Success;
+}
+
+static int
+ProcXvMCDestroySubpicture(ClientPtr client)
+{
+ REQUEST(xvmcDestroySubpictureReq);
+ REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq);
+
+ if(!LookupIDByType(stuff->subpicture_id, XvMCRTSubpicture))
+ return (XvMCBadSubpicture + XvMCErrorBase);
+
+ FreeResource(stuff->subpicture_id, RT_NONE);
+
+ return Success;
+}
+
+
+static int
+ProcXvMCListSubpictureTypes(ClientPtr client)
+{
+ XvPortPtr pPort;
+ xvmcListSubpictureTypesReply rep;
+ XvMCScreenPtr pScreenPriv;
+ ScreenPtr pScreen;
+ XvMCAdaptorPtr adaptor = NULL;
+ XvMCSurfaceInfoPtr surface = NULL;
+ xvImageFormatInfo info;
+ XvImagePtr pImage;
+ int i, j;
+ REQUEST(xvmcListSubpictureTypesReq);
+ REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq);
+
+ if(!(pPort = LOOKUP_PORT(stuff->port, client))) {
+ client->errorValue = stuff->port;
+ return _XvBadPort;
+ }
+
+ pScreen = pPort->pAdaptor->pScreen;
+
+ if(XvMCScreenIndex < 0) /* No XvMC adaptors */
+ return BadMatch;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
+ return BadMatch; /* None this screen */
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+
+ if(!adaptor) return BadMatch;
+
+ for(i = 0; i < adaptor->num_surfaces; i++) {
+ if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) {
+ surface = adaptor->surfaces[i];
+ break;
+ }
+ }
+
+ if(!surface) return BadMatch;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.num = 0;
+ if(surface->compatible_subpictures)
+ rep.num = surface->compatible_subpictures->num_xvimages;
+
+ rep.length = rep.num * sizeof(xvImageFormatInfo) >> 2;
+
+ WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep);
+
+ for(i = 0; i < rep.num; i++) {
+ pImage = NULL;
+ for(j = 0; j < adaptor->num_subpictures; j++) {
+ if(surface->compatible_subpictures->xvimage_ids[i] ==
+ adaptor->subpictures[j]->id)
+ {
+ pImage = adaptor->subpictures[j];
+ break;
+ }
+ }
+ if(!pImage) return BadImplementation;
+
+ info.id = pImage->id;
+ info.type = pImage->type;
+ info.byte_order = pImage->byte_order;
+ memcpy(&info.guid, pImage->guid, 16);
+ info.bpp = pImage->bits_per_pixel;
+ info.num_planes = pImage->num_planes;
+ info.depth = pImage->depth;
+ info.red_mask = pImage->red_mask;
+ info.green_mask = pImage->green_mask;
+ info.blue_mask = pImage->blue_mask;
+ info.format = pImage->format;
+ info.y_sample_bits = pImage->y_sample_bits;
+ info.u_sample_bits = pImage->u_sample_bits;
+ info.v_sample_bits = pImage->v_sample_bits;
+ info.horz_y_period = pImage->horz_y_period;
+ info.horz_u_period = pImage->horz_u_period;
+ info.horz_v_period = pImage->horz_v_period;
+ info.vert_y_period = pImage->vert_y_period;
+ info.vert_u_period = pImage->vert_u_period;
+ info.vert_v_period = pImage->vert_v_period;
+ memcpy(&info.comp_order, pImage->component_order, 32);
+ info.scanline_order = pImage->scanline_order;
+ WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info);
+ }
+
+ return Success;
+}
+
+
+
+int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = {
+ ProcXvMCQueryVersion,
+ ProcXvMCListSurfaceTypes,
+ ProcXvMCCreateContext,
+ ProcXvMCDestroyContext,
+ ProcXvMCCreateSurface,
+ ProcXvMCDestroySurface,
+ ProcXvMCCreateSubpicture,
+ ProcXvMCDestroySubpicture,
+ ProcXvMCListSubpictureTypes
+};
+
+static int
+ProcXvMCDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if(stuff->data < xvmcNumRequest)
+ return (*ProcXvMCVector[stuff->data])(client);
+ else
+ return BadRequest;
+}
+
+static int
+SProcXvMCDispatch (ClientPtr client)
+{
+ /* We only support local */
+ return BadImplementation;
+}
+
+void
+XvMCExtensionInit()
+{
+ ExtensionEntry *extEntry;
+
+ if(XvMCScreenIndex < 0) /* nobody supports it */
+ return;
+
+ if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes)))
+ return;
+
+ if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes)))
+ return;
+
+ if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes)))
+ return;
+
+ extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors,
+ ProcXvMCDispatch, SProcXvMCDispatch,
+ XvMCResetProc, StandardMinorOpcode);
+
+ if(!extEntry) return;
+
+ XvMCReqCode = extEntry->base;
+ XvMCEventBase = extEntry->eventBase;
+ XvMCErrorBase = extEntry->errorBase;
+}
+
+static Bool
+XvMCCloseScreen (int i, ScreenPtr pScreen)
+{
+ XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+
+ xfree(pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+
+int
+XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt)
+{
+ XvMCScreenPtr pScreenPriv;
+
+ if(XvMCGeneration != serverGeneration) {
+ if((XvMCScreenIndex = AllocateScreenPrivateIndex()) < 0)
+ return BadAlloc;
+
+ XvMCGeneration = serverGeneration;
+ }
+
+ if(!(pScreenPriv = (XvMCScreenPtr)xalloc(sizeof(XvMCScreenRec))))
+ return BadAlloc;
+
+ pScreen->devPrivates[XvMCScreenIndex].ptr = (pointer)pScreenPriv;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = XvMCCloseScreen;
+
+ pScreenPriv->num_adaptors = num;
+ pScreenPriv->adaptors = pAdapt;
+
+ return Success;
+}
+
+XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id)
+{
+ XvImagePtr pImage = NULL;
+ ScreenPtr pScreen = pPort->pAdaptor->pScreen;
+ XvMCScreenPtr pScreenPriv;
+ XvMCAdaptorPtr adaptor = NULL;
+ int i;
+
+ if(XvMCScreenIndex < 0) return NULL;
+
+ if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen)))
+ return NULL;
+
+ for(i = 0; i < pScreenPriv->num_adaptors; i++) {
+ if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) {
+ adaptor = &(pScreenPriv->adaptors[i]);
+ break;
+ }
+ }
+
+ if(!adaptor) return NULL;
+
+ for(i = 0; i < adaptor->num_subpictures; i++) {
+ if(adaptor->subpictures[i]->id == id) {
+ pImage = adaptor->subpictures[i];
+ break;
+ }
+ }
+
+ return pImage;
+}