📄 pe_consumer.cpp
字号:
} /* end cPEConsumer::DemuxRemoveVideoPS() */
/**
* DemuxRemoveAudioPS
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::DemuxRemoveAudioPS(void)
{
if (m_ConsumerState == PE_CONSUMER_STATE_UNREALIZED)
{
return (PE_INVALID_STATE);
}
/* Invalidate audio decoder */
m_audioDecode[0] = NULL;
return (PE_SUCCESS);
} /* end cPEConsumer::DemuxRemoveAudioPS() */
/**
* SendEvent
*
* @param PE_ISTREAMCTRL_EVENT_CODE event
* @param PVOID pEventinfo
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::SendEvent(PE_EVENT_CODE event, PVOID pEventinfo)
{
PE_STATUS status;
if (peConsumerCallback != NULL)
{
status = ((PE_CONSUMER_CALLBACK)(peConsumerCallback))((PVOID)peConsumerCallbackContext, event, pEventinfo, m_ConsumerInput);
}
else
{
status = PE_NULL_POINTER;
}
return (status);
} /* end cPEConsumer::SendEvent() */
PE_STATUS cPEConsumer::ProcessBegOfStream(PVOID StreamContext)
{
PE_BEG_OF_STREAM_EVENT_INFO info;
PE_STATUS event_status;
/* fill in the event info */
info.pContext = StreamContext;
info.input = m_ConsumerInput;
info.pe_rate = m_playrate;
/* send the event */
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::%s - SendEvent BegOfStream\n", __FUNCTION__));
event_status = SendEvent(PE_EVENT_BEG_OF_STREAM, &info);
if (PE_STATUS_FAILED(event_status) == FALSE)
{
/* if the application needs to reconfigure anything for the new
* stream it will return idle to indicate that we should stop processing
* until further notice */
if ( (event_status & PE_EVNT_IDLE) == PE_EVNT_IDLE)
{
m_fSuspend = TRUE;
}
/* if the application will keep track of the transition point,
* it will return wait_for_done to indicate that we should
* configure the decoder to notify for the decode_done */
if ( (event_status & PE_EVNT_WAIT_FOR_DONE) == PE_EVNT_WAIT_FOR_DONE )
{
if ( m_videoDecode[0] != NULL )
{
// SDK:PCI
m_videoDecode[0]->ProcessEndOfStream();
}
}
}
return (event_status);
}
PE_STATUS cPEConsumer::RequestDecodeDoneEvent(void)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
/* @TODO - need to prepare this for multiple decoders */
/* Send the Call */
if (m_videoDecode[0] != NULL)
{
error = m_videoDecode[0]->RequestNotification(DECODE_EVENT_DECODE_DONE, DECODE_NOTIFY_ONCE);
if ( VDVD_IS_ERROR( error ))
{
status = PE_FAILURE;
}
else
{
/* a decode done once request is used at the end of title playback
* when the navigator is not using the always notify model
* insert a NULL clip info to kick out the request */
// SDK:PCI
m_videoDecode[0]->ProcessEndOfStream();
}
}
else
{
status = PE_FAILURE;
}
if (status != PE_SUCCESS)
{
DbgPrint(("RequestDecodeDoneEvent -- FAILED\n"));
}
DBGPRINT(DBG_ON(DBG_TRACE), ("RequestDecodeDoneEvent EXIT\n\n"));
return (status);
}
PE_STATUS cPEConsumer::ForceLastPictureDecode()
{
PE_STATUS peStatus = PE_SUCCESS;
VDVD_ERROR error = VDVD_SUCCESS;
if (m_videoDecode[0] != NULL)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::%s - decode flush[0] BEGIN\n", __FUNCTION__));
error = m_videoDecode[0]->Flush( DECODER_TYPE_VIDEO, DECODE_FLUSH_MODE_NO_DISCARD );
if ( VDVD_IS_ERROR(error) )
{
peStatus = PE_FAILURE;
}
}
if (m_videoDecode[1] != NULL)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::%s - decode flush[1] BEGIN\n", __FUNCTION__));
error = m_videoDecode[1]->Flush( DECODER_TYPE_VIDEO, DECODE_FLUSH_MODE_NO_DISCARD );
if ( VDVD_IS_ERROR(error) )
{
peStatus = PE_FAILURE;
}
}
return (PE_SUCCESS);
}
PE_STATUS cPEConsumer::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), ("cPEConsumer::%s - SendEvent EndOfStream\n", __FUNCTION__));
event_status = SendEvent(PE_EVENT_END_OF_STREAM, &info);
/* The status bits are only valid if there was no error */
if (PE_STATUS_FAILED(event_status) == FALSE)
{
if (INPUT_MAIN == m_ConsumerInput)
{
if ((event_status & PE_EVNT_BEGIN_STILL) == PE_EVNT_BEGIN_STILL)
{
m_fStillOn = TRUE;
}
if ((event_status & PE_EVNT_END_OF_PLAY) == PE_EVNT_END_OF_PLAY)
{
ForceLastPictureDecode();
}
if ((event_status & PE_EVNT_WAIT_FOR_DONE) == PE_EVNT_WAIT_FOR_DONE)
{
// This indicates the nav is going to stop sending data and wait for the PE to finish decode.
/* TODO-SDK - Request to have the decoder give end of stream information. */
if ( m_videoDecode[0] != NULL )
{
// SDK:PCI
m_videoDecode[0]->ProcessEndOfStream();
}
}
}
}
return (event_status);
}
/**
* Receives incoming DR messages, handles stream events, and passes payloads
* onto the appropriate handler.
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::dataProc(void)
{
PEINPUTMESSAGE *pInMessage = NULL;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::dataProc() - starting up (%d)\n", m_ConsumerInput));
while (FALSE == m_fKillDataProc)
{
/* handle stop request */
if (m_fStop == TRUE)
{
/* update state info */
m_ConsumerState = PE_CONSUMER_STATE_STOP;
m_fStillOn = FALSE;
m_fStop = FALSE;
DBGPRINT(DBG_ON(DBG_TRACE), ("cPEConsumer::dataProc() - PE_CONSUMER_STATE_STOP (%d)\n", m_ConsumerInput));
continue;
}
/* if we should prefill check the stream to see if there is any data yet */
if ( (m_fPrefill == TRUE) && (m_ConsumerInput != INPUT_BDROM_SUBPATH_TEXT_SUBTITLE) &&
(m_ConsumerInput != INPUT_BDROM_SUBPATH_INTERACTIVE_GRAPHICS) )
{
if (m_InputStream->FullStatus() > 0)
{
/* clear prefill flag */
m_fPrefill = FALSE;
/* send the event */
PE_PREFILL_EVENT_INFO prefill_info = {m_ConsumerInput};
SendEvent(PE_EVENT_ASYNC_PREFILL, &prefill_info);
}
}
/*
* Go no further unless we're in the Run state with no still on, and
* we're not prefilling the TextST or IG subpath.
*/
if ( ( (PE_CONSUMER_STATE_RUN != m_ConsumerState) || (m_fStillOn == TRUE) ) &&
( !m_fPrefill ||
( (m_ConsumerInput != INPUT_BDROM_SUBPATH_TEXT_SUBTITLE) &&
(m_ConsumerInput != INPUT_BDROM_SUBPATH_INTERACTIVE_GRAPHICS) ) ) )
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %uw ", m_ConsumerInput));
OS_TaskYield();
continue;
}
/* Get a new message with more data */
pInMessage = (PEINPUTMESSAGE*)m_InputStream->Read(OS_WAIT_1S/10);
if (NULL == pInMessage)
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %un ", m_ConsumerInput));
OS_TaskYield();
continue;
}
if (m_fStop == FALSE)
{
if (pInMessage->BegOfStream == TRUE)
{
PE_STATUS status;
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %ub ", m_ConsumerInput));
status = ProcessBegOfStream(pInMessage->StreamContext);
if (m_fSuspend == TRUE)
{
PE_IDLE_EVENT_INFO info;
/* fill in the event info */
info.pContext = pInMessage->StreamContext;
info.input = m_ConsumerInput;
/* Notify application that the PE is now idle */
SendEvent(PE_EVENT_IDLE, &info);
}
}
/* don't process data while we are suspended for reconfiguration */
while (m_fSuspend == TRUE)
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %us ", m_ConsumerInput));
OS_TaskYield();
}
/* check for discontinuities */
if (TRUE == pInMessage->DiscontinuityAtBeginning)
{
/* Notify application of the discontinuity about to arrive */
SendEvent(PE_EVENT_DISCONTINUITY, NULL);
}
/* Handle the payloads */
if (pInMessage->payload != NULL)
{
TCH_PAYLOAD(pInMessage->payload); /* for debugging */
if (pInMessage->fInfoPayload)
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %ui ", m_ConsumerInput));
processInfo(pInMessage);
}
else
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %ud ", m_ConsumerInput));
processData(pInMessage);
}
}
if (pInMessage->EndOfStream == TRUE)
{
DBGPRINT(DBG_ON(DBG_PROCTRACE), (" %ue ", m_ConsumerInput));
ProcessEndOfStream(pInMessage->StreamContext);
}
}
/* Release message so dr can send next */
if (pInMessage->payload != NULL)
{
delete (pInMessage->payload);
pInMessage->payload = NULL;
}
m_InputStream->ReleaseMsg(pInMessage);
}
return (PE_SUCCESS);
} /* end cPEConsumer::dataProc() */
/**
* Returns the current video PTS.
*
* @param pTime45k_PTS - receives the current video PTS value.
* @param pTime45k_STC - receives the current system clock value.
*
* @return PE_STATUS - Error code.
*/
PE_STATUS cPEConsumer::GetVidPTS(TIME45k* pTime45k_PTS, TIME45k* pTime45k_STC)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS pe_status = PE_SUCCESS;
DECODE_STATUS_TYPE d_status;
if (NULL == pTime45k_PTS)
{
return (PE_NULL_POINTER);
}
if (NULL == pTime45k_STC)
{
return (PE_NULL_POINTER);
}
/* TODO-SDK - Get the current PTS and STC of the decoder and return in pTime45k params. */
error = m_videoDecode[0]->GetStatus(&d_status);
if ( VDVD_IS_ERROR(error))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s(%d): GetStatus\n", __FUNCTION__, __LINE__));
pe_status = PE_FAILURE;
}
else
{
pe_status = PE_SUCCESS;
/* return pts & scr */
*pTime45k_PTS = d_status.video_pts;
*pTime45k_STC = d_status.video_stc;
}
return (pe_status);
}
/**
* Send payload to decoder
*
* @param pPayload - pointer to payload
*
* @return PE_STATUS - Error code.
*/
PE_STATUS cPEConsumer::SendPayloadToDecoder(Decoder* pDecoder, cPayload *pPayload)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_FAILURE;
unsigned char* payload_buffer = 0;
size_t payload_buffer_size = 0;
if (NULL == pPayload)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s(%d): NULL pPayload\n", __FUNCTION__, __LINE__));
return (PE_NULL_POINTER);
}
if (NULL == pDecoder)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("%s(%d): NULL pDecoder\n", __FUNCTION__, __LINE__));
return (PE_NULL_POINTER);
}
payload_buffer = (unsigned char *)pPayload->get_rd_ptr();
payload_buffer_size = pPayload->get_size();
do {
error = pDecoder->SendData(payload_buffer, payload_buffer_size );
if ( !VDVD_IS_ERROR(error))
{
return (PE_SUCCESS);
}
// Yeild the processor, try again to send the data
OS_TaskYield();
} while ( (m_fStop == FALSE) && (m_fAbort == FALSE) && (error == VDVD_ERROR_TIMEOUT) );
return (status);
}
/**
* Handles trick mode changes
*
* @param rate - The new rate requested.
*
* @return PE_STATUS
*/
PE_STATUS cPEConsumer::SetVideoDecodeRate(PE_ISTREAMCTRL_PLAYRATE *pPlayRate)
{
VDVD_ERROR error = VDVD_SUCCESS;
PE_STATUS status = PE_SUCCESS;
if (pPlayRate == NULL)
{
status = PE_FAILURE;
}
else
{
if (pPlayRate->rate == PLAY_RATE_NORMAL)
{
/* SDK: Re-enable CC */
}
else
{
/* SDK: Mute CC during any trickplay*/
}
/* step is handled slightly differently than the rest of the trick modes
* NOTE: The decoder MUST be paused in order to perform a frame advance */
if ( (pPlayRate->rate == PLAY_RATE_STEP) && (pPlayRate->direction != PE_ISTREAMCTRL_DIRECTION_BACKWARD) &&
( (m_playrate.rate == PLAY_RATE_PAUSE) || (m_playrate.rate == PLAY_RATE_STEP) ) )
{
if (m_videoDecode[0] != NULL)
{
/* TODO-SDK - Advance the decoder by one frame. */
}
if (m_videoDecode[1] != NULL)
{
/* TODO-SDK - Advance the decoder by one frame. */
}
}
else
{
/* TODO-SDK - Configure the data channel, decoder, and other hardware for trick modes. */
/* apply decoder settings */
if (m_videoDecode[0] != NULL)
{
/* TODO-SDK - Start playing back in the trick mode. */
error = m_videoDecode[0]->SetPlayRate(pPlayRate);
if ( VDVD_IS_ERROR(error) )
{
status = PE_FAILURE;
}
}
if (m_videoDecode[1] != NULL)
{
/* TODO-SDK - Start playing back in the trick mode. */
error = m_videoDecode[1]->SetPlayRate(pPlayRate);
if ( VDVD_IS_ERROR(error) )
{
status = PE_FAILURE;
}
}
}
status = PE_SUCCESS;
}
return (status);
}
PE_ISTREAMCTRL_PLAYRATE cPEConsumer::GetRate(void)
{
return (m_playrate);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -