libdvbpsi库使用方法简介

本文介绍libdvbpsi库的基本使用方法,包括获取句柄、绑定解码器、发送TS数据包等步骤,并提供了PAT表解析的具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只是简单介绍了libdvbpsi库的使用方法,希望对其他童鞋有所帮助。
对于函数和结构体的定义,请查找在线帮助文档:http://www.videolan.org/developers/libdvbpsi/doc/doxygen/html/
本文是以1.1.0版本为参照进行介绍。

1 基本使用方法

  基本步骤如下:

(1)使用dvbpsi_new接口获取句柄并注册消息处理函数
(2)绑定所需要的解码器,绑定解码器所需要的回调函数。
(3)发送TS数据包进行解析
(4)解除绑定的解码器
(5)释放库句柄

  下面是以pat表的解析为例进行说明的。具体可以参照实例程序中的decode_pat.c。

(1)使用dvbpsi_new接口获取句柄并注册消息处理函数。

dvbpsi_t *p_dvbpsi = dvbpsi_new(&message, DVBPSI_MSG_DEBUG);
if(p_dvbpsi==NULL)
    //错误处理
  在使用前需要获得dvbpsi库的句柄(这里的句其实是指向一个数据结构的指针),一个句柄对应一个解码环境,就相当于一个工作空间,通过获取多个句柄就可以同时进行多种解码。
  消息处理函数是用户编写的,由库调用,当库有消息(比如错误提示,警告)提示用户时,库将调用该函数。用户在该函数内处理消息(比如打印到屏幕上)。消息处理函数的声明可以在在线文档中找到。
  函数声明为:
dvbpsi_t * dvbpsi_new (
    dvbpsi_message_cb  callback,
    enum dvbpsi_msg_level  level
);
  dvbpsi_t结构体类型:

typedef struct dvbpsi_s dvbpsi_t; //dvbpsi_t是dvbpsi_s的别名
struct dvbpsi_s
{
    dvbpsi_decoder_t *  p_decoder ,//标识解码器
    dvbpsi_message_cb  pf_message ,//消息处理函数,dvbpsi_new函数中设置
    enum dvbpsi_msg_level  i_msg_level ,//消息等级,dvbpsi_new函数中设置
    void *  p_sys,//指向调用者的私有数据,不能使用库内的数据,否则程序崩溃
};

  典型的消息处理函数如下(取自examples文件夹中的示例程序),可以根据需要编写:

static void message(
    dvbpsi_t *handle,
    const dvbpsi_msg_level_t level,
    const char* msg)//消息内容
{
    switch(level)
    {
        case DVBPSI_MSG_ERROR: fprintf(stderr, "Error: "); break;
        case DVBPSI_MSG_WARN:  fprintf(stderr, "Warning: "); break;
        case DVBPSI_MSG_DEBUG: fprintf(stderr, "Debug: "); break;
        default: /* do nothing */
            return;
    }
    fprintf(stderr, "%s\n", msg);
}

  这一步需要包含头文件dvbpsi.h,psi.h

(2)绑定所需要的解码器,绑定解码器所需要的回调函数。

  dvbpsi_XXX_attach()将给dvbpsi_t* 附上一个XXX表解码器(XXX:一个表对应一个解码器,一个表也对应一个绑定函数,由于绑定函数命名非常规整,所以接口    dvbpsi_XXX_attach就是绑定某个表的解码器),库将使用该解码器进行工作。也就是给(dvbpsi_t*)->p_decoder赋值。该函数将返回新的绑定了解码器的库句柄。
  接口需要指定一个回调函数,当库解析出了某个表时,将调用该回调函数,用户在回调函数中实现数据的处理即可。回调函数的格式也都是统一的。见在线帮助文档。
  当解码器不需要使用,需用相应的函数进行解绑。
  需包含相应表的头文件。

例如(PAT表解码):

//包含头文件pat.h
//DumpPAT为回调函数,处理解析出的PAT表
if(!dvbpsi_pat_attach(p_dvbpsi, DumpPAT, NULL))
    错误处理
 
//---------------------------------------------------------------------------------
//附函数声明和结构体定义
//绑定函数
bool dvbpsi_pat_attach(
    dvbpsi_t *  p_dvbpsi,
    dvbpsi_pat_callback  pf_callback,
    void *  p_cb_data);//一般为NULL
typedef void(* dvbpsi_pat_callback )(void *p_cb_data, dvbpsi_pat_t *p_new_pat);
 
//记录表数据的结构体
typedef struct dvbpsi_pat_s  dvbpsi_pat_t;
struct dvbpsi_pat_s
{
    uint16_t  i_ts_id;//ts流id
    int8_t  i_version;//版本号
    bool  b_current_next;
    dvbpsi_pat_program_t *  p_first_program;//第一个节目节点。(节目列表用链表记录的,遍历该链表就可以获取所有节目,关于该结构体的详细说明见在线帮助文档)
};

对于所在数据包中只包含某个表的表,直接调用dvbpsi_xxx_attach,然后在回调函数中解码即可。比如PAT表。
对于所在数据包包含多个表的表,需先调用dvbpsi_AttachDemux(解复用程序)解码出子表,然后在回调函数中进行dvbpsi_xxx_attach,其后的操作与上面的相同。比如SDT表。这时的dvbpsi_xxx_attach函数还需要将子表id作为参数,从而绑定相应的子表解码器。子表解码器不需要解绑。详见“复杂表的解析”。

(3)发送TS数据包

  通过dvbpsi_packet_push()发送数据包给解码器,如果一个表处理完了,解码器将调用dvbpsi_XXX_attach绑定的回调函数。回调函数中会包含解码出的数据。如果数据中包含descriples(p_first_descriptor指针),那么需要额外再调用处理descriptors的函数(将p_descriptor作为参数传递给处理函数,处理函数会返回结果)。descriptors处理详见dr.h部分。
  所有表的解析都是调用这个函数发送数据进行解析。
  例如:

dvbpsi_packet_push(p_dvbpsi, data);//p_dvbpsi是句柄,data是188字节的数据。读取数据的函数为ReadPacket。
  当有表被解析处理后回调函数就会被执行。
  注意当记录某个表的所有数据都被解析了(即表完全解析完),解码过程才会结束,并调用回调函数。比如记录EIT (table_id=0x50,servic_id=19)的表共用了20个section,只有20个section全部解析完成才行。

  函数声明为:

//p_data是一个188字节数据包
//包含dvbpsi.h
bool dvbpsi_packet_push(dvbpsi_t *  p_dvbpsi,uint8_t *  p_data);

(4)解除绑定的解码器

  当不需要再使用该解码器时,调用dvbpsi_XXX_detach解除解码器。
  例如:

dvbpsi_pat_detach(p_dvbpsi);//解除后该句柄不能再用了解码了。

  包含相应表的头文件。

(5) 释放库句柄

  应用程序结束,调用dvbpsi_delete()释放句柄,例如:

dvbpsi_delete(p_dvbpsi);

在此之前,需解除绑定的解码器,例如:

dvbpsi_pat_detach(p_dvbpsi);//解除后该句柄不能再用了解码了。

2 简单表的解析

使用的基本解析流程,见“使用方法”。比如:PAT表,PMT表。PMT在attach的时候给定需要给定program_number和i_program_number,这样库才知道需要解析那个节目的PMT表。

3 复杂表的解析

  需先通过解复用将子表解析出来,然后为各个子表绑解码器,解码子表的过程同“简单表的解析”。
  解复用需调用dvbpsi_AttachDemux绑定解复用过程,解复用过程解析出子表后将调用dvbpsi_AttachDemux函数中指定的回调函数,然后再该回调函数中对为子表绑定解码器。
  SDT表、EIT表等都需要使用这种方式进行解析。可以参考decode_sdt.c示例程序。
   例EIT表:
    dvbpsi_eit_attach将table_id、servic_id、callback_func关联起来。不能立即解除绑定,因为一组(table_id,servic_id)指定一个解码过程,该过程会记录已解码的表,当再次出现相同的表时不在解码。如果解除绑定,解码过程也释放了,再次出现相同的表时会再次解码。

4 描述符解析

  dir.h文件将dr_XX.h包含至一个头文件。这些dr_xx.h文件都是用来解析descriptors(描述符)的。xx对应的是描述符的标识符。
  解码工作完成后库调用的回调函数中,处理后的数据以指针的方式作为参数传递出来。在数据中,descriptors通过一个p_first_descriptor指针访问。
  所有的descriptors都用同一个结构体描述,即:dvbpsi_descriptor_t。因此所有的解析函数都使用dvbpsi_descriptor_t*作为参数,而且这些函数的参数几乎都一样,只是函数名和返回值不同。p_descriptor->i_tag指明描述符类型,以便调用相应的解析函数。
  解析descriptors时,将p_descriptor作为参数调用相应的解析函数,处理结果在返回值中。
  例如解析EIT表的事件名和事件简介: 
if(p_descriptor->i_tag==0x4d)//对应的描述符id为0x4d
{
    dvbpsi_short_event_dr_t *p=dvbpsi_DecodeShortEventDr(p_descriptor);
    //结构体dvbpsi_short_event_dr_t中就包含了事件名和简介
}

一、 编译安装VLC 使用vlc-1.0.5.tar.bz2 + live555-2010.01.tar.gz export MYDIR=/root/lf 将live555-2010.01.tar.gz和vlc-1.0.5.tar.bz2放置在$MYDIR下 cd $MYDIR (一) 编译liveMedia tar xvfz live555-2010.01.tar.gz cd live ./genMakefiles linux make (二) 安装libdvbpsi rpm -hiv libdvbpsi-0.1.7-1.el4.rf.i386.rpm rpm -hiv libdvbpsi-devel-0.1.7-1.el4.rf.i386.rpm 需要什么rpm可到http://apt.sw.be/redhat/el4/en/i386/rpmforge/RPMS/中下载 (三) 编译VLC 1. configure ./configure --prefix=/usr --enable-debug --disable-avcodec --disable-hal --disable-avformat --disable-swscale --disable-a52 --disable-x11 --disable-sdl --disable-fribidi --disable-dbus --disable-libgcrypt --disable-gnutls --disable-remoteosd --disable-skins2 --disable-qt4 --disable-libxml2 --disable-lua --disable-xcb --disable-alsa --disable-v4l2 --disable-qt --enable-run-as-root --enable-live555 --with-live555-tree=$MYDIR/live --disable-mad --disable-postproc --enable-dvbpsi --enable-x264 2. make 3. 出现错误error: syntax error before "vlc_spinlock_t": ../include/vlc_threads.h:240: error: syntax error before "vlc_spinlock_t" …… make[4]: *** [control/libvlc_la-vlm.lo] Error 1 make[4]: Leaving directory `/root/lf/vlc-1.0.5/src' make[3]: *** [all-recursive] Error 1 make[3]: Leaving directory `/root/lf/vlc-1.0.5/src' make[2]: *** [all] Error 2 make[2]: Leaving directory `/root/lf/vlc-1.0.5/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/root/lf/vlc-1.0.5' make: *** [all] Error 2 通过以下命令解决: sed -e 's/define\s*_POSIX_SPIN_LOCKS\s*/define _POSIX_SPIN_LOCKS -1 \/\/ wrong: /g' -i /usr/include/bits/posix_opt.h 4. 重试make出现error: `AFS_SUPER_MAGIC' undeclared: file.c:52:28: linux/magic.h: No such file or directory file.c: In function `IsRemote': file.c:141: error: `AFS_SUPER_MAGIC' undeclared (first use in this function) file.c:141: error: (Each undeclared identifier is reported only once file.c:141: error: for each function it appears in.) file.c:142: error: `CODA_SUPER_MAGIC' undeclared (first use in this function) file.c:143: error: `NCP_SUPER_MAGIC' undeclared (first use in this function) file.c:144: error: `NFS_SUPER_MAGIC' undeclared (first use in this function) file.c:145: error: `SMB_SUPER_MAGIC' undeclared (first use in this function) make[5]: *** [libaccess_file_plugin_la-file.lo] Error 1 make[5]: Leaving directory `/root/lf/vlc-1.0.5/modules/access' make[4]: *** [all-recursive] Error 1 make[4]: Leaving directory `/root/lf/vlc-1.0.5/modules/access' make[3]: *** [all] Error 2 make[3]: Leaving directory `/root/lf/vlc-1.0.5/modules/access' make[2]: *** [all-recursive] Error 1 make[2]: Leaving directory `/root/lf/vlc-1.0.5/modules' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/root/lf/vlc-1.0.5' make: *** [all] Error 2 将下面的magic.h文件复制到/usr/include/linux/目录下 5. make install 6. 检查 vlc -l | grep access_output access_output_udp UDP stream output access_output_http HTTP stream output access_output_file File stream output access_output_dummy Dummy stream output access_output_rtmp RTMP stream output vlc -l | grep dvbpsi mux_ts TS muxer (libdvbpsi) (四) 进行RTSP To TS转码:  不经视音频重编码的直接转码: vlc rtsp://172.17.0.219:8554/1 --sout '#standard{access=http, mux=ts, dst=172.17.0.100:1234}' 注:黑体部分为本机IP和端口,不能是127.0.0.1 vlc rtsp://172.17.0.219:8554/1 --sout '#duplicate{dst="std{access=udp, mux=ts, dst=172.17.1.116:1234}"}' vlc rtsp://172.17.0.219:8554/1 --sout '#duplicate{dst="std{access=http, mux=ts, dst=172.17.0.100:1234}"}' 二、 视音频重编码的VLC编译安装 (一) 需要编译安装ffmpeg ./configure --prefix=/usr --enable-libfaac --enable-libx264 --enable-pthreads --disable-ffserver --disable-ffplay --enable-gpl --enable-nonfree [root@localhost ffmpeg-0.6.7]# make common.mak:28: *** unterminated call to function `foreach': missing `)'. Stop. 出现上面错误需要更新Make版本,使用make-3.81.tar.gz ./configure --prefix=/usr;make;make install In file included from libavdevice/v4l.c:33: /usr/include/linux/videodev.h:56: error: syntax error before "ulong" /usr/include/linux/videodev.h:72: error: syntax error before '}' token 编辑/usr/include/linux/videodev.h第56行,把ulong改为 unsigned long (二) 编译VLC ./configure --prefix=/usr --enable-debug --enable-avcodec --disable-hal --disable-avformat --disable-swscale --disable-a52 --disable-x11 --disable-sdl --disable-fribidi --disable-dbus --disable-libgcrypt --disable-gnutls --disable-remoteosd --disable-skins2 --disable-qt4 --disable-libxml2 --disable-lua --disable-xcb --disable-alsa --disable-v4l2 --disable-qt --enable-run-as-root --enable-live555 --with-live555-tree=$MYDIR/live --disable-mad --disable-postproc --enable-dvbpsi --enable-x264 没有--enable-avcodec运行VLC转码会出现"cannot find video decoder"的错误。 (三) 进行RTSP To TS转码: vlc tcp://172.17.0.199:7799 --sout '#duplicate{dst="transcode{venc=x264{profile=baseline},vcodec=h264,acodec=mpga,vb=644,ab=56}:std{access=udp,mux=ts,dst=172.17.0.219:1234}"}' 使用VLC转时,不要激活转码 可正常工作的选项: :sout=#http{mux=ts,dst=:8080/1} :sout-keep :sout=#udp{mux=ts,dst=172.17.1.116:1234} :sout-keep http://www.videolan.org/doc/videolan-howto/en/ch09.html ffmpeg -i "rtsp://172.17.0.219:8554/1" -acodec libfaac -vcodec libx264 -vpre default -f mpegts -async 1 udp://127.0.0.1:3344 ./configure --prefix=/usr --enable-libfaac --enable-libx264 --enable-pthreads --disable-ffserver --disable-ffplay --enable-gpl --enable-nonfree 转码 ffmpeg -i "rtsp://172.17.0.219:8080/1" -acodec libfaac -vcodec libx264 -vpre default -f mpegts -async 1 udp://172.17.0.219:3344
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值