Files
2026-08-24 10:03:24 +08:00

327 lines
12 KiB
C

/***************************************************************************
* 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 <linux/dvb/dmx.h>
#include <stdbool.h>
#include <stdint.h>
#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