/*************************************************************************** * Copyright (C) 2014-2025 Amlogic, Inc. All rights reserved. * * All information contained herein is Amlogic confidential. * * This software is provided to you pursuant to Software License Agreement * (SLA) with Amlogic Inc ("Amlogic"). This software may be used * only in accordance with the terms of this agreement. * * Redistribution and use in source and binary forms, with or without * modification is strictly prohibited without prior written permission from * Amlogic. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Description: * Demux module, basic data structures definition in "linux/dvb/dmx.h" ***************************************************************************/ #include #include #include #include "AmlogicUtil.h" #ifdef __cplusplus extern "C" { #endif /** Error code of the demux module*/ enum DEMUX_ERROR_CODE { DEMUX_ERROR_BASE = ERROR_BASE(AM_MOD_DMX), DEMUX_ERROR_INVALID_DEV_NO, /** Invalid device number*/ DEMUX_ERROR_INVALID_ID, /** Invalid filer handle*/ DEMUX_ERROR_BUSY, /** The device has already been opened*/ DEMUX_ERROR_NOT_ALLOCATED, /** The device has not been allocated*/ DEMUX_ERROR_CANNOT_CREATE_THREAD, /** Cannot create new thread*/ DEMUX_ERROR_CANNOT_OPEN_DEV, /** Cannot open device*/ DEMUX_ERROR_NOT_SUPPORTED, /** Not supported*/ DEMUX_ERROR_NO_FREE_FILTER, /** No free filter*/ DEMUX_ERROR_NO_MEM, /** Not enough memory*/ DEMUX_ERROR_TIMEOUT, /** Timeout*/ DEMUX_ERROR_SYS, /** System error*/ DEMUX_ERROR_NO_DATA, /** No data received*/ DEMUX_ERROR_END }; /**************************************************************************** * Type definitions ***************************************************************************/ /** Input source of the demux*/ typedef enum { DEMUX_SRC_TS0, /** TS input port 0*/ DEMUX_SRC_TS1, /** TS input port 1*/ DEMUX_SRC_TS2, /** TS input port 2*/ DEMUX_SRC_TS3, /** TS input port 3*/ DEMUX_SRC_HIU, /** HIU input (memory)*/ DEMUX_SRC_HIU1 } AmlogicDemuxSourceType; /** Demux device open parameters*/ typedef struct { bool use_sw_filter; /** M_TRUE to use DVR software filters.*/ int dvr_fifo_no; /** Async fifo number if use software filters.*/ int dvr_buf_size; /** Async fifo buffer size if use software filters.*/ } AmlogicDemuxOpenParameterType; // Added to get the newest demux pts. Codes come from demuxer driver. enum { AMDMX_VIDEO_TYPE = 0, AMDMX_AUDIO_TYPE, AMDMX_SUBTITLE_TYPE, AMDMX_TELETEXT_TYPE, AMDMX_SECTION_TYPE, }; typedef struct { __u32 dmx_total_size; __u32 dmx_buf_phy_start; __u32 dmx_free_size; __u32 dvb_core_total_size; __u32 dvb_core_free_size; __u32 wp_offset; __u64 newest_pts; // The latest demux pts } amdmx_mem_info; typedef struct { __u32 type; // AMDMX_*_TYPE __u32 pid; // Filter pid amdmx_mem_info filter_info; // amdmx_mem_info } amfilter_mem_info; typedef struct { __u32 filter_num; // The number of amfilter_mem_info amfilter_mem_info info[40]; // Detail of filters } amdmx_filter_mem_info; #define AMDMX_GET_FILTER_MEM_INFO _IOR('o', 84, amdmx_filter_mem_info) // [END]: Added to get the newest demux pts. come from demuxer driver. /** Filter received data callback function * \a fhandle is the filter's handle. * \a data is the received data buffer pointer. * \a len is the data length. * If \a data == null, means timeout. */ typedef void (*DemuxDataCb)(int dev_no, int fhandle, const uint8_t *data, int len, void *user_data); /**************************************************************************** * Function prototypes ***************************************************************************/ /** Open a demux device * dev_no Demux device number * \param[in] para Demux device's open parameters * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxOpen(int dev_no, const AmlogicDemuxOpenParameterType *para); /** Close a demux device * dev_no Demux device number * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxClose(int dev_no); /** Allocate a filter * dev_no Demux device number * \param[out] fhandle Return the allocated filter's handle * \retval AM_SUCCESS On success * \return Error Code */ extern int DemuxAllocateFilter(int dev_no, int *fhandle); /** Set a section filter's parameters * dev_no Demux device number * fhandle Filter handle * \param[in] params Section filter's parameters * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSetSecFilter(int dev_no, int fhandle, const struct dmx_sct_filter_params *params); /** Set a PES filter's parameters * dev_no Demux device number * fhandle Filter handle * \param[in] params PES filter's parameters * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSetPesFilter(int dev_no, int fhandle, const struct dmx_pes_filter_params *params); /** Release an unused filter * dev_no Demux device number * fhandle Filter handle * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxFreeFilter(int dev_no, int fhandle); /** Start filtering * dev_no Demux device number * fhandle Filter handle * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxStartFilter(int dev_no, int fhandle); /** Stop filtering * dev_no Demux device number * fhandle Filter handle * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxStopFilter(int dev_no, int fhandle); /** Set the ring queue buffer size of a filter * dev_no Demux device number * fhandle Filter handle * size Ring queue buffer size in bytes * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSetBufferSize(int dev_no, int fhandle, int size); /** Get a filter's data callback function * dev_no Demux device number * fhandle Filter handle * \param[out] cb Return the data callback function of the filter * \param[out] data Return the user defined parameter of the callback function * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxGetCallback(int dev_no, int fhandle, DemuxDataCb *cb, void **data); /** Set a filter's data callback function * dev_no Demux device number * fhandle Filter handle * \param[in] cb New data callback function * \param[in] data User defined parameter of the callback function * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSetCallback(int dev_no, int fhandle, DemuxDataCb cb, void *data); /** Set the demux input source * dev_no Demux device number * src Input source * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSetSource(int dev_no, AmlogicDemuxSourceType src); /**\cond */ /** Sync the demux data * dev_no Demux device number * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxSync(int dev_no); /**\endcond */ /** * Get the scramble status of the AV channels in the demux * dev_no Demux device number * \param[out] dev_status Return the AV channel scramble status. * dev_status[0] is the video status, dev_status[1] is the audio status. * true means the channel is scrambled, 0 means the channel is not scrambled. * \retval AM_SUCCESS On success * \return Error code */ extern int DemuxGetScrambleStatus(int dev_no, bool dev_status[2]); /** * Get the newest AV PTS at current time in the demuxer, which located in * amdmx_filter_mem_info structure. * \param[in] dev_no Demux device number. * \param[out] demuxFilterMemInfo Return demux filter memory information. * \retval AM_SUCCESS on success, otherwise is AM_FAILURE. */ extern int DemuxGetNewestPts(int dev_no, amdmx_filter_mem_info *demuxFilterMemInfo); #define DEMUX_FILTER_COUNT (32) #define DEMUX_WAKE_POLL_EVENT (1) #define DEMUX_FILTER_COUNT_EXT DEMUX_FILTER_COUNT + DEMUX_WAKE_POLL_EVENT #define DMX_FL_RUN_CB (1) /**************************************************************************** * Type definitions ***************************************************************************/ /** Demultiplexing equipment*/ typedef struct DemuxDevice DemuxDeviceType; /** Filter*/ typedef struct DemuxFilter DemuxFilterType; /** Filter bit mask*/ typedef uint32_t Demux_FilterMaskType; #define DEMUX_FILTER_MASK_ISEMPTY(m) (!(*(m))) #define DEMUX_FILTER_MASK_CLEAR(m) (*(m) = 0) #define DEMUX_FILTER_MASK_ISSET(m, i) (*(m) & (((unsigned int)1 << (i)) & 0xFFFFFFFF)) #define DEMUX_FILTER_MASK_SET(m, i) (*(m) |= ((unsigned int)1 << (i))) /** Demultiplexing device drivers*/ typedef struct { int (*open)(DemuxDeviceType *dev, const AmlogicDemuxOpenParameterType *para); int (*close)(DemuxDeviceType *dev); int (*wake)(DemuxDeviceType *dev); int (*alloc_filter)(DemuxDeviceType *dev, DemuxFilterType *filter); int (*free_filter)(DemuxDeviceType *dev, DemuxFilterType *filter); int (*set_sec_filter)(DemuxDeviceType *dev, DemuxFilterType *filter, const struct dmx_sct_filter_params *params); int (*set_pes_filter)(DemuxDeviceType *dev, DemuxFilterType *filter, const struct dmx_pes_filter_params *params); int (*enable_filter)(DemuxDeviceType *dev, DemuxFilterType *filter, bool enable); int (*set_buf_size)(DemuxDeviceType *dev, DemuxFilterType *filter, int size); int (*poll)(DemuxDeviceType *dev, Demux_FilterMaskType *mask, int timeout); int (*poll_exit)(DemuxDeviceType *dev); int (*read)(DemuxDeviceType *dev, DemuxFilterType *filter, uint8_t *buf, int *size); int (*set_source)(DemuxDeviceType *dev, AmlogicDemuxSourceType src); int (*get_newest_pts)(DemuxDeviceType *dev, amdmx_filter_mem_info *demuxFilterMemInfo); } DemuxDriverType; /** Section filter*/ struct DemuxFilter { void *drv_data; /** Driver private data*/ bool used; /** Whether this Filter has been allocated*/ bool enable; /** Whether this Filter device is enabled*/ int id; /** Filter ID*/ DemuxDataCb cb; /** Demultiplexing data callback function*/ void *user_data; /** Data callback function user parameters*/ }; /** Demultiplexing device*/ struct DemuxDevice { int dev_no; /** device number*/ const DemuxDriverType *drv; /** device driver*/ void *drv_data; /** Driver private data*/ DemuxFilterType filters[DEMUX_FILTER_COUNT]; /** Filter in the device*/ int open_count; /** The number of times the device has been opened*/ bool enable_thread; /** The data thread is already running*/ int flags; /** Thread running status control flag*/ pthread_t thread; /** data detection thread*/ pthread_mutex_t lock; /** device protection mutex*/ pthread_cond_t cond; /** condition variable*/ AmlogicDemuxSourceType src; /** TS input source*/ }; #ifdef __cplusplus } #endif