| #ifdef _FORTIFY_SOURCE |
| #undef _FORTIFY_SOURCE |
| #endif |
| /*************************************************************************** |
| * Copyright (c) 2014 Amlogic, Inc. All rights reserved. |
| * |
| * This source code is subject to the terms and conditions defined in the |
| * file 'LICENSE' which is part of this source code package. |
| * |
| * Description: |
| */ |
| /**\file |
| * \brief |
| * |
| * \author Gong Ke <ke.gong@amlogic.com> |
| * \date 2010-05-21: create the document |
| ***************************************************************************/ |
| |
| #define AM_DEBUG_LEVEL 1 |
| |
| //#include <am_debug.h> |
| #include "am_mem.h" |
| #include "am_dmx_internal.h" |
| #include "am_adp_internal.h" |
| #include <string.h> |
| #include <assert.h> |
| #include <unistd.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| //#include "am_misc.h" |
| |
| /**************************************************************************** |
| * Macro definitions |
| ***************************************************************************/ |
| |
| //#define DMX_WAIT_CB /*Wait callback function stop in API*/ |
| |
| #define DMX_SYNC |
| |
| #define DMX_BUF_SIZE (4096) |
| #define DMX_POLL_TIMEOUT (200) |
| #define DMX_DEV_COUNT (32) |
| |
| #define DMX_CHAN_ISSET_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]&(1<<((fid)&3))) |
| #define DMX_CHAN_SET_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]|=(1<<((fid)&3))) |
| #define DMX_CHAN_CLR_FILTER(chan,fid) ((chan)->filter_mask[(fid)>>3]&=~(1<<((fid)&3))) |
| |
| /**************************************************************************** |
| * Static data |
| ***************************************************************************/ |
| |
| #ifdef EMU_DEMUX |
| extern const AM_DMX_Driver_t emu_dmx_drv; |
| #define HW_DMX_DRV emu_dmx_drv |
| #else |
| extern const AM_DMX_Driver_t linux_dvb_dmx_drv; |
| #define HW_DMX_DRV linux_dvb_dmx_drv |
| #endif |
| //extern const AM_DMX_Driver_t dvr_dmx_drv; |
| //#define SW_DMX_DRV dvr_dmx_drv |
| |
| static AM_DMX_Device_t dmx_devices[DMX_DEV_COUNT] = |
| { |
| #ifdef EMU_DEMUX |
| { |
| .drv = &emu_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| }, |
| { |
| .drv = &emu_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| } |
| #else |
| { |
| .drv = &linux_dvb_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| }, |
| { |
| .drv = &linux_dvb_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| }, |
| { |
| .drv = &linux_dvb_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| }, |
| { |
| .drv = &linux_dvb_dmx_drv, |
| .src = AM_DMX_SRC_TS0 |
| } |
| #endif |
| }; |
| static void init_dmx_dev() { |
| static int init_dmx_dev_flag = 0; |
| int i = 0; |
| |
| if (!init_dmx_dev_flag) { |
| init_dmx_dev_flag = 1; |
| |
| for (i = 0; i < DMX_DEV_COUNT; i++) { |
| dmx_devices[i].drv = &linux_dvb_dmx_drv; |
| dmx_devices[i].src = AM_DMX_SRC_TS0; |
| } |
| } |
| } |
| /**************************************************************************** |
| * Static functions |
| ***************************************************************************/ |
| |
| /**\brief 根据设备号取得设备结构指针*/ |
| static AM_INLINE AM_ErrorCode_t dmx_get_dev(int dev_no, AM_DMX_Device_t **dev) |
| { |
| if (dev_no < 0 || dev_no >= DMX_DEV_COUNT) { |
| printf("invalid demux device number %d, must in(%d~%d)", dev_no, 0, DMX_DEV_COUNT-1); |
| return AM_DMX_ERR_INVALID_DEV_NO; |
| } |
| |
| *dev = &dmx_devices[dev_no]; |
| return AM_SUCCESS; |
| } |
| |
| /**\brief 根据设备号取得设备结构并检查设备是否已经打开*/ |
| static AM_INLINE AM_ErrorCode_t dmx_get_opened_dev(int dev_no, AM_DMX_Device_t **dev) |
| { |
| AM_TRY(dmx_get_dev(dev_no, dev)); |
| |
| if ((*dev)->open_count <= 0) { |
| printf("demux device %d has not been opened", dev_no); |
| return AM_DMX_ERR_INVALID_DEV_NO; |
| } |
| |
| return AM_SUCCESS; |
| } |
| |
| /**\brief 根据ID取得对应filter结构,并检查设备是否在使用*/ |
| static AM_INLINE AM_ErrorCode_t dmx_get_used_filter(AM_DMX_Device_t *dev, int filter_id, AM_DMX_Filter_t **pf) |
| { |
| AM_DMX_Filter_t *filter; |
| |
| if (filter_id < 0 || filter_id >= DMX_FILTER_COUNT) { |
| printf("invalid filter id, must in %d~%d", 0, DMX_FILTER_COUNT-1); |
| return AM_DMX_ERR_INVALID_ID; |
| } |
| |
| filter = &dev->filters[filter_id]; |
| |
| if (!filter->used) |
| { |
| printf("filter %d has not been allocated", filter_id); |
| return AM_DMX_ERR_NOT_ALLOCATED; |
| } |
| |
| *pf = filter; |
| return AM_SUCCESS; |
| } |
| |
| /**\brief 数据检测线程*/ |
| static void* dmx_data_thread(void *arg) |
| { |
| AM_DMX_Device_t *dev = (AM_DMX_Device_t*)arg; |
| uint8_t *sec_buf; |
| uint8_t *sec; |
| int sec_len; |
| AM_DMX_FilterMask_t mask; |
| AM_ErrorCode_t ret; |
| |
| #define BUF_SIZE (4096) |
| |
| sec_buf = (uint8_t*)malloc(BUF_SIZE); |
| |
| while (dev->enable_thread) { |
| AM_DMX_FILTER_MASK_CLEAR(&mask); |
| int id; |
| |
| ret = dev->drv->poll(dev, &mask, DMX_POLL_TIMEOUT); |
| if (ret == AM_SUCCESS) { |
| if (AM_DMX_FILTER_MASK_ISEMPTY(&mask)) |
| continue; |
| |
| #if defined(DMX_WAIT_CB) || defined(DMX_SYNC) |
| pthread_mutex_lock(&dev->lock); |
| dev->flags |= DMX_FL_RUN_CB; |
| pthread_mutex_unlock(&dev->lock); |
| #endif |
| |
| for (id = 0; id < DMX_FILTER_COUNT; id++) { |
| AM_DMX_Filter_t *filter = &dev->filters[id]; |
| AM_DMX_DataCb cb; |
| void *data; |
| |
| if (!AM_DMX_FILTER_MASK_ISSET(&mask, id)) |
| continue; |
| |
| if (!filter->enable || !filter->used) |
| continue; |
| |
| sec_len = BUF_SIZE; |
| |
| #ifndef DMX_WAIT_CB |
| pthread_mutex_lock(&dev->lock); |
| #endif |
| if (!filter->enable || !filter->used) { |
| ret = AM_FAILURE; |
| } else { |
| cb = filter->cb; |
| data = filter->user_data; |
| ret = dev->drv->read(dev, filter, sec_buf, &sec_len); |
| } |
| #ifndef DMX_WAIT_CB |
| pthread_mutex_unlock(&dev->lock); |
| #endif |
| if (ret == AM_DMX_ERR_TIMEOUT) { |
| sec = NULL; |
| sec_len = 0; |
| } else if (ret != AM_SUCCESS) { |
| continue; |
| } else { |
| sec = sec_buf; |
| } |
| |
| if (cb) { |
| if (id && sec) |
| printf("filter %d data callback len fd:%ld len:%d, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", |
| id, (long)filter->drv_data, sec_len, |
| sec[0], sec[1], sec[2], sec[3], sec[4], |
| sec[5], sec[6], sec[7], sec[8], sec[9]); |
| cb(dev->dev_no, id, sec, sec_len, data); |
| if (id && sec) |
| printf("filter %d data callback ok", id); |
| } |
| } |
| #if defined(DMX_WAIT_CB) || defined(DMX_SYNC) |
| pthread_mutex_lock(&dev->lock); |
| dev->flags &= ~DMX_FL_RUN_CB; |
| pthread_mutex_unlock(&dev->lock); |
| pthread_cond_broadcast(&dev->cond); |
| #endif |
| } else { |
| usleep(10000); |
| } |
| } |
| |
| if (sec_buf) { |
| free(sec_buf); |
| } |
| |
| return NULL; |
| } |
| |
| /**\brief 等待回调函数停止运行*/ |
| static AM_INLINE AM_ErrorCode_t dmx_wait_cb(AM_DMX_Device_t *dev) |
| { |
| #ifdef DMX_WAIT_CB |
| if (dev->thread != pthread_self()) { |
| while (dev->flags & DMX_FL_RUN_CB) |
| pthread_cond_wait(&dev->cond, &dev->lock); |
| } |
| #else |
| UNUSED(dev); |
| #endif |
| return AM_SUCCESS; |
| } |
| |
| /**\brief 停止Section过滤器*/ |
| static AM_ErrorCode_t dmx_stop_filter(AM_DMX_Device_t *dev, AM_DMX_Filter_t *filter) |
| { |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| if (!filter->used || !filter->enable) { |
| return ret; |
| } |
| |
| if (dev->drv->enable_filter) { |
| ret = dev->drv->enable_filter(dev, filter, AM_FALSE); |
| } |
| |
| if (ret >= 0) { |
| filter->enable = AM_FALSE; |
| } |
| |
| return ret; |
| } |
| |
| /**\brief 释放过滤器*/ |
| static int dmx_free_filter(AM_DMX_Device_t *dev, AM_DMX_Filter_t *filter) |
| { |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| if (!filter->used) |
| return ret; |
| |
| ret = dmx_stop_filter(dev, filter); |
| |
| if (ret == AM_SUCCESS) { |
| if (dev->drv->free_filter) { |
| ret = dev->drv->free_filter(dev, filter); |
| } |
| } |
| |
| if (ret == AM_SUCCESS) { |
| filter->used = AM_FALSE; |
| } |
| |
| return ret; |
| } |
| |
| /**************************************************************************** |
| * API functions |
| ***************************************************************************/ |
| |
| /**\brief 打开解复用设备 |
| * \param dev_no 解复用设备号 |
| * \param[in] para 解复用设备开启参数 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_Open(int dev_no, const AM_DMX_OpenPara_t *para) |
| { |
| AM_DMX_Device_t *dev; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| assert(para); |
| |
| init_dmx_dev(); |
| |
| AM_TRY(dmx_get_dev(dev_no, &dev)); |
| |
| // pthread_mutex_lock(&am_gAdpLock); |
| |
| if (dev->open_count > 0) { |
| printf("demux device %d has already been opened", dev_no); |
| dev->open_count++; |
| ret = AM_SUCCESS; |
| goto final; |
| } |
| |
| dev->dev_no = dev_no; |
| |
| if (para->use_sw_filter) { |
| // dev->drv = &SW_DMX_DRV; |
| } else { |
| dev->drv = &HW_DMX_DRV; |
| } |
| |
| if (dev->drv->open) { |
| ret = dev->drv->open(dev, para); |
| } |
| |
| if (ret == AM_SUCCESS) { |
| pthread_mutex_init(&dev->lock, NULL); |
| pthread_cond_init(&dev->cond, NULL); |
| dev->enable_thread = AM_TRUE; |
| dev->flags = 0; |
| |
| if (pthread_create(&dev->thread, NULL, dmx_data_thread, dev)) { |
| pthread_mutex_destroy(&dev->lock); |
| pthread_cond_destroy(&dev->cond); |
| ret = AM_DMX_ERR_CANNOT_CREATE_THREAD; |
| } |
| } |
| |
| if (ret == AM_SUCCESS) { |
| dev->open_count = 1; |
| } |
| final: |
| // pthread_mutex_unlock(&am_gAdpLock); |
| |
| return ret; |
| } |
| |
| /**\brief 关闭解复用设备 |
| * \param dev_no 解复用设备号 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_Close(int dev_no) |
| { |
| AM_DMX_Device_t *dev; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| int i; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| // pthread_mutex_lock(&am_gAdpLock); |
| |
| if (dev->open_count == 1) { |
| dev->enable_thread = AM_FALSE; |
| pthread_join(dev->thread, NULL); |
| |
| for (i = 0; i < DMX_FILTER_COUNT; i++) { |
| dmx_free_filter(dev, &dev->filters[i]); |
| } |
| |
| if (dev->drv->close) { |
| dev->drv->close(dev); |
| } |
| |
| pthread_mutex_destroy(&dev->lock); |
| pthread_cond_destroy(&dev->cond); |
| } |
| dev->open_count--; |
| |
| // pthread_mutex_unlock(&am_gAdpLock); |
| |
| return ret; |
| } |
| |
| /**\brief 分配一个过滤器 |
| * \param dev_no 解复用设备号 |
| * \param[out] fhandle 返回过滤器句柄 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_AllocateFilter(int dev_no, int *fhandle) |
| { |
| AM_DMX_Device_t *dev; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| int fid; |
| |
| assert(fhandle); |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| for (fid = 0; fid < DMX_FILTER_COUNT; fid++) { |
| if (!dev->filters[fid].used) |
| break; |
| } |
| |
| if (fid >= DMX_FILTER_COUNT) { |
| printf("no free section filter"); |
| ret = AM_DMX_ERR_NO_FREE_FILTER; |
| } |
| |
| if (ret == AM_SUCCESS) { |
| dmx_wait_cb(dev); |
| |
| dev->filters[fid].id = fid; |
| if (dev->drv->alloc_filter) { |
| ret = dev->drv->alloc_filter(dev, &dev->filters[fid]); |
| } |
| } |
| |
| if (ret == AM_SUCCESS) { |
| dev->filters[fid].used = AM_TRUE; |
| *fhandle = fid; |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 设定Section过滤器 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \param[in] params Section过滤器参数 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_SetSecFilter(int dev_no, int fhandle, const struct dmx_sct_filter_params *params) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| assert(params); |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| if (!dev->drv->set_sec_filter) { |
| printf("demux do not support set_sec_filter"); |
| return AM_DMX_ERR_NOT_SUPPORTED; |
| } |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| dmx_wait_cb(dev); |
| ret = dmx_stop_filter(dev, filter); |
| } |
| |
| if (ret == AM_SUCCESS) { |
| ret = dev->drv->set_sec_filter(dev, filter, params); |
| printf("set sec filter %d PID: %d filter: %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x %02x:%02x", |
| fhandle, params->pid, |
| params->filter.filter[0], params->filter.mask[0], |
| params->filter.filter[1], params->filter.mask[1], |
| params->filter.filter[2], params->filter.mask[2], |
| params->filter.filter[3], params->filter.mask[3], |
| params->filter.filter[4], params->filter.mask[4], |
| params->filter.filter[5], params->filter.mask[5], |
| params->filter.filter[6], params->filter.mask[6], |
| params->filter.filter[7], params->filter.mask[7]); |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 设定PES过滤器 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \param[in] params PES过滤器参数 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_SetPesFilter(int dev_no, int fhandle, const struct dmx_pes_filter_params *params) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| assert(params); |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| if (!dev->drv->set_pes_filter) { |
| printf("demux do not support set_pes_filter"); |
| return AM_DMX_ERR_NOT_SUPPORTED; |
| } |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| dmx_wait_cb(dev); |
| ret = dmx_stop_filter(dev, filter); |
| } |
| |
| if (ret == AM_SUCCESS) { |
| ret = dev->drv->set_pes_filter(dev, filter, params); |
| printf("set pes filter %d PID %d", fhandle, params->pid); |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| AM_ErrorCode_t AM_DMX_GetSTC(int dev_no, int fhandle) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| printf("%s line:%d\n", __FUNCTION__, __LINE__); |
| if (!dev->drv->get_stc) { |
| printf("demux do not support set_pes_filter"); |
| return AM_DMX_ERR_NOT_SUPPORTED; |
| } |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| ret = dev->drv->get_stc(dev, filter); |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| printf("%s line:%d\n", __FUNCTION__, __LINE__); |
| |
| return ret; |
| } |
| |
| |
| /**\brief 释放一个过滤器 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_FreeFilter(int dev_no, int fhandle) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| dmx_wait_cb(dev); |
| ret = dmx_free_filter(dev, filter); |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 让一个过滤器开始运行 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_StartFilter(int dev_no, int fhandle) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter = NULL; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (!filter->enable) { |
| if (ret == AM_SUCCESS) { |
| if (dev->drv->enable_filter) { |
| ret = dev->drv->enable_filter(dev, filter, AM_TRUE); |
| } |
| } |
| |
| if (ret == AM_SUCCESS) { |
| filter->enable = AM_TRUE; |
| } |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 停止一个过滤器 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_StopFilter(int dev_no, int fhandle) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter = NULL; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| if (filter->enable) { |
| dmx_wait_cb(dev); |
| ret = dmx_stop_filter(dev, filter); |
| } |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 设置一个过滤器的缓冲区大小 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \param size 缓冲区大小 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_SetBufferSize(int dev_no, int fhandle, int size) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| if (!dev->drv->set_buf_size) { |
| printf("do not support set_buf_size"); |
| ret = AM_DMX_ERR_NOT_SUPPORTED; |
| } |
| |
| if (ret == AM_SUCCESS) |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) |
| ret = dev->drv->set_buf_size(dev, filter, size); |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 取得一个过滤器对应的回调函数和用户参数 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \param[out] cb 返回过滤器对应的回调函数 |
| * \param[out] data 返回用户参数 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_GetCallback(int dev_no, int fhandle, AM_DMX_DataCb *cb, void **data) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| if (cb) |
| *cb = filter->cb; |
| |
| if (data) |
| *data = filter->user_data; |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 设置一个过滤器对应的回调函数和用户参数 |
| * \param dev_no 解复用设备号 |
| * \param fhandle 过滤器句柄 |
| * \param[in] cb 回调函数 |
| * \param[in] data 回调函数的用户参数 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_SetCallback(int dev_no, int fhandle, AM_DMX_DataCb cb, void *data) |
| { |
| AM_DMX_Device_t *dev; |
| AM_DMX_Filter_t *filter; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| |
| ret = dmx_get_used_filter(dev, fhandle, &filter); |
| |
| if (ret == AM_SUCCESS) { |
| dmx_wait_cb(dev); |
| |
| filter->cb = cb; |
| filter->user_data = data; |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| /**\brief 设置解复用设备的输入源 |
| * \param dev_no 解复用设备号 |
| * \param src 输入源 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_SetSource(int dev_no, AM_DMX_Source_t src) |
| { |
| AM_DMX_Device_t *dev; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| if (!dev->drv->set_source) { |
| printf("do not support set_source"); |
| ret = AM_DMX_ERR_NOT_SUPPORTED; |
| } |
| |
| if (ret == AM_SUCCESS) { |
| ret = dev->drv->set_source(dev, src); |
| } |
| |
| pthread_mutex_unlock(&dev->lock); |
| |
| if (ret == AM_SUCCESS) { |
| // pthread_mutex_lock(&am_gAdpLock); |
| dev->src = src; |
| // pthread_mutex_unlock(&am_gAdpLock); |
| } |
| |
| return ret; |
| } |
| |
| /**\brief DMX同步,可用于等待回调函数执行完毕 |
| * \param dev_no 解复用设备号 |
| * \return |
| * - AM_SUCCESS 成功 |
| * - 其他值 错误代码(见am_dmx.h) |
| */ |
| AM_ErrorCode_t AM_DMX_Sync(int dev_no) |
| { |
| AM_DMX_Device_t *dev; |
| AM_ErrorCode_t ret = AM_SUCCESS; |
| |
| AM_TRY(dmx_get_opened_dev(dev_no, &dev)); |
| |
| pthread_mutex_lock(&dev->lock); |
| if (dev->thread != pthread_self()) { |
| while (dev->flags & DMX_FL_RUN_CB) |
| pthread_cond_wait(&dev->cond, &dev->lock); |
| } |
| pthread_mutex_unlock(&dev->lock); |
| |
| return ret; |
| } |
| |
| AM_ErrorCode_t AM_DMX_GetScrambleStatus(int dev_no, AM_Bool_t dev_status[2]) |
| { |
| #if 0 |
| char buf[32]; |
| char class_file[64]; |
| int vflag, aflag; |
| int i; |
| |
| dev_status[0] = dev_status[1] = AM_FALSE; |
| snprintf(class_file, sizeof(class_file), "/sys/class/dmx/demux%d_scramble", dev_no); |
| for (i = 0; i < 5; i++) { |
| if (AM_FileRead(class_file, buf, sizeof(buf)) == AM_SUCCESS) { |
| sscanf(buf, "%d %d", &vflag, &aflag); |
| if (!dev_status[0]) |
| dev_status[0] = vflag ? AM_TRUE : AM_FALSE; |
| if (!dev_status[1]) |
| dev_status[1] = aflag ? AM_TRUE : AM_FALSE; |
| // AM_DEBUG(1, "AM_DMX_GetScrambleStatus video scramble %d, audio scramble %d\n", vflag, aflag); |
| if (dev_status[0] && dev_status[1]) { |
| return AM_SUCCESS; |
| } |
| usleep(10 * 1000); |
| } else { |
| printf("AM_DMX_GetScrambleStatus read scramble status failed\n"); |
| return AM_FAILURE; |
| } |
| } |
| #endif |
| return AM_SUCCESS; |
| } |
| |
| |