📄 pe_consumer_vcd.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_vcd.cpp
*
* $Revision: 1.20 $
*
* PE Consumer VCD/SVCD Derived 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"
#include "pe_consumer_vcd.h"
#define DEBUG_PE_CONSUMER_VCD DBG_ERROR
#define DBG_ON(x) (DEBUG_PE_CONSUMER_VCD >= x)
/**
* cPEConsumer_VCD::Configure
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::Configure(PE_CONSUMER_CONFIG_INFO *pConfigInfo)
{
PE_STATUS status = PE_SUCCESS;
if ( (m_streamType == STREAM_TYPE_MPEG1_SS) || (m_streamType == STREAM_TYPE_AUDIO) )
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::Configure() - Ring buffer model\n"));
/*
* Config Ring buffer model
*/
/*
* Cleanup of all the created resources happen in the pe_consumer base class
*/
if (m_ConsumerState != PE_CONSUMER_STATE_UNREALIZED)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer::Configure() - STATE ERROR\n"));
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;
m_fPCM = FALSE;
/* TODO-SDK - Configure the data channel. */
/* update state */
m_ConsumerState = PE_CONSUMER_STATE_REALIZING;
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::Configure() - SG buffer model\n"));
/*
* Config for SG buffer model
*/
status = cPEConsumer::Configure(pConfigInfo);
}
return (status);
error_out :
return (status);
}
/**
* cPEConsumer_VCD::Reset
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::Reset(void)
{
PE_STATUS status;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Reset()\n"));
/* clear prefill since we are going to stop state */
m_fPrefill = FALSE;
m_fSuspend = FALSE;
/* @todo Examine what decode/channel stops need to be called and if teardown
* of dataProc for this VCD consumer and its information should be done. */
if ( (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == TRUE) && (m_fStop == FALSE) )
{
/* tell the consumer data task it should stop */
m_fStop = TRUE;
m_fAbort = TRUE;
/* wait for transition to stopped state */
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Reset() - wait for transition to stopped (%d)\n", m_ConsumerInput));
while (m_fStop == TRUE)
{
OS_TaskYield();
}
m_fAbort = FALSE;
}
/* use the base clase to terminate the consumer task */
status = cPEConsumer::Reset();
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Reset() done\n"));
return (status);
} /* end cPEConsumer_VCD::Reset() */
/**
* DemuxAddVideoPS
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer_VCD::DemuxAddVideoPS(LONG lPID, PE_ISTREAMCTRL_VIDEO_TYPE VideoType, LONG lExtID,
PE_ISTREAMCTRL_VIDEO_EXT_TYPE ExtVideoType, Decoder* pDecoder)
{
m_lPid = lPID;
return ( cPEConsumer::DemuxAddVideoPS(lPID, VideoType, lExtID, ExtVideoType, pDecoder) );
}
/**
* DemuxAddAudioPS
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer_VCD::DemuxAddAudioPS(LONG lPID, LONG lSubID, PE_ISTREAMCTRL_AUDIO_TYPE AudioType,
PE_ISTREAMCTRL_AUDIO_ATTRIBUTES *pAttributes, Decoder* pDecoder)
{
if (AudioType == AUDIO_TYPE_PCM)
{
m_fPCM = TRUE;
return (PE_SUCCESS);
}
else
{
m_fPCM = FALSE;
return ( cPEConsumer::DemuxAddAudioPS(lPID, lSubID, AudioType, pAttributes, pDecoder) );
}
}
/**
* DemuxRemoveAudioPS
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::DemuxRemoveAudioPS(void)
{
if (m_fPCM == TRUE)
{
m_fPCM = FALSE;
return (PE_SUCCESS);
}
else
{
return ( cPEConsumer::DemuxRemoveAudioPS() );
}
}
/**
* If active start consuming and presenting AV data. Wakes up dataProc.
*
* @return PE_STATUS
*
*
*/
PE_STATUS cPEConsumer_VCD::Run(void)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Run()\n"));
if (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == FALSE)
{
if (INPUT_MAIN == m_ConsumerInput)
{
if (m_fPCM)
{
if (m_audioDecode[0] != NULL)
{
DECODER_SETTINGS_TYPE settings;
settings.streamType = DECODER_STREAM_TYPE_PCM;
settings.pcm.bits_per_sample = 16;
settings.pcm.sample_rate = 44100;
settings.pcm.channels = 2;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Run - pcm decoder setup\n"));
error = m_audioDecode[0]->Setup(&settings);
if (VDVD_IS_ERROR(error))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_VCD::Run - pcm decoder setup FAILED!\n"));
}
}
}
else if (m_videoDecode[0] != NULL)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Run() - decode setup\n"));
DECODER_SETTINGS_TYPE settings;
settings.streamType = DECODER_STREAM_TYPE_MPEG2;
error = m_videoDecode[0]->Setup(&settings);
if (VDVD_IS_ERROR(error))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("cPEConsumer_VCD::Run() - decode setup FAILED!\n"));
status = PE_FAILURE;
}
}
}
}
/* update state info */
if (status == PE_SUCCESS)
{
m_fPrefill = FALSE;
m_fSuspend = FALSE;
m_ConsumerState = PE_CONSUMER_STATE_RUN;
m_fStillOn = FALSE;
}
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Run() - DONE\n"));
return (status);
} /* end cPEConsumer_VCD::Run() */
/**
* If active start consuming and presenting AV data.
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::Stop(BOOLEAN fHoldPicture)
{
VDVD_ERROR error = VDVD_SUCCESS;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Stop() - input = %d\n", m_ConsumerInput));
/* clear prefill since we are going to stop state */
m_fPrefill = FALSE;
m_fSuspend = FALSE;
/* @todo Examine what decode/channel stops need to be called and if teardown
* of dataProc for this VCD consumer and its information should be done. */
if ( (IS_PECONSUMER_STATE_RUNNING(m_ConsumerState) == TRUE) && (m_fStop == FALSE) )
{
PEINPUTMESSAGE* pMessage = NULL;
/* tell the consumer data task it should stop */
m_fStop = TRUE;
m_fAbort = TRUE;
/* TODO-SDK - Wait for payloads to be consumed by the decoder. */
/* 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);
}
/* wait for transition to stopped state */
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Stop() - wait for transition to stopped\n"));
while (m_fStop == TRUE)
{
OS_TaskYield();
}
/* stop the decoder */
if (m_fPCM == TRUE)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Stop() - pcm decoder stop\n"));
if (m_audioDecode[0] != NULL)
{
error = m_audioDecode[0]->Stop(FALSE);
}
}
else
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Stop() - decoder stop\n"));
if (INPUT_MAIN == m_ConsumerInput)
{
if (m_videoDecode[0] != NULL)
{
error = m_videoDecode[0]->Stop(fHoldPicture);
}
}
}
m_fAbort = FALSE;
}
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer_VCD::Stop() - DONE (%d)\n", m_ConsumerInput));
return (PE_SUCCESS);
} /* end cPEConsumer_VCD::Stop() */
/**
* If active start consuming and presenting AV data.
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::Flush(void)
{
DBGPRINT(DBG_ON(DBG_VERBOSE), ("cPEConsumer_VCD::Flush\n" ));
return (PE_NOT_IMPLEMENTED);
} /* end cPEConsumer_VCD::Flush() */
PE_STATUS cPEConsumer_VCD::ProcessEndOfStream(PVOID StreamContext)
{
PE_END_OF_STREAM_EVENT_INFO info;
PE_STATUS event_status;
/* fill in the event info */
info.pContext = StreamContext;
info.input = m_ConsumerInput;
/* TODO-SDK - Wait until outstanding payloads are released */
/* send the event */
DBGPRINT(DBG_ON(DBG_TRACE), ("ProcessEndOfStream: PE_EVENT_END_OF_STREAM\n"));
event_status = SendEvent(PE_EVENT_END_OF_STREAM, &info);
/* check status returned from event handler */
if (m_fPCM == FALSE)
{
if ( (event_status & PE_EVNT_VCD_PUSH) == PE_EVNT_VCD_PUSH)
{
/* Push out the last frame (vcd never has a seamless connection) */
DBGPRINT(DBG_ON(DBG_TRACE), ("ProcessEndOfStream: ForceLastPictureDecode\n"));
ForceLastPictureDecode();
}
}
return (event_status);
}
/**
* If active start consuming and presenting AV data.
*
* @return PE_STATUS
*
*/
PE_STATUS cPEConsumer_VCD::processData(PEINPUTMESSAGE *pInMessage)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS pe_status = PE_SUCCESS;
ULONG currentPosition;
DECODE_STATUS_TYPE d_status;
/* get the current position, adjust for buffering, and send */
currentPosition = pInMessage->payload->get_user_data();
if (!m_fPCM)
{
if (m_videoDecode[0] != NULL)
{
/* TODO-SDK - Get the current amount of data in the channel so that the display time can be adjusted. */
error = m_videoDecode[0]->GetStatus(&d_status);
if ( VDVD_IS_ERROR(error))
{
currentPosition -= (d_status.video_fifo_depth / CD_MODE2_FORM2_USER_DATA);
}
}
}
SendEvent(PE_EVENT_POSITION, ¤tPosition);
/* send autopause message */
if (pInMessage->AutoPause)
{
SendEvent(PE_EVENT_AUTO_PAUSE, NULL);
}
/* send the payload to the appropriate place */
if (m_fPCM == TRUE)
{
/* CDDA Track */
pe_status = SendPayloadToDecoder(m_audioDecode[0], pInMessage->payload);
}
else
{
pe_status = SendPayloadToDecoder(m_videoDecode[0], pInMessage->payload);
}
if (m_fPCM == FALSE)
{
if ((0xE0 + pInMessage->SequenceEnd - 1) == m_lPid)
{
/* Push out the frames whenever a sequenceEnd is received */
DBGPRINT(DBG_ON(DBG_TRACE),("processData: ForceLastPictureDecode\n "));
ForceLastPictureDecode();
}
}
return (pe_status);
} /* end cPEConsumer_VCD::processData() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -