libdvbpsi库的使用
来源:互联网 发布:人工智能会议 2017 编辑:程序博客网 时间:2024/06/06 04:23
@By涂启明
@email:tuqiming_x@163.com
@
@如果您发现了错误,或者有什么建议或意见,请务必通过邮件告诉我
@直接从word里拷贝上来的,排版很烂啊,哎,写得也很烂
同其他linux代码库一样,libdvbpsi库也没有在其网站上找到一个完整的使用说明,虽然有一个简单得不能再简单的介绍,但是要使用这个库进行正式开放还远远不够,只能通过阅读示例程序进行更多的了解。这篇文章只是在我现有认识的基础上的简单介绍,希望这能让你更快掌握libdvbpsi库的使用。
对于函数和结构体的定义,请查找在线帮助文档:
http://www.videolan.org/developers/libdvbpsi/doc/doxygen/html/
本文是以1.1.0版本为参照进行介绍。
1 使用方法
libdvbpsi库自0.2.0版本起使用了新的接口和使用方法, 0.1.7之前的版本使用的是另一种更为简单的使用方法。在线帮助文档中对老版本转新版本做了说明:
http://www.videolan.org/developers/libdvbpsi/doc/doxygen/html/howto-new-api.html
下面是以pat表的解析为例进行说明的。具体可以参照实例程序中的decode_pat.c。
1.1 使用dvbpsi_new获取句柄并注册消息处理函数。
在使用前需要获得dvbpsi库的句柄(这里的句其实是指向一个数据结构的指针),一个句柄对应一个解码环境,就相当于一个工作空间,通过获取多个句柄就可以同时进行多种解码。
消息处理函数是用户编写的,由库调用,当库有消息(比如错误提示,警告)提示用户时,库将调用该函数。用户在该函数内处理消息(比如打印到屏幕上)。消息处理函数的声明可以在在线文档中找到。
句柄由dvbpsi_new(&message_cb,DVBPSI_MSG_DEBUG)函数返回:
dvbpsi_t *p_dvbpsi = dvbpsi_new(&message, DVBPSI_MSG_DEBUG);
if(p_dvbpsi==NULL)
错误处理
函数声明为:
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
1.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作为参数,从而绑定相应的子表解码器。子表解码器不需要解绑。详见“复杂表的解析”。
1.3 发送TS数据包
通过dvbpsi_packet_push()发送数据包给解码器,如果一个表处理完了,解码器将调用dvbpsi_XXX_attach绑定的回调函数。回调函数中会包含解码出的数据。如果数据中包含descriples(p_first_descriptor指针),那么需要额外再调用处理descriptors的函数(将p_descriptor作为参数传递给处理函数,处理函数会返回结果)。descriptors处理详见dr.h部分。
函数声明为:
//p_data是一个188字节数据包
//包含dvbpsi.h
bool dvbpsi_packet_push(dvbpsi_t * p_dvbpsi,uint8_t * p_data);
所有表的解析都是调用这个函数发送数据进行解析。
例如:dvbpsi_packet_push(p_dvbpsi, data);//p_dvbpsi是句柄,data是188字节的数据。读取数据的函数为ReadPacket。
当有表被解析处理后回调函数就会被执行。
注意当记录某个表的所有数据都被解析了(即表完全解析完),解码过程才会结束,并调用回调函数。比如记录EIT (table_id=0x50,servic_id=19)的表共用了20个section,只有20个section全部解析完成才行。
1.4 解除绑定的解码器
当不需要再使用该解码器时,调用dvbpsi_XXX_detach解除解码器。
例如:
dvbpsi_pat_detach(p_dvbpsi);//解除后该句柄不能再用了解码了。
包含相应表的头文件。
1.5 释放库句柄
应用程序结束,调用dvbpsi_delete()释放句柄。
voiddvbpsi_delete(dvbpsi_t * p_dvbpsi);
在此之前,需解除绑定的解码器。
包含dvbpsi.h
例如:dvbpsi_delete(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中就包含了事件名和简介
}
- libdvbpsi库的使用
- Android下libdvbpsi的使用
- libdvbpsi库简单学习心得(一):使用和编辑库
- 在android平台上如何使用libdvbpsi
- libdvbpsi的例子解析(一)
- libdvbpsi的例子解析(二)
- libdvbpsi库简单学习心得(二):PAT表
- libdvbpsi源码结构
- libdvbpsi源码分析(前言)
- libdvbpsi 源代码学习(一)
- libdvbpsi 源代码学习(二)
- 在Qt creater中编译libdvbpsi
- libevent库的使用--定时器的使用
- tinyxml库的使用
- tinyxml库的使用
- NCURSES库的使用
- iconv库的使用
- sigslot库的使用
- 【iOS开发】---- iOS7适配问题
- Android调用天气预报的WebService简单例子
- Android多线程断点下载jar包使用
- linux小记10 创建本地yum源
- 毫秒必争,前端网页性能最佳实践
- libdvbpsi库的使用
- Objective-c中线程NSThread的使用
- uva 10651- Pebble Solitaire(状态压缩DP)待看。。。
- 逆向并查集(ZOJ 3261)
- Oracle分区表,哈希分区的新建与增加
- Android开发之WebService介绍
- windows server 2012 AD 活动目录部署系列(十)操作主机角色转移
- 一些常用接口
- Android详细的对话框AlertDialog.Builder使用方法