次文章记录了在Android系统中使用vlcplayer播放DVB制式数字TV遇到的问题。
在Android上使用win-tv-975 电视棒播放实现中,win-tv-975的frontend节点有两个,ATSC/QAM时使用节点/dev/dvb/adapter0/frontend0,DVB制式时使用/dev/dvb/adapter0/frontend1,log如下:
06-08 08:03:08.477 4300 4300 I cx231xx 5-1: 1.1: DVB: registering adapter 0 frontend 0 (LG Electronics LGDT3306A VSB/QAM Frontend)...
06-08 08:03:08.478 4300 4300 I cx231xx 5-1: 1.1: DVB: registering adapter 0 frontend 1 (Silicon Labs Si2168)...
节点截图如下
但是vlcplayer不支持这种的。查看vlcplayer源码,其只定义了dvb-adapter和dvb-device两个参数,dmx节点和frontend节点使用dvb-device决定了demux、frontend设备号只能是一样的。
vlc/modules/access/dvb/linux_dvb.c
#define DMX "/dev/dvb/adapter%d/demux%d"
#define FRONTEND "/dev/dvb/adapter%d/frontend%d"
#define DVR "/dev/dvb/adapter%d/dvr%d"
i_adapter = var_GetInteger( p_access, "dvb-adapter" );
i_device = var_GetInteger( p_access, "dvb-device" );
snprintf( frontend, sizeof(frontend), FRONTEND, i_adapter, i_device );
snprintf( dmx, sizeof(dmx), DMX, i_adapter, i_device );//dmx节点和frontend节点使用dvb-device
所以这里需要修改vlc库源码使他能动态配置demux、frontend的设备号。这里新增dvb-dmx-device和dvb-frontend-device配置项,默认值是-1
vlc/modules/access/dtv/access.c
add_integer ("dvb-dmx-device", -1, DEVICE_TEXT, DEVICE_LONGTEXT, false)
change_safe ()
add_integer ("dvb-frontend-device", -1, DEVICE_TEXT, DEVICE_LONGTEXT, false)
change_safe ()
判断如果app配置了dvb-frontend-device或者dvb-dmx-device参数,则获取并用之,否则默认使用dvb-device。这样实现demux和frontend的设备号可以不一样。
vlc源码中grep dvb-device一下,在使用dvb-device的地方需要修改,linux_dvb.c如下:
vlc/modules/access/dvb/linux_dvb.c
int FrontendOpen( vlc_object_t *p_access, dvb_sys_t *p_sys, const char *psz_access )
unsigned int i_adapter, i_device,i_frotend_device;
i_frotend_device = var_GetInteger( p_access, "dvb-frontend-device");
i_adapter = var_GetInteger( p_access, "dvb-adapter" );
i_device = var_GetInteger( p_access, "dvb-device" );
if(i_frotend_device >= 0){
i_device=i_frotend_device;
}
int DMXSetFilter( vlc_object_t *p_access, int i_pid, int * pi_fd, int i_type )
i_dmx_device = var_GetInteger( p_access, "dvb-dmx-device");
i_adapter = var_GetInteger( p_access, "dvb-adapter" );
i_device = var_GetInteger( p_access, "dvb-device" );
if(i_dmx_device>=0){
i_device =i_dmx_device;
}
linux.c中也有使用,修改如下:
vlc/modules/access/dtv/linux.c
uint8_t frontend_device;
uint8_t demux_device;
d->demux_device = var_InheritInteger (obj, "dvb-dmx-device");
d->frontend_device = var_InheritInteger (obj, "dvb-frontend-device");
/** Opens the DVB device node of the specified type */
static int dvb_open_node (dvb_device_t *d, const char *type, int flags)
{
char path[strlen (type) + 4];
uint8_t device = d->device;
if(0==strcmp(type,"frontend")){
if(d->frontend_device>=0){
device= d->frontend_device;
}
}
if(0==strcmp(type,"demux")){
if(d->demux_device >=0){
device= d->demux_device;
}
}
snprintf (path, sizeof (path), "%s%u", type,device);
这样修改以后,重新编译出vlc player aar包,app中配置ATSC播放是配置–dvb-frontend-device=1而DVB播放时使用–dvb-frontend-device=0即可。
private ArrayList<String> getOpt() {
final ArrayList<String> args = new ArrayList<>();//VLC参数
switch (norm) {
case TYPE_ATSC:
args.add("--live-caching=1000");
args.add("--dvb-adapter=0");
args.add("--file-caching=1000");
args.add("--sub-track=0");
args.add("--dvb-frontend-device=0");
args.add("--dvb-dmx-device=0");
break;
case TYPE_DVB_C:
case TYPE_DVB_S:
case TYPE_DVB_T:
case TYPE_DVB_S2:
case TYPE_DVB_T2:
args.add("--live-caching=1000");
args.add("--file-caching=1000");
args.add("--dvb-adapter=0");
args.add("--sub-track=0");
args.add("--dvb-frontend-device=1");
args.add("--dvb-dmx-device=0");
break;