videoeditorengine/h263decoder/src/vdeims.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - Initial contribution
*
* Contributors:
* Ixonos Plc
*
* Description:  
* Frame memory organization module.
*
*/




/*
 * Includes
 */


#include "h263dConfig.h"
#include "vdeims.h"

#include "debug.h"
#include "vde.h"
#include "vdeimb.h"


/*
 * Structs and typedefs
 */

/* Structure for a single "Free" store */
typedef struct {
   LST_ITEM_SKELETON

   lifo_t freeStore;    /* a stack of free image store items */
   int lumWidth;        /* width of the items in freeStore */
   int lumHeight;       /* height of the items in freeStore
                           (in luminance pixels) */
   int fYuvNeeded;                            
} vdeImsFreeStore_t;


/*
 * Local function prototypes
 */

static vdeImsItem_t *vdeImsAllocItem(int lumWidth, int lumHeight, int fYuvNeeded);

static vdeImsFreeStore_t *vdeImsAllocFreeStore(int numFreeItems, 
   int lumWidth, int lumHeight, int fYuvNeeded);

static int vdeImsDeallocFreeStore(vdeImsFreeStore_t *store);

static int vdeImsGetFreeStore(lst_t *freeStoreList, int lumWidth, int lumHeight,
   vdeImsFreeStore_t **freeStore);


/*
 * Global functions
 */

/* {{-output"vdeImsChangeReference.txt"}} */
/*
 * vdeImsChangeReference
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    newItem                    new reference frame to replace a corresponding
 *                               reference frame in the image store
 *
 * Function:
 *    This function is used to change a reference frame in the image store.
 *    The function is passed a new reference frame. Then, the function
 *    searches for a reference frame with the same TR as the passed frame
 *    (from the image store). If such a frame is found, the function
 *    takes the old referece frame away from the reference store and puts
 *    it to the free or idle store depending on whether the frame has already
 *    been displayed or not. The new reference frame is placed into 
 *    the reference store. If a corresponding reference frame is not found
 *    from the image store, the function returns VDE_OK_NOT_AVAILABLE.
 *
 *    This function is intended to be used together with error concealment
 *    methods capable of repairing past frames.
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_OK_NOT_AVAILABLE       the function behaved as expected but
 *                               a requested frame was not found
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsChangeReference(vdeIms_t *store, vdeImsItem_t *newItem)
/* {{-output"vdeImsChangeReference.txt"}} */
{
   vdeImsItem_t *oldItem; /* old reference frame */

    /* Note: This case may not be ever used, but it is supported for 
     consistency */

    /* If the TRs of the reference frames do not match */
    if (store->refFrame->imb->tr == newItem->imb->tr)
     /* Return with not found indication */
     return VDE_OK_NOT_AVAILABLE;

    /* Store the new reference to the image store */
    oldItem = store->refFrame;
    store->refFrame = newItem;

    /* Add the old reference to the "Free" store */
    if (vdeImsPutFree(store, oldItem) < 0)
         return VDE_ERROR;

   return VDE_OK;
}


/* {{-output"vdeImsClose.txt"}} */
/*
 * vdeImsClose
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *
 * Function:
 *    This function closes the given image store.
 *    Notice that the memory pointed by the given image store pointer is not
 *    deallocated but rather it is assumed that this memory is either static
 *    or externally deallocated.
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsClose(vdeIms_t *store)
/* {{-output"vdeImsClose.txt"}} */
{
   vdeImb_t *imb;
   vdeImsFreeStore_t *freeStore;
   vdeImsItem_t *pItem;

   /* freeStoreList */
   if (lstHead(&store->freeStoreList, (void **) &freeStore) < 0)
      return VDE_ERROR;

   do {
      if (lstRemove(&store->freeStoreList, (void **) &freeStore) < 0)
         return VDE_ERROR;
      
      if (freeStore) {
         if (vdeImsDeallocFreeStore(freeStore) < 0)
            return VDE_ERROR;
      }
   } while (freeStore);

   if (lstClose(&store->freeStoreList) < 0)
      return VDE_ERROR;

   if (store->refFrame) {
     vdeImbDealloc(store->refFrame->imb);
     vdeDealloc(store->refFrame);
   }

   /* idleStore */
   if (lstHead(&store->idleStore, (void **) &pItem) < 0)
      return VDE_ERROR;

   do {
      if (lstRemove(&store->idleStore, (void **) &pItem) < 0)
         return VDE_ERROR;

      if (pItem) {
         imb = pItem->imb;
         vdeDealloc(pItem);
         vdeImbDealloc(imb);
      }
   } while (pItem);

   if (lstClose(&store->idleStore) < 0)
      return VDE_ERROR;

   return VDE_OK;
}



/* {{-output"vdeImsGetFree.txt"}} */
/*
 * vdeImsGetFree
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    lumWidth                   width of the luminance image (in pixels)
 *    lumHeight                  height of the luminance image (in pixels)
 *    item                       a free image store item
 *
 * Function:
 *    This function is used to get a free frame memory (of requested size).
 *    If a free frame memory (image store item) does not exist, a new one
 *    is allocated and initialized.
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsGetFree(vdeIms_t *store, int lumWidth, int lumHeight, 
   vdeImsItem_t **item)
/* {{-output"vdeImsGetFree.txt"}} */
{
   vdeImsFreeStore_t *freeStore, *tmpFreeStore;
   vdeImsItem_t *pItem;

   if (vdeImsGetFreeStore(&store->freeStoreList, lumWidth, lumHeight, 
      &freeStore) < 0)
      return VDE_ERROR;

   if (freeStore) {
      if (lifoGet(&freeStore->freeStore, (void **) &pItem) < 0)
         return VDE_ERROR;
      if (pItem) {
         *item = pItem;
         return VDE_OK;
      }
      else {
         *item = vdeImsAllocItem(lumWidth, lumHeight, store->fYuvNeeded);
         return VDE_OK;
      }
   }

   else {
      freeStore = vdeImsAllocFreeStore(0, lumWidth, lumHeight, store->fYuvNeeded);
      if (freeStore == NULL)
         return VDE_ERROR;

      if (lstHead(&store->freeStoreList, (void **) &tmpFreeStore) < 0) {
         vdeImsDeallocFreeStore(freeStore);
         return VDE_ERROR;
      }

      if (lstAdd(&store->freeStoreList, freeStore) < 0) {
         vdeImsDeallocFreeStore(freeStore);
         return VDE_ERROR;
      }

      *item = vdeImsAllocItem(lumWidth, lumHeight, store->fYuvNeeded);
      return VDE_OK;
   }
}


/* {{-output"vdeImsGetReference.txt"}} */
/*
 * vdeImsGetReference
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    mode                       VDEIMS_REF_LATEST = latest reference frame
 *                               VDEIMS_REF_OLDEST = oldest reference frame
 *                               VDEIMS_REF_TR = frame specified by tr,
 *                                  see also the explation for
 *                                  VDEIMS_GET_CLOSEST_REFERENCE
 *                                  in the module description at the beginning
 *                                  of this file
 *    tr                         if mode is equal to VDEIMS_REF_TR,
 *                               this parameter specifies the TR (temporal
 *                               reference) of the reference frame
 *    item                       used to return the specified reference frame
 *
 * Function:
 *    This function is used to get a reference frame memory (image store item).
 *    One can either query for the latest reference frame or for a frame
 *    having a certain temporal reference value.
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsGetReference(vdeIms_t *store, int mode, int tr, vdeImsItem_t **item)
/* {{-output"vdeImsGetReference.txt"}} */
{
   vdeAssert(
      mode == VDEIMS_REF_LATEST || 
      mode == VDEIMS_REF_OLDEST || 
      mode == VDEIMS_REF_TR);

   switch (mode) {
      case VDEIMS_REF_LATEST:
         *item = store->refFrame;
         break;

      case VDEIMS_REF_OLDEST:
         *item = store->refFrame;
         break;

      case VDEIMS_REF_TR:
         /* This section of code returns the reference frame having the same
            TR as requested. If there is no such TR, the code returns a NULL
            frame. */
         if (store->refFrame->imb->tr == tr)
             *item = store->refFrame;
         else
             *item = NULL;
         break;
   }        

   return VDE_OK;
}


/* {{-output"vdeImsOpen.txt"}} */
/*
 * vdeImsOpen
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    numFreeItems               number of initial free image store items
 *    lumWidth                   width of the luminance image (in pixels)
 *                               for free items
 *    lumHeight                  height of the luminance image (in pixels)
 *                               for free items
 *
 * Function:
 *    This function initializes the given image store. The function allocates
 *    and initializes a given number of free image store items of given size.
 *    The Reference image store is initialized to carry multiple image store
 *    items, if the Reference Picture Selection mode is indicated. Otherwise,
 *    the Reference image store carries only one image store item at a time.
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsOpen(vdeIms_t *store, int /*numFreeItems*/, int /*lumWidth*/, int /*lumHeight*/)
{
   vdeImsFreeStore_t *freeStore;

   store->refFrame = 0;

   if (lstOpen(&store->idleStore) < 0)
      goto errIdleStore;
   
// not ready to open freeStore yet
    freeStore = NULL;

   if (lstOpen(&store->freeStoreList) < 0)
      goto errOpenFreeStoreList;


   return VDE_OK;

   /* Error cases */
   errOpenFreeStoreList:

   vdeImsDeallocFreeStore(freeStore);

   lstClose(&store->idleStore);
   errIdleStore:

   return VDE_ERROR;
}

void vdeImsSetYUVNeed(vdeIms_t *store, int fYuvNeeded)
{
    store->fYuvNeeded = fYuvNeeded;
}
    
/* {{-output"vdeImsPut.txt"}} */
/*
 * vdeImsPut
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    item                       image store item to put into the image store
 *
 * Function:
 *    This function is used to return a filled image store item into
 *    the image store. If the item is possibly referenced later on, it is
 *    stored into the Reference store. If the item is not referenced but
 *    it is going to be displayed, it is put into the Idle store.
 *    Otherwise, the item is put into the Free store. 
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsPut(vdeIms_t *store, vdeImsItem_t *item)
/* {{-output"vdeImsPut.txt"}} */
{
   vdeImb_t *imb;

   imb = item->imb;

   /* If the item is referenced */
   if (imb->fReferenced) {

     /* If an old reference exists */
     if (store->refFrame) {
       /* Add the old reference to the "Free" store */
       if (vdeImsPutFree(store, store->refFrame) < 0)
          return VDE_ERROR;
     }

     store->refFrame = item;
   }

   /* Else (the item is not referenced) */
   else {
     /* Add the item to the "Free" store */
     if (vdeImsPutFree(store, item) < 0)
        return VDE_ERROR;
   }

   return VDE_OK;
}


/* {{-output"vdeImsPutFree.txt"}} */
/*
 * vdeImsPutFree
 *    
 *
 * Parameters:
 *    store                      a pointer to an image store
 *    item                       image store item to put into the Free store
 *
 * Function:
 *    This function puts an image store item to a suitable Free store
 *    of the passed image store. It selects the Free store according to 
 *    the image size or creates a new Free store if a suitable Free store 
 *    does not already exist.
 *
 *    One can use this function instead of vdeImsPut to explicitly discard
 *    an image store item (whereas for vdeImsPut, one would have to set
 *    the correct flags and pass a NULL renderer handle to get the same
 *    effect).
 *
 * Returns:
 *    VDE_OK                     if the function was successful
 *    VDE_ERROR                  if an error occured
 *
 *    
 */

int vdeImsPutFree(vdeIms_t *store, vdeImsItem_t *item)
/* {{-output"vdeImsPutFree.txt"}} */
{
   vdeImsFreeStore_t *freeStore, *tmpFreeStore;
   int 
      lumWidth = renDriBitmapWidth(item->imb->drawItem),
      lumHeight = renDriBitmapHeight(item->imb->drawItem);

   if (vdeImsGetFreeStore(&store->freeStoreList, lumWidth, 
      lumHeight, &freeStore) < 0)
      return VDE_ERROR;

   if (freeStore == NULL) {
      /* The same algorithm as in vdeImsGetFree */
      freeStore = vdeImsAllocFreeStore(0, lumWidth, lumHeight, store->fYuvNeeded);
      if (freeStore == NULL)
         return VDE_ERROR;

      if (lstHead(&store->freeStoreList, (void **) &tmpFreeStore) < 0) {
         vdeImsDeallocFreeStore(freeStore);
         return VDE_ERROR;
      }

      if (lstAdd(&store->freeStoreList, freeStore) < 0) {
         vdeImsDeallocFreeStore(freeStore);
         return VDE_ERROR;
      }
   }

   if (lifoPut(&freeStore->freeStore, item) < 0)
      return VDE_ERROR;

   return VDE_OK;
}




/*
 * Local functions
 */

/*
 * vdeImsAllocItem
 *    This function allocates and initializes a new image store item
 *    of given size.
 */

static vdeImsItem_t *vdeImsAllocItem(int lumWidth, int lumHeight, int fYuvNeeded)
{
   vdeImb_t *imb;
   vdeImsItem_t *pItem;

   imb = vdeImbAlloc(lumWidth, lumHeight, fYuvNeeded);
   if (imb == NULL)
      return NULL;

   pItem = (vdeImsItem_t *) vdeMalloc(sizeof(vdeImsItem_t));
   if (pItem == NULL) {
      vdeImbDealloc(imb);
      return NULL;
   }

   pItem->imb = imb;

   return pItem;
}


/*
 * vdeImsAllocFreeStore
 *    This function allocates and initializes a new Free store.
 *    In addition, it allocates a given number of free image store items
 *    of given size and puts these items into the created Free store.
 */

static vdeImsFreeStore_t *vdeImsAllocFreeStore(int numFreeItems, 
   int lumWidth, int lumHeight, int fYuvNeeded)
{
   int i;
   vdeImsFreeStore_t *store;
   vdeImsItem_t *pItem;

   store = (vdeImsFreeStore_t *) vdeMalloc(sizeof(vdeImsFreeStore_t));
   if (store == NULL)
      return NULL;

   store->lumWidth = lumWidth;
   store->lumHeight = lumHeight;
   store->fYuvNeeded = fYuvNeeded;

   if (lifoOpen(&store->freeStore) < 0) {
      vdeDealloc(store);
      return NULL;
   }

   for (i = 0; i < numFreeItems; i++) {
      pItem = vdeImsAllocItem(lumWidth, lumHeight, fYuvNeeded);
      if (pItem == NULL)
         goto error;

      if (lifoPut(&store->freeStore, pItem) < 0)
         goto error;
   }

   return store;

   error:
   if (pItem)
      vdeDealloc(pItem);
   vdeImsDeallocFreeStore(store);
   return NULL;
}


/*
 * vdeImsDeallocFreeStore
 *    This function deallocates a given Free store and all image store items
 *    which were in the store.
 */

static int vdeImsDeallocFreeStore(vdeImsFreeStore_t *store)
{
   vdeImb_t *imb;
   vdeImsItem_t *pItem;

   do {
      if (lifoGet(&store->freeStore, (void **) &pItem) < 0)
         return VDE_ERROR;
      
      if (pItem) {
         imb = pItem->imb;
         vdeDealloc(pItem);
         vdeImbDealloc(imb);
      }
   } while (pItem);

   if (lifoClose(&store->freeStore) < 0)
      return VDE_ERROR;

   vdeDealloc(store);

   return VDE_OK;
}




/*
 * vdeImsGetFreeStore
 *    This function returns a pointer to a Free store which contains frames of
 *    requested size. The Free store is searched from a list of Free stores.
 */

static int vdeImsGetFreeStore(lst_t *freeStoreList, int lumWidth, int lumHeight,
   vdeImsFreeStore_t **freeStore)
{
   if (lstHead(freeStoreList, (void **) freeStore) < 0)
      return VDE_ERROR;

   while (*freeStore && 
      ((*freeStore)->lumWidth != lumWidth || (*freeStore)->lumHeight != lumHeight)) {
      if (lstNext(freeStoreList, (void **) freeStore) < 0)
         return VDE_ERROR;
   }

   return VDE_OK;
}
// End of File