📄 pe_consumer.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_consumer.cpp
*
* $Revision: 1.29 $
*
* PE Consumer Base Class Definition
* The PE Consumer moves data from an input stream to a decoder or demux.
*
*/
#include <stdlib.h>
#include "decoder.h"
#include "vdvd_types.h"
#include "osapi.h"
#include "dbgprint.h"
#include "pe_app.h"
#include "pe_consumer.h"
#define DEBUG_PE_CONSUMER DBG_ERROR
#define DBG_PROCTRACE DBG_VERBOSE /* set lower than DEBUG_PE_CONSUMER to trace the PE dataProc threads */
#define DBG_ON(x) (DEBUG_PE_CONSUMER >= x)
#define PE_CONSUMER_PROC_PRIORITY OS_TASK_NORMAL_PRIORITY
#define PE_CONSUMER_PROC_STACK_SIZE (16 * 1024)
char *stream_name[] = { "main", "pg", "ig", "ts", (char *)0};
/**
* cPEConsumer::Configure
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::Configure(PE_CONSUMER_CONFIG_INFO *pConfigInfo)
{
PE_STATUS status;
if (m_ConsumerState != PE_CONSUMER_STATE_UNREALIZED)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::Configure() - STATE ERROR"));
return (PE_INVALID_STATE);
}
/* verify input */
if (pConfigInfo == NULL)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::Configure() - pConfigInfo NULL\n"));
status = PE_NULL_POINTER;
goto error_out;
}
/* These need intialized */
m_fKillDataProc = FALSE;
m_fStillOn = FALSE;
/* Store the input that this consumer is responsible for */
m_ConsumerInput = pConfigInfo->input;
if (FALSE == pConfigInfo->fPlaybackStarted)
{
/* TODO-SDK - Setup data channel. */
}
/* update state */
m_ConsumerState = PE_CONSUMER_STATE_REALIZING;
return (PE_SUCCESS);
error_out:
return (status);
}
/**
* cPEConsumer::Reset
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::Reset(void)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
PEINPUTMESSAGE *pMessage = NULL;
if (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::Reset() - PE_INVALID_STATE (%d)\n", m_ConsumerState));
return (PE_INVALID_STATE);
}
m_fKillDataProc = TRUE;
m_fStop = TRUE;
m_fAbort = TRUE;
m_fSuspend = FALSE;
if (m_ConsumerState > PE_CONSUMER_STATE_REALIZING)
{
/* kick the dataProc so it won't wait */
pMessage = (PEINPUTMESSAGE*)m_InputStream->GetMsg((ULONG)OS_NO_WAIT);
if (pMessage != NULL)
{
m_InputStream->Write((PVOID)pMessage, OS_NO_WAIT);
}
/* kill the data task */
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::Reset() - Killing the data task\n"));
OS_TaskJoin(m_dataProcID);
OS_TaskDelete(m_dataProcID);
m_dataProcID = 0;
}
/* stop the decoder */
if ( m_videoDecode[0] != NULL )
{
error = m_videoDecode[0]->Stop(FALSE);
if ( VDVD_IS_ERROR(error) )
{
status = PE_FAILURE;
}
}
if (m_videoDecode[1] != NULL)
{
error = m_videoDecode[1]->Stop(FALSE);
if ( VDVD_IS_ERROR(error) )
{
status = PE_FAILURE;
}
}
/* update the state */
m_ConsumerState = PE_CONSUMER_STATE_UNREALIZED;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::Reset() - DONE\n"));
return (status);
} /* end cPEConsumer::Reset() */
/**
* AttachInputStream
*
* @param[in] cStream *pStream
* @param[in] PE_ISTREAMCTRL_INPUT input
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::AttachInputStream(cStream *pStream, PE_ISTREAMCTRL_INPUT input)
{
char task_name[32];
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::AttachInputStream()\n"));
DbgAssert(NULL != pStream);
if (m_ConsumerState != PE_CONSUMER_STATE_REALIZING)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::AttachInputStream - STATE ERROR, state=%d\n", m_ConsumerState));
return (PE_INVALID_STATE);
}
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::AttachInputStream - pStream = %lx, input = %lx\n", (long)pStream, (long)input));
/* Intialize parameters */
m_InputStream = pStream;
/* create the data task */
snprintf(task_name, sizeof(task_name), "%s_%s", "dataProc", stream_name[m_ConsumerInput]);
m_dataProcID = OS_TaskSpawnParam(task_name, PE_CONSUMER_PROC_PRIORITY, PE_CONSUMER_PROC_STACK_SIZE,
peConsumerDataProcCaller, this, NULL);
if (OS_FAILURE == m_dataProcID)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::AttachInputStream - dataProc spawn failure\n"));
m_dataProcID = 0;
goto AttachInputStream_err_out;
}
/* update the state */
m_ConsumerState = PE_CONSUMER_STATE_STOP;
return (PE_SUCCESS);
AttachInputStream_err_out:
m_fKillDataProc = TRUE;
/* kill the data task */
if (m_dataProcID != 0)
{
OS_TaskJoin(m_dataProcID);
OS_TaskDelete(m_dataProcID);
m_dataProcID = 0;
}
/* invalidate stream pointer */
m_InputStream = NULL;
return (PE_FAILURE);
}
/**
* AttachEvent
*
* @param PE_CONSUMER_CALLBACK function
* @param PVOID pContext
*
* @return PE_STATUS
*
* @remarks Only one event is ever attached and used. It may be overwritten without notification.
*/
PE_STATUS cPEConsumer::AttachEvent(PE_CONSUMER_CALLBACK function, PVOID pContext)
{
PE_STATUS status;
if (function != NULL)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::AttachEvent - function = %08x, pContext = %08x\n", (ULONG)function, (ULONG)pContext));
peConsumerCallback = function;
peConsumerCallbackContext = pContext;
status = PE_SUCCESS;
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::AttachEvent - tried to attach NULL callback\n"));
status = PE_FAILURE;
}
return (status);
} /* end cPEConsumer::AttachEvent() */
/**
* SetRate
*
* @param PE_ISTREAMCTRL_PLAYRATE *pPlayRate
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::SetRate(PE_ISTREAMCTRL_PLAYRATE *pPlayRate)
{
PE_STATUS status;
if (INPUT_MAIN == m_ConsumerInput)
{
status = SetVideoDecodeRate(pPlayRate);
if (status == PE_SUCCESS)
{
/* update playrate */
m_playrate = *pPlayRate;
}
}
else
{
status = PE_NOT_IMPLEMENTED;
}
return (status);
} /* end cPEConsumer::SetRate() */
/**
* Base class consumer Run implementation.
* Does nothing more than initialize some variables.
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::Run(void)
{
/* the base class just updates the state info
* a media specific consumer should override this version to add
* real functionality. This base class version can still be used
* by the derived class to update the state info */
/* update state info */
m_fPrefill = FALSE;
m_fSuspend = FALSE;
m_fStillOn = FALSE;
m_ConsumerState = PE_CONSUMER_STATE_RUN;
return (PE_SUCCESS);
} /* end cPEConsumer::Run() */
/**
* DemuxAddVideoPS
*
* @param lPID
* @param VideoType
* @param lExtID
* @param ExtVideoType
* @param pDecoder
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::DemuxAddVideoPS(LONG lPID, PE_ISTREAMCTRL_VIDEO_TYPE VideoType, LONG lExtID,
PE_ISTREAMCTRL_VIDEO_EXT_TYPE ExtVideoType, Decoder* pDecoder)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::DemuxAddVideoPS() - PID=%x, VideoType=%d\n", lPID, VideoType));
/* validate state
* NOTE: We don't support dynamic video configuration. You should stop the consumer if you
* want to change video streams */
if ( (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED) || (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == TRUE) )
{
status = PE_INVALID_STATE;
}
/* validate input */
if (pDecoder == NULL)
{
status = PE_NULL_POINTER;
}
if (status == PE_SUCCESS)
{
DECODE_VIDEO_PARAMETERS video_params;
/* Store main video decode handle */
m_videoDecode[0] = pDecoder;
/* TODO-SDK - Configure the demux and decoder for the attributes given in the params. */
video_params.pid = 0;
video_params.stream_id = lPID;
video_params.substream_id = 0;
video_params.extstream_id = 0;
video_params.stc_offset = 0;
/* add demux to decoder */
error = m_videoDecode[0]->SelectVideoStream(&video_params);
if ( VDVD_IS_ERROR( error ))
{
m_videoDecode[0] = NULL;
status = PE_FAILURE;
}
}
return (status);
} /* end cPEConsumer::DemuxAddVideoPS() */
/**
* DemuxAddAudioPS
*
* @param lPID
* @param lSubID
* @param AudioType
* @param pDecoder
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::DemuxAddAudioPS(LONG lPID, LONG lSubID, PE_ISTREAMCTRL_AUDIO_TYPE AudioType, PE_ISTREAMCTRL_AUDIO_ATTRIBUTES *pAttributes, Decoder* pDecoder)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::DemuxAddAudioPS() - id=%x, subid=%x, AudioType=%d\n",
lPID, lSubID, AudioType));
/* validate state */
if (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED)
{
status = PE_INVALID_STATE;
}
/* validate input */
if (pDecoder == NULL)
{
status = PE_NULL_POINTER;
}
if (status == PE_SUCCESS)
{
DECODE_AUDIO_PARAMETERS audio_params;
/* Store main audio decode handle */
m_audioDecode[0] = pDecoder;
/* TODO-SDK - Setup the audio decoder and configure according to the attributes. */
audio_params.pid = 0;
audio_params.stream_id = lPID;
audio_params.substream_id = (lSubID == 0xff) ? 0 : lSubID;
audio_params.extstream_id = 0;
audio_params.stc_offset = 0;
audio_params.downmix_enable = false;
if (pAttributes != NULL)
{
/* config sampling freq and num channels */
switch (pAttributes->sampling_frequency)
{
case AUDIO_SAMPLING_FREQUENCY_44_1_KHz:
audio_params.sample_rate = 44100;
break;
default:
case AUDIO_SAMPLING_FREQUENCY_INVALID:
case AUDIO_SAMPLING_FREQUENCY_48_KHz:
audio_params.sample_rate = 48000;
break;
case AUDIO_SAMPLING_FREQUENCY_96_KHz:
audio_params.sample_rate = 96000;
break;
case AUDIO_SAMPLING_FREQUENCY_192_KHz:
audio_params.sample_rate = 192000;
break;
}
switch(pAttributes->n_channels)
{
case AUDIO_MONO:
audio_params.num_channels = 1;
break;
case AUDIO_DUAL_MONO:
case AUDIO_STEREO:
audio_params.num_channels = 2;
break;
case AUDIO_3_CHANNELS:
audio_params.num_channels = 3;
break;
case AUDIO_4_CHANNELS:
audio_params.num_channels = 4;
break;
case AUDIO_5_CHANNELS:
audio_params.num_channels = 5;
break;
case AUDIO_6_CHANNELS:
audio_params.num_channels = 6;
break;
case AUDIO_7_CHANNELS:
audio_params.num_channels = 7;
break;
case AUDIO_8_CHANNELS:
audio_params.num_channels = 8;
break;
case AUDIO_MULTI_CHANNEL: /* Blu-Ray audio_presentation_type 6 */
case AUDIO_STEREO_PLUS_MULTI_EXT: /* Blu-Ray audio_presentation_type 12 */
case AUDIO_CHANNELS_INVALID:
audio_params.num_channels = 0;
break;
}
}
else
{
/* the audio attributes were NULL */
audio_params.sample_rate = 48000;
audio_params.num_channels = 0;
}
audio_params.format = AudioType;
// if need to check if already running before changing streams use
// if (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == TRUE)
error = m_audioDecode[0]->SelectAudioStream(&audio_params);
if ( VDVD_IS_ERROR(error) )
{
m_audioDecode[0] = NULL;
status = PE_FAILURE;
}
}
return (status);
} /* end cPEConsumer::DemuxAddAudioPS() */
/**
* DemuxRemoveVideoPS
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::DemuxRemoveVideoPS(void)
{
if (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED)
{
return (PE_INVALID_STATE);
}
/* Invalidate video decoder */
m_videoDecode[0] = NULL;
return (PE_SUCCESS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -