/*************************************************************************** * Copyright (c) 2003-2008, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: stream api implementation, utility module used to manage * decode structures for FCC. API assumes all functions are called from the same thread. * * Revision History: * * $brcm_Log: $ * * ***************************************************************************/ #include "bsettop_stream.h" #include "bsettop_p_stream.h" #include "ts_psi.h" BDBG_MODULE(bstream); #define INVALID_PID 0xFFFF struct bstream { bool in_use; /* flag indicating the context is in use */ int index; /* stream index */ bband_t band; /* Band with possibly playback flag */ bstream_mpeg mpeg; /* mpeg program pids */ bsettop_p_stream_t stream_info; /* private stream parameters */ }; static struct bstream s_streams[BSETTOP_MAX_STREAMS] = { { false, 0, DEF_PARSER_BAND, { { {INVALID_PID}},{{INVALID_PID, TS_PSI_ST_ATSC_AC3}},INVALID_PID}}, { false, 1, DEF_PARSER_BAND, { { {INVALID_PID}},{{INVALID_PID, TS_PSI_ST_ATSC_AC3}},INVALID_PID}}, { false, 2, DEF_PARSER_BAND, { { {INVALID_PID}},{{INVALID_PID, TS_PSI_ST_ATSC_AC3}},INVALID_PID}} }; static bstream_mpeg s_def_stream_mpeg = { {{INVALID_PID}}, {{ INVALID_PID,TS_PSI_ST_ATSC_AC3}},INVALID_PID}; static bool s_bstream_init = false; /* Summary: Reset mpeg program structure to the default. */ void bstream_mpeg_init(bstream_mpeg *mpeg) { *mpeg = s_def_stream_mpeg; return; } /* Summary: Returns the current global configuration settings. */ bresult bstream_get_config(bstream_config *config) { BSTD_UNUSED(config); BKNI_Memset(config,0,sizeof(bstream_config)); return b_ok; } /* Summary: Sets the current global configuration settings. */ bresult bstream_set_config(bstream_config *config) { BSTD_UNUSED(config); return b_ok; } /* Summary: Find available stream. */ static bstream_t bstream_p_find_stream(void) { int i; for (i = 0; i < BSETTOP_MAX_STREAMS; ++i) { if (!s_streams[i].in_use) return(bstream_t)&s_streams[i]; } return NULL; } /* Summary: Module initialization function. */ void bstream_init(NEXUS_VideoDecoderHandle videoDecodeHandle) { int i; if (s_bstream_init) return; for (i = 0; i < BSETTOP_MAX_STREAMS; ++i) { BKNI_Memset(&(s_streams[i].stream_info),0,sizeof(s_streams[i].stream_info)); s_streams[i].stream_info.videoDecoder = videoDecodeHandle; #if 0 s_streams[i].stream_info.primerHandle = NEXUS_VideoDecoder_OpenPrimer(videoDecodeHandle); BDBG_ASSERT(s_streams[i].stream_info.primerHandle); #endif } s_bstream_init = true; return; } /* Summary: Module deinitialization function. */ void bstream_destroy(void) { int i; if (!s_bstream_init) return; #if 0 for (i = 0; i < BSETTOP_MAX_STREAMS; ++i) { if (s_streams[i].stream_info.primerHandle) NEXUS_VideoDecoder_ClosePrimer(s_streams[i].stream_info.videoDecoder,s_streams[i].stream_info.primerHandle); } #endif s_bstream_init = true; return; } /* Summary: Open stream and allocate transport channels. */ bstream_t bstream_open(bband_t band, const bstream_mpeg *mpeg) { bstream_t stream; NEXUS_StcChannelSettings stcSettings; BDBG_ASSERT(mpeg); BDBG_WRN(("%s:%d\n",__FUNCTION__,__LINE__)); stream = bstream_p_find_stream(); if (!stream) { BDBG_WRN(("%s no more streams available.\n",__FUNCTION__)); goto ExitError; } stream->band = band; stream->mpeg = *mpeg; stream->stream_info.pcrPidChannel = NULL; if (stream->mpeg.video[0].pid != 0) { stream->stream_info.videoPidChannel = NEXUS_PidChannel_Open(stream->band,stream->mpeg.video[0].pid,NULL); if (!stream->stream_info.videoPidChannel) { BDBG_WRN(("NEXUS_PidChannel_Open Video PID = 0x%04x\n",stream->mpeg.video[0].pid)); goto ExitError; } if (stream->mpeg.pcr_pid == stream->mpeg.video[0].pid) { stream->stream_info.pcrPidChannel = stream->stream_info.videoPidChannel; } } if (stream->mpeg.audio[0].pid != 0) { stream->stream_info.audioPidChannel = NEXUS_PidChannel_Open(stream->band,stream->mpeg.audio[0].pid,NULL); if (!stream->stream_info.audioPidChannel) { BDBG_WRN(("NEXUS_PidChannel_Open Audio PID = 0x%04x\n",stream->mpeg.audio[0].pid)); goto ExitError; } if (stream->mpeg.pcr_pid == stream->mpeg.audio[0].pid) { stream->stream_info.pcrPidChannel = stream->stream_info.audioPidChannel; } } if ((stream->mpeg.pcr_pid != 0) && (stream->stream_info.pcrPidChannel == NULL)) { stream->stream_info.pcrPidChannel = NEXUS_PidChannel_Open(stream->band,stream->mpeg.pcr_pid,NULL); if (!stream->stream_info.pcrPidChannel) { BDBG_WRN(("NEXUS_PidChannel_Open PCR PID = 0x%04x\n",stream->mpeg.pcr_pid)); goto ExitError; } } BDBG_ASSERT(stream->stream_info.pcrPidChannel); NEXUS_StcChannel_GetDefaultSettings(0, &stcSettings); stcSettings.autoConfigTimebase = false; /* must do it manually */ stcSettings.timebase = NEXUS_Timebase_e0; stcSettings.mode = NEXUS_StcChannelMode_ePcr; /* live */ stcSettings.modeSettings.pcr.pidChannel = stream->stream_info.pcrPidChannel; stcSettings.modeSettings.pcr.offsetThreshold = 0; stcSettings.stcIndex = 0; stcSettings.modeSettings.Auto.behavior = NEXUS_StcChannelAutoModeBehavior_eFirstAvailable; stcSettings.modeSettings.Auto.transportType = NEXUS_TransportType_eTs; stream->stream_info.stcChannel = NEXUS_StcChannel_Open(stream->index, &stcSettings); if (!stream->stream_info.stcChannel) { BDBG_WRN(("NEXUS_StcChannel_Open %d\n",stream->index)); goto ExitError; } NEXUS_VideoDecoder_GetDefaultStartSettings(&(stream->stream_info.decodeSettings)); stream->stream_info.decodeSettings.codec = stream->mpeg.video[0].format; stream->stream_info.decodeSettings.pidChannel = stream->stream_info.videoPidChannel; stream->stream_info.decodeSettings.stcChannel = stream->stream_info.stcChannel; stream->stream_info.decodeSettings.prerollRate = 1; stream->stream_info.primerHandle = NEXUS_VideoDecoder_OpenPrimer(stream->stream_info.videoDecoder); if (!stream->stream_info.primerHandle) { BDBG_WRN(("NEXUS_VideoDecoder_OpenPrimer failed %d\n",stream->index)); goto ExitError; } BDBG_ASSERT(stream->stream_info.decodeSettings.stcChannel); BDBG_ERR(("NEXUS_VideoDecoder_StartPrimer(0x%08x,0x%08x)\n",stream->stream_info.primerHandle)); NEXUS_VideoDecoder_StartPrimer(stream->stream_info.videoDecoder, stream->stream_info.primerHandle, &(stream->stream_info.decodeSettings)); stream->in_use = true; BDBG_WRN(("%s:%d\n",__FUNCTION__,__LINE__)); return stream; ExitError: if (stream) bstream_close(stream); return NULL; } void bstream_close(bstream_t stream) { BDBG_ASSERT(stream); BDBG_ASSERT(stream->stream_info.videoDecoder); BDBG_ASSERT(stream->stream_info.primerHandle); BDBG_WRN(("%s:%d\n",__FUNCTION__,__LINE__)); BDBG_ERR(("NEXUS_VideoDecoder_StopPrimer(0x%08x)\n",stream->stream_info.primerHandle)); NEXUS_VideoDecoder_StopPrimer(stream->stream_info.videoDecoder, stream->stream_info.primerHandle); NEXUS_VideoDecoder_ClosePrimer(stream->stream_info.videoDecoder,stream->stream_info.primerHandle); if (stream->stream_info.stcChannel) { NEXUS_StcChannel_Close(stream->stream_info.stcChannel); stream->stream_info.stcChannel = NULL; } if ((stream->stream_info.pcrPidChannel != stream->stream_info.videoPidChannel) && (stream->stream_info.pcrPidChannel != stream->stream_info.audioPidChannel) && stream->stream_info.pcrPidChannel) { NEXUS_PidChannel_Close(stream->stream_info.pcrPidChannel); stream->stream_info.pcrPidChannel = NULL; } if (stream->stream_info.videoPidChannel) { NEXUS_PidChannel_Close(stream->stream_info.videoPidChannel); stream->stream_info.videoPidChannel = NULL; } if (stream->stream_info.audioPidChannel) { NEXUS_PidChannel_Close(stream->stream_info.audioPidChannel); stream->stream_info.audioPidChannel = NULL; } stream->in_use = false; BDBG_WRN(("%s:%d\n",__FUNCTION__,__LINE__)); } static uint32_t ts_clock_diff_avg = 0; bresult bstream_get_status(bstream_t stream, bstream_status *status ) { BDBG_ASSERT(stream); BDBG_ASSERT(status); BKNI_Memset(status,0,sizeof(bstream_status)); status->mpeg = stream->mpeg; status->band = stream->band; return b_ok; } /** Summary: Return private stream structure. */ bsettop_p_stream_t *bstream_get_info(bstream_t stream) { return &(stream->stream_info); }