⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textst_decoder.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
******************************************************************************
**                                                                          **
**  Copyright (c) 2005-2006 Videon Central, Inc.                            **
**  All rights reserved.                                                    **
**                                                                          **
**  The computer program contained herein contains proprietary information  **
**  which is the property of Videon Central, Inc.  The program may be used  **
**  and/or copied only with the written permission of Videon Central, Inc.  **
**  or in accordance with the terms and conditions stipulated in the        **
**  agreement/contract under which the programs have been supplied.         **
**                                                                          **
******************************************************************************
*****************************************************************************/

/**
 * @file textst_decoder.cpp
 *
 * $Revision: 1.7 $ 
 *
 * Text Subtitle decoder.
 * This is a private module that is intented to be used only by
 * modules internal to the TextST Module.
 *
 */

#include <string.h>
#include "vdvd_types.h"
#include "textst_decoder.h"
#include "textst_api.h"
#include "textst_render.h"
#include "textst_presctrl.h"
#include "osapi.h"
#include "utility.h"
#include "dbgprint.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif

/* Debug macros */
#define DBG_TEXTST_DECODER  DBG_ERROR
#define DBG_ON(x)           (DBG_TEXTST_DECODER >= x)

/**
 * TextST Decoder local handle
 */
typedef struct tagTEXTST_DECODER_HANDLE
{
    ULONG               ulTaskId;
    BOOLEAN             fExitPending;
    BOOLEAN             fStopPending;
    OS_SEM_ID           semWaitingStart;
    OS_SEM_ID           semSynch;
    ULONG               ulCurrentDPS;
} TEXTST_DECODER_HANDLE;

/**
 * Local variables
 */
static TEXTST_DECODER_HANDLE    *hTextSTDecoder = NULL;

/**
 * Local functions
 */
static ULONG            TextSTDecoderTask(PVOID pvParam);
static TEXTST_STATUS    textstdecoderParseDPS(TEXTST_INFO *hTextST, ULONG ulDPSNumber, TEXTST_RENDER_INFO *pRenderInfo, TEXTST_COMPOSITION_INFO *pCompInfo);
static TEXTST_STATUS    textstdecoderGetDPSOffset(TEXTST_INFO *hTextST, ULONG ulDPSNumber, ULONG *pByteOffset);
static TEXTST_STATUS    textstdecoderIsDPSContinuous(TEXTST_INFO *hTextST, ULONG ulDPSNumber, UBYTE *pContFlag);
/**
 * TextSTDecoderCreate --  Create the Text Subtitle Decoder.
 *
 * @param
 *      none
 *
 * @retval
 *      TEXTST_STATUS
 */
TEXTST_STATUS  TextSTDecoderCreate(TEXTST_INFO *hTextST)
{
    if (hTextSTDecoder != NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderCreate: Already created!\n"));
        goto errout;
    }

    /* Create the local handle */
    hTextSTDecoder = (TEXTST_DECODER_HANDLE *)OS_MemAlloc(sizeof(TEXTST_DECODER_HANDLE) );
    if (hTextSTDecoder == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderCreate: Failure creating local handle!\n"));
        goto errout;
    }

    /* Initialize TextST decoder handle */
    memset(hTextSTDecoder, 0, sizeof(TEXTST_DECODER_HANDLE) );

    /* Create waiting semaphore */
    hTextSTDecoder->semWaitingStart = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
    if (hTextSTDecoder->semWaitingStart == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderCreate: Failure creating waiting semaphore!\n"));
        goto errout;
    }

    /* Create synhronization semaphore */
    hTextSTDecoder->semSynch = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
    if (hTextSTDecoder->semSynch == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderCreate: Failure creating synch semaphore!\n"));
        goto errout;
    }

    /* Create the TextST Decoder task */
    hTextSTDecoder->ulTaskId = OS_TaskSpawnParam("TextSTDecoderTask", OS_TASK_HIGH_PRIORITY, 4096, TextSTDecoderTask, (PVOID)hTextST, NULL);
    if (hTextSTDecoder->ulTaskId == (ULONG)OS_FAILURE)
    {
        hTextSTDecoder->ulTaskId = 0;
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderCreate: Failure spawning task!\n"));
        goto errout;
    }

    return (TEXTST_SUCCESS);

errout:

    if (hTextSTDecoder != NULL)
    {
        if (hTextSTDecoder->ulTaskId != 0)
        {
            /* Force task to exit */
            hTextSTDecoder->fExitPending = TRUE;
            hTextSTDecoder->fStopPending = TRUE;
            OS_SemGive(hTextSTDecoder->semWaitingStart);

            /* Wait for task to exit then delete the task */
            OS_TaskJoin(hTextSTDecoder->ulTaskId);
            OS_TaskDelete(hTextSTDecoder->ulTaskId);
            hTextSTDecoder->ulTaskId = 0;
        }

        if (0 != hTextSTDecoder->semSynch)
        {
            /* Delete semaphore */
            OS_SemDelete(hTextSTDecoder->semSynch);
            hTextSTDecoder->semSynch = 0;
        }

        if (0 != hTextSTDecoder->semWaitingStart)
        {
            /* Delete semaphore */
            OS_SemDelete(hTextSTDecoder->semWaitingStart);
            hTextSTDecoder->semWaitingStart = 0;
        }

        /* Delete local handle */
        OS_MemFree(hTextSTDecoder);
        hTextSTDecoder = NULL;
    }

    return (TEXTST_FAILURE);
}

/**
 * TextSTDecoderDelete --  Delete the Text Subtitle Decoder.
 *
 * @param
 *      none
 *
 * @retval
 *      TEXTST_STATUS
 */
TEXTST_STATUS  TextSTDecoderDelete(void)
{
    if (hTextSTDecoder != NULL)
    {
        if (hTextSTDecoder->ulTaskId != 0)
        {
            /* Force task to exit */
            hTextSTDecoder->fExitPending = TRUE;
            hTextSTDecoder->fStopPending = TRUE;
            OS_SemGive(hTextSTDecoder->semWaitingStart);

            /* Wait for task to exit then delete the task */
            OS_TaskJoin(hTextSTDecoder->ulTaskId);
            OS_TaskDelete(hTextSTDecoder->ulTaskId);
            hTextSTDecoder->ulTaskId = 0;
        }

        if (0 != hTextSTDecoder->semSynch)
        {
            /* Delete semaphore */
            OS_SemDelete(hTextSTDecoder->semSynch);
            hTextSTDecoder->semSynch = 0;
        }

        if (0 != hTextSTDecoder->semWaitingStart)
        {
            /* Delete semaphore */
            OS_SemDelete(hTextSTDecoder->semWaitingStart);
            hTextSTDecoder->semWaitingStart = 0;
        }

        /* Delete local handle */
        OS_MemFree(hTextSTDecoder);
        hTextSTDecoder = NULL;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderDelete: Not created!\n"));
        return (TEXTST_FAILURE);
    }

    return (TEXTST_SUCCESS);
}

/**
 * TextSTDecoderStart --  Start the Text Subtitle Decoder.
 *
 * @param
 *      hTextST -- TextST Module handle
 *
 * @retval
 *      TEXTST_STATUS
 */
TEXTST_STATUS  TextSTDecoderStart(ULONG ulDPSNumber)
{
    if (hTextSTDecoder == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderStart: TextST Decoder not created!\n"));
        return (TEXTST_FAILURE);
    }

    /* Set the current DPS */
    hTextSTDecoder->ulCurrentDPS = ulDPSNumber;

    /* Clear flags */
    hTextSTDecoder->fExitPending = FALSE;
    hTextSTDecoder->fStopPending = FALSE;

    /* Signal that decoder should start */
    OS_SemGive(hTextSTDecoder->semWaitingStart);

    return (TEXTST_SUCCESS);
}

/**
 * TextSTDecoderStop --  Stop the Text Subtitle Decoder.
 *
 * @param
 *      hTextST -- TextST Module handle
 *
 * @retval
 *      TEXTST_STATUS
 */
TEXTST_STATUS  TextSTDecoderStop(void)
{
    if (hTextSTDecoder == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderStop: TextST Decoder not created!\n"));
        return (TEXTST_FAILURE);
    }

    /* Set stop flag */
    hTextSTDecoder->fStopPending = TRUE;

    /* Release decoder from waiting for a start */
    OS_SemGive(hTextSTDecoder->semWaitingStart);

    DBGPRINT(DBG_ON(DBG_TRACE), ("TextSTDecoderStop: wait for decoder to become stopped\n"));

    /* Wait for the decoder to become stopped */
    OS_SemTake(hTextSTDecoder->semSynch, OS_WAIT_FOREVER);

    return (TEXTST_SUCCESS);
}

/**
 * TextSTDecoderFlush --  Flush the Text Subtitle Decoder.
 *
 * @param
 *      hTextST -- TextST Module handle
 *
 * @retval
 *      TEXTST_STATUS
 */
TEXTST_STATUS  TextSTDecoderFlush(void)
{
    DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderFlush: stubbed\n"));
    return (TEXTST_NOT_IMPLEMENTED);
}

//////////////////////////////////////////////////////////////////////////////////
// Private Functions
//

/**
 * TextSTDecoderTask -- Task that runs during the life of the TextST Decoder.  All
 *                      TextST decoding occurs in the context of this task.
 */
static ULONG  TextSTDecoderTask(PVOID pvParam)
{
    TEXTST_INFO             *hTextST        = (TEXTST_INFO *)pvParam;
    TEXTST_RENDER_INFO      *pRenderInfo    = NULL;
    TEXTST_COMPOSITION_INFO *pCompInfo      = NULL;
    BOOLEAN                 fError          = FALSE;
    BOOLEAN                 fStartDPS;

    while (hTextSTDecoder->fExitPending == FALSE)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("TextSTDecoderTask: wait for start\n"));

        /* Initialize start flag */
        fStartDPS = TRUE;

        /* Wait until decoder is started */
        OS_SemTake(hTextSTDecoder->semWaitingStart, OS_WAIT_FOREVER);

        DBGPRINT(DBG_ON(DBG_TRACE), ("TextSTDecoderTask: decoder started\n"));

        while (hTextSTDecoder->fStopPending == FALSE)
        {
            if (pCompInfo == NULL)
            {
                /* Entering DCB critical section */
                OS_SemTake(hTextST->semDCB, OS_WAIT_FOREVER);

                /* Allocate a buffer from the Dialog Buffer to load rendering info */
                pCompInfo = (TEXTST_COMPOSITION_INFO *)OS_MemPoolAlloc(hTextST->mempoolDCB, sizeof(TEXTST_COMPOSITION_INFO) );
                if (pCompInfo == NULL)
                {
                    DBGPRINT(DBG_ON(DBG_VERBOSE), ("TextSTDecoderTask: Dialog Composition Buffer full!\n"));
                }

                /* Leaving DCB Critical Section */
                OS_SemGive(hTextST->semDCB);
            }

            if (pRenderInfo == NULL)
            {
                /* Entering DB critical section */
                OS_SemTake(hTextST->semDB, OS_WAIT_FOREVER);

                /* Allocate a buffer from the Dialog Buffer to load rendering info */
                pRenderInfo = (TEXTST_RENDER_INFO *)OS_MemPoolAlloc(hTextST->mempoolDB, sizeof(TEXTST_RENDER_INFO) );
                if (pRenderInfo == NULL)
                {
                    DBGPRINT(DBG_ON(DBG_VERBOSE), ("TextSTDecoderTask: Dialog Buffer full!\n"));
                }

                /* Leaving DB Critical Section */
                OS_SemGive(hTextST->semDB);
            }

            /*
             * Don't parse DPS until neither DB nor DCB is full.
             */
            if ( (pRenderInfo == NULL) || (pCompInfo ==  NULL) )
            {
                OS_TaskYield(); // avoid getting stuck in a tight loop
                continue;
            }

            /* Parse a single DPS */
            if (textstdecoderParseDPS(hTextST, hTextSTDecoder->ulCurrentDPS, pRenderInfo, pCompInfo) != TEXTST_SUCCESS)
            {
                DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderTask: Failed to parse DPS!\n"));
                fError = TRUE;
            }
            else
            {
                /*
                 * If palette update flag is set for this DPS (AND this is NOT a starting DPS), then no rendering
                 * needs to occur so just pass the composition info along to the
                 * presentation controller.  Otherwise, pass the rendering info to
                 * the textst renderer, as well as passing composition info to the
                 * presentation controller.
                 */
                if ( (pCompInfo->palette_update_flag == 0) || (fStartDPS == TRUE) )
                {
                    /* Pass the rendering info to the TextST Renderer */
                    if (TextSTRenderAddDPS(pRenderInfo) != TEXTST_SUCCESS)
                    {
                        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderTask: Failed to Add DPS to renderer queue\n"));
                        fError = TRUE;
                    }
                }
                else
                {
                    /* Don't need rendering info, so can release it */

                    /* Entering DB critical section */
                    OS_SemTake(hTextST->semDB, OS_WAIT_FOREVER);

                    /* Free memory from Dialog Buffer */
                    if (OS_MemPoolFree(hTextST->mempoolDB, pRenderInfo) != OS_OK)
                    {
                        DBGPRINT(DBG_ON(DBG_ERROR), ("TextSTDecoderTask: Failed to release buffer!\n"));
                    }

                    /* Leaving DB Critical Section */
                    OS_SemGive(hTextST->semDB);
                }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -