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

📄 pe_consumer.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

} /* 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 + -