📄 pe_istreamctrl.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 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 pe_istreamctrl.cpp
*
* $Revision: 1.29 $
*
* Presentation Engine Stream Control Interface source file.
*
*/
#include <stdlib.h>
#include "decoder.h"
#include "vdvd_types.h"
#include "osapi.h"
#include "msg_app.h"
#include "dbgprint.h"
#include "utility.h"
#include "pe_app.h"
#include "pe_consumer.h"
#include "pe_consumer_dvd.h"
#include "pe_consumer_vcd.h"
#if BDROM_ENABLE
#include "pe_consumer_bdrom.h"
#endif
#include "pe_consumer_cdda.h"
#ifdef HDDVD_ENABLE
#include "pe_consumer_hddvd_std.h"
#include "pe_consumer_hddvd_adv.h"
#endif
#include "pe_types.h"
#include "usrapi.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
/* THE TODO LIST
*
* @todo - set audio type is not implemented.
* @todo - get state should return info about the PEConsumers
*/
#define DEBUG_ISTRMCTRL DBG_ERROR
#define DBG_ON(x) (DEBUG_ISTRMCTRL >= x)
#define PE_STACK_SIZE (16*1024)
#define PE_TASK_PRIORITY 130
#define PE_VSYNC_CALLBACK_DEPTH 4
#define PE_CALLBACK_DEPTH 7 /* 3 for pres start / decode end, and 4 for timestamp */
extern IDirectFB *pDfb;
BOOLEAN fMainStarted;
/*
* Private Function Prototypes
****************************************************************************/
static ULONG peiStrmEngine(PVOID pvParam);
static PE_STATUS peiStrmKillTasks(ISTREAMCTRLHANDLE *iStrmCtrl);
static PE_STATUS peiStrmConfigGraphics(DfbExtHandle *layer, int screen_width, int screen_height, IDirectFBDisplayLayer **disp_layer);
static PE_STATUS peiStrmResetGraphics(IDirectFBDisplayLayer **disp_layer);
static void peDecodeNotify_cb(Decoder* decoder, DECODE_EVENT_TYPE event, void *event_data, void *context);
static ULONG peiStrmDecoderEventTask(PVOID pvParam);
static PE_STATUS peiStrmSetGraphicsAspectRatio(DfbExtHandle *layer_handle, PE_ICONFIGURE_VIDEO_FORMAT VideoFormat,
PE_ICONFIGURE_ASPECT_RATIO ScreenAspect, PE_ISTREAMCTRL_SOURCE_ASPECT_RATIO SourceAspect);
/**
* Create the iStrmCtrl interface.
*
* @param PEManager - Handle to PE manager. This can be used to obtain access to the other PE interfaces.
*
* @return iStrmCtrl handle.
*/
ISTREAMCTRLHANDLE* PECreateiStreamCtrl(PE_HANDLE PEManager)
{
VDVD_ERROR error = VDVD_SUCCESS;
ISTREAMCTRLHANDLE* iStrmCtrl = NULL;
ICONFIGUREHANDLE* iConfigure = NULL;
PEHANDLE* pe = NULL;
int i;
DbgAssert(PEManager != NULL);
pe = (PEHANDLE*)PEManager;
iConfigure = pe->iConfigure;
DbgAssert(iConfigure != NULL);
/* allocate the iStrmCtrl handle */
iStrmCtrl = (ISTREAMCTRLHANDLE*)OS_MemAlloc(sizeof(ISTREAMCTRLHANDLE));
if (iStrmCtrl == NULL)
{
goto error_out;
}
/* initial conditions */
iStrmCtrl->SystemState = PE_ISTREAMCTRL_STATE_UNREALIZED;
iStrmCtrl->StreamType = STREAM_TYPE_INVALID;
iStrmCtrl->AudioType = AUDIO_TYPE_INVALID;
iStrmCtrl->VideoType = VIDEO_TYPE_INVALID;
iStrmCtrl->fKillTasks = FALSE;
iStrmCtrl->pMsgQ = NULL;
iStrmCtrl->pMsgQPool = NULL;
iStrmCtrl->pCallbackMsgQ = NULL;
iStrmCtrl->pCallbackMsgQPool = NULL;
iStrmCtrl->m_decoders.spu = NULL;
iStrmCtrl->semCountingVsync = 0;
#if BDROM_ENABLE
iStrmCtrl->m_decoders.pg_dec = NULL;
iStrmCtrl->m_decoders.ig_dec = NULL;
iStrmCtrl->m_decoders.st_dec = NULL;
#endif
iStrmCtrl->ig_dfb_disp_layer = NULL;
iStrmCtrl->pg_dfb_disp_layer = NULL;
iStrmCtrl->GraphicsMode = GRAPHICS_MODE_NOT_SET;
iStrmCtrl->sendMsgSem = 0;
iStrmCtrl->VideoWidth = 0;
iStrmCtrl->VideoHeight = 0;
iStrmCtrl->evntTask = 0;
iStrmCtrl->cmdTask = 0;
for (i=0; i<PE_NUM_SEMS; i++)
{
iStrmCtrl->msgQSem[i] = 0;
}
for (i=0; i<MAX_PE_INPUTS; i++)
{
iStrmCtrl->pPEConsumer[i] = NULL;
}
/* open the decoders and decode windows
* NOTE: the display is already opened in main because this is required earlier in the startup
* process to enable directFB */
error = GetDecoder(DECODER_ID_PRIMARY, &iConfigure->primaryDecoder );
if ( VDVD_IS_ERROR(error))
{
goto error_out;
}
error = iConfigure->primaryDecoder->SetNotifyCallback(peDecodeNotify_cb,iStrmCtrl);
if ( VDVD_IS_ERROR(error))
{
goto error_out;
}
/* PRIMARY DISPLAY: set zorder 0 */
#ifdef SECONDARY_DISPLAY_SUPPORT
/* SECONDARY DISPLAY: set zorder 0, DEINTERLACE disabled */
#endif
/* store PEManager handle */
iStrmCtrl->PEManager = PEManager;
/* Create the PE semaphores */
for (i=0; i<PE_NUM_SEMS; i++)
{
/* create a semaphore for each command */
iStrmCtrl->msgQSem[i] = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_EMPTY);
/* verify */
if (iStrmCtrl->msgQSem[i] == 0)
{
goto error_out;
}
}
/* create mutex sem for event clients */
iStrmCtrl->sendMsgSem = OS_SemBCreate(OS_SEM_Q_FIFO, OS_SEM_FULL);
if (iStrmCtrl->sendMsgSem == 0)
{
goto error_out;
}
/* create counting semaphore for outstanding vsync messages in callback msgQ */
iStrmCtrl->semCountingVsync = OS_SemCCreate(OS_SEM_Q_FIFO, PE_VSYNC_CALLBACK_DEPTH);
if (iStrmCtrl->semCountingVsync == 0)
{
goto error_out;
}
/* Allocate and initialize the PE message queue. */
iStrmCtrl->pMsgQ = new MESSAGEQUEUE;
iStrmCtrl->pMsgQPool = OS_MemAlloc(sizeof(PE_MESSAGE) * PE_QUEUE_DEPTH);
if ((iStrmCtrl->pMsgQ == NULL) || (iStrmCtrl->pMsgQPool == NULL))
{
goto error_out;
}
iStrmCtrl->pMsgQ->Initialize(iStrmCtrl->pMsgQPool, PE_QUEUE_DEPTH, sizeof(PE_MESSAGE), "PE_CMD");
/* Allocate and initialize the Callback MsgQ */
iStrmCtrl->pCallbackMsgQ = new MESSAGEQUEUE;
iStrmCtrl->pCallbackMsgQPool = OS_MemAlloc(sizeof(PE_MESSAGE) * PE_CALLBACK_DEPTH);
if ((iStrmCtrl->pCallbackMsgQ == NULL) || (iStrmCtrl->pCallbackMsgQPool == NULL))
{
goto error_out;
}
iStrmCtrl->pCallbackMsgQ->Initialize(iStrmCtrl->pCallbackMsgQPool, PE_CALLBACK_DEPTH,
sizeof(PE_MESSAGE), "PE_CALLBACK");
/* create the decoder callback task, this will post a message to a task to send
times along to IG/PG/TextST and handle decode done messages */
iStrmCtrl->evntTask = OS_TaskSpawnParam("PEDecEvnt", PE_TASK_PRIORITY,
PE_STACK_SIZE, peiStrmDecoderEventTask, (PVOID)iStrmCtrl, NULL);
if (iStrmCtrl->evntTask == 0)
{
DbgPrint(("Error Spawning PE Event Task\n"));
goto error_out;
}
/* Last step is to create the iStrmCtrl task
* don't want to create this before the message queue it needs to read from */
iStrmCtrl->cmdTask = OS_TaskSpawnParam("PECmds", PE_TASK_PRIORITY, PE_STACK_SIZE, peiStrmEngine,
(PVOID)iStrmCtrl, NULL);
if (iStrmCtrl->cmdTask == 0)
{
DbgPrint(("Error Spawning PE Command Task\n"));
goto error_out;
}
return (iStrmCtrl);
error_out:
/* error - clean up and return NULL */
if (iStrmCtrl->evntTask != 0)
{
peiStrmKillTasks(iStrmCtrl);
}
if (iStrmCtrl->pCallbackMsgQ != 0)
{
iStrmCtrl->pCallbackMsgQ->Destroy();
delete (iStrmCtrl->pCallbackMsgQ);
}
if (iStrmCtrl->pCallbackMsgQPool != NULL)
{
OS_MemFree(iStrmCtrl->pCallbackMsgQPool);
}
/* release message queue */
if (iStrmCtrl->pMsgQ != 0)
{
iStrmCtrl->pMsgQ->Destroy();
delete (iStrmCtrl->pMsgQ);
}
if (iStrmCtrl->pMsgQPool != NULL)
{
OS_MemFree(iStrmCtrl->pMsgQPool);
}
if (iStrmCtrl->semCountingVsync != 0)
{
OS_SemDelete(iStrmCtrl->semCountingVsync);
iStrmCtrl->semCountingVsync = 0;
}
if (iStrmCtrl->sendMsgSem != 0)
{
OS_SemDelete(iStrmCtrl->sendMsgSem);
iStrmCtrl->sendMsgSem = 0;
}
/* TODO-SDK - Close the decoders. */
/* release istreamctrl handle */
if (iStrmCtrl != NULL)
{
OS_MemFree(iStrmCtrl);
}
return (NULL);
}
/**
* Delete the iStrmCtrl interface.
*
* @param handle - iStrmCtrl handle.
*
* @return PE_STATUS - Error code.
*/
PE_STATUS PEDeleteiStreamCtrl(ISTREAMCTRLHANDLE* iStrmCtrl)
{
int i;
/* verify input */
if (NULL == iStrmCtrl)
{
return (PE_INVALID_HANDLE);
}
/* verify state
* this insures that there all PEConsumer objects have been deleted */
if (iStrmCtrl->SystemState != PE_ISTREAMCTRL_STATE_UNREALIZED)
{
return (PE_INVALID_STATE);
}
/* kill the pe iStrmCtrl tasks */
DBGPRINT(DBG_ON(DBG_TRACE), ("PEDeleteiStreamCtrl: kill the pe iStrmCtrl tasks\n"));
peiStrmKillTasks(iStrmCtrl);
/* release message queues */
DBGPRINT(DBG_ON(DBG_TRACE), ("PEDeleteiStreamCtrl: release message queues\n"));
/* the updatetime queue and pool */
if (iStrmCtrl->pCallbackMsgQ != 0)
{
iStrmCtrl->pCallbackMsgQ->Destroy();
delete (iStrmCtrl->pCallbackMsgQ);
iStrmCtrl->pCallbackMsgQ = NULL;
}
if (iStrmCtrl->pCallbackMsgQPool != NULL)
{
OS_MemFree(iStrmCtrl->pCallbackMsgQPool);
iStrmCtrl->pCallbackMsgQPool = NULL;
}
/* the streamengine queue and pool */
if (iStrmCtrl->pMsgQ != NULL)
{
iStrmCtrl->pMsgQ->Destroy();
delete (iStrmCtrl->pMsgQ);
iStrmCtrl->pMsgQ = NULL;
}
if (iStrmCtrl->pMsgQPool != NULL)
{
OS_MemFree(iStrmCtrl->pMsgQPool);
}
/* release semaphores */
if (iStrmCtrl->semCountingVsync != 0)
{
OS_SemDelete(iStrmCtrl->semCountingVsync);
iStrmCtrl->semCountingVsync = 0;
}
if (iStrmCtrl->sendMsgSem != 0)
{
OS_SemDelete(iStrmCtrl->sendMsgSem);
iStrmCtrl->sendMsgSem = 0;
}
for (i=0; i<PE_NUM_SEMS; i++)
{
if (iStrmCtrl->msgQSem[i] != 0)
{
OS_SemDelete(iStrmCtrl->msgQSem[i]);
iStrmCtrl->msgQSem[i] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -