锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / Darwin服务器 / Darwin概念之QTSS运行时环境、QTSS流、服务和命名规则
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

一、QTSS模块的运行时环境


QTSS模块可以创建线程,使用互斥锁,并且可以完全自由地使用任何操作系统工具。

QuickTime流媒体服务器是完全多线程的,因此QTSS模块必须做好被别的线程抢入的准备。全局的数据结构以及代码中的关键部分应该用互斥锁进行保护。除非有特别的说明,否则我们只能假定线程的抢入是随时可能发生的。

服务器通常在很少的几个线程,或者可能是某个单一的线程上进行所有的活动,这就要求服务器尽可能使用异步I/O(服务器实际的行为取决于具体的平台和管理员配置服务器的方法)。

QTSS模块应该遵循下面的规则:

  • 尽可能快地执行任务,并将控制权返回给服务器。快速地返回使得服务器可以在大量的客户端之间进行负载均衡。
  • 在执行流I/O的时候,需要做好处理QTSS_WouldBlock错误的准备。如果发出的I/O请求被阻塞,则QTSS_Write,QTSS_WriteV,和QTSS_Read c这些回调函数就返回QTSS_WouldBlock。
  • 尽可能避免使用同步I/O。一个I/O操作被阻塞,可能会影响其它客户的流的品质。

服务器时间

QuickTime流媒体服务器处理的是媒体的实时分发,因此QTSS模块编程接口的很多元素是时间值。

服务器的内部时钟计数从1970年1月1日0点以来经过的毫秒数。QTSS_TimeVal这个数据类型就是用于存储服务器内部时钟的值。为了使时间值更加容易使用,每个处理时间的属性,参数,和回调函数都显示指定时间单位。举例来说,qtssRTPStrBufferDelayInSecs属性指定的是客户端缓冲区大小对应的秒数。如果没有特别的说明,所有的时间值代表的是服务器内部时钟的毫秒数,都使用QTSS_TimeVal这个数据类型来表示。

如果要获得服务器时钟的当前值,可以调用QTSS_Milliseconds函数,或者获取服务器对象(QTSS_ServerObject)的qtssSvrCurrentTimeMilliseconds属性值。调用QTSS_MilliSecsTo1970Secs函数可以把从服务器时钟上得到的时间转换为当前时间。


二、QTSS流


QTSS编程接口中提供了一些QTSS流引用,作为一般化的流抽象。流可以用于读取或者写入很多类型的I/O资源,包括(但不限于)文件,错误日志,以及通过RTSP或者RTP进行通讯的套接口。举例来说,模块的所有RTSP角色都会接收到一个带有qtssRTSPReqStreamRef属性的QTSS_RTSPRequestObject对象类型。该属性值的类型为QTSS_StreamRef,可以用于将RTSP相应数据发送给客户。

如果没有特殊的说明,所有的流都是异步的。在使用异步的QTSS文件系统回调函数时,模块应该做好接收QTSS_WouldBlock结果码的准备,遵守本部分描述的各种类型的流的限制和规则。在需要阻塞当前线程才能完成被请求的操作时,流的回调函数就会返回QTSS_WouldBlock错误。举例来说,如果某个套接口当前受到流量控制的约束,则对该套接口进行操作的QTSS_Write函数就会返回QTSS_WouldBlock。

当模块接收到QTSS_WouldBlock返回码时,应该调用QTSS_RequestEvent回调函数,请求服务器在指定的流可以进行I/O的时候发出通知。调用QTSS_RequestEvent函数之后,模块应该马上将控制权返回给服务器。这样当指定的流可以进行I/O时,服务器将会以完全相同的状态再次调用模块的同一角色。

所有流引用的类型都是QTSS_StreamRef。QTSS编程接口使用下面这些流类型:

QTSS_ErrorLogStream

用于将二进制数据写入到服务器的错误日志中。服务器进程中只有一个这种流类型的实例,被作为参数传递给模块的初始化角色。在数据写入到这个流的时候,注册了Error Log角色的模块将会被调用。所有对于这种流类型的操作都是同步的。

QTSS_FileStream

代表一个文件,可以通过调用QTSS_OpenFileStream函数得到。如果打开文件流的时候使用了qtssFileStreamAsync标志,则调用者在调用QTSS_Read,QTSS_Write,和QTSS_WriteV函数时应该考虑处理QTSS_WouldBlock返回码。

QTSS_RTSPSessionStream

用来从RTSP客户端读取数据(QTSS_Read),或者将数据写入到RTSP客户端(QTSS_Write或者QTSS_WriteV)。服务器可能会处于流量控制状态,因此模块在读写这种流类型的时候应该做好处理QTSS_WouldBlock返回码的准备。调用QTSS_Read函数表示您要读取客户端发送给服务器端的请求体。这个流引用是QTSS_RTSPSessionObject对象的一个属性。

QTSS_RTSPRequestStream

用来从RTSP客户端读取数据(QTSS_Read),或者将数据写入到RTSP客户端(QTSS_Write或者QTSS_WriteV)。写入到这种流类型的数据会在内存中缓存,直到整个RTSP响应全部构造完成。除此之外,这种流和QTSS_RTSPSessionStream流是完全一样的。由于数据在内部进行缓存,在向这种流类型写入数据时,模块不会收到QTSS_WouldBlock错误。调用QTSS_Read函数对这种流进行操作表示您要读取客户端发送给服务器端的请求体。

模块在调用QTSS_Read函数读取这种类型的流时,应该做好处理QTSS_WouldBlock返回码的准备。这个流引用是QTSS_RTSPRequestObject对象的一个属性。

QTSS_RTPStreamStream

用于将数据写入到RTP客户端。在向这种类型的流写数据时,一个写调用对应一个完整的RTP数据包,包括报头。目前不可能用QTSS_RequestEvent回调函数来接收这种流的事件,因此如果QTSS_Write或者QTSS_WriteV函数返回QTSS_WouldBlock,则模块必须周期性地检测阻塞状态是否被消除。这种流引用是QTSS_RTPStreamObject对象的一个属性。

QTSS_SocketStream

表示一个套接口。这种流类型允许模块使用QTSS流事件机制(QTSS_RequestEvent)来进行raw套接口I/O(事实上,QTSS_RequestEvent回调是唯一一个可用于这种流类型的流回调函数)。模块应该异步地读取套接口,而且应该使用操作系统的套接口函数来读写套接口。当那些例程处于阻塞状态时,模块可以通过QTSS_RequestEvent函数来获得阻塞状态被清除的通知。

表1-24用“X”来概括与I/O相关的回调函数是否适用于各种类型的流。

表1-24 流及其适用的回调例程
流类型 Read Seek Flush Advise Write WriteV RequestEvent SignalStream
File Stream(文件流) X X   X     X X
Error Log(错误日志流)         X      
Socket Stream(套接口流)             X  
RTSP Session Stream会话流 X   X   X X X  
RTSP Request Stream请求流 X   X   X X X  
RTP Stream RTP流 X   X   X X    

三、QTSS服务


QTSS服务是一些可以由模块访问的服务,可以是服务器提供的内建服务,或者其它模块提供的、并在后来添加的服务。服务的一个实例就是一个日志模块,允许其它模块将信息写入到错误日志中。

模块使用“服务回调例程”部分描述的回调例程来注册和调用服务。模块添加和寻找服务的方式和添加及寻找对象属性的方式类似。

每个服务都有一个名字。调用模块必须知道服务的名称,并将它转化为一个ID,才能调用服务。

每个服务都有自己特定的参数块格式。输出服务的模块应该将其输出的服务进行认真的文档说明。调用服务的模块则应该在服务不可用或者返回错误时优雅地进行错误处理。

实现某种服务的模块需要在Register角色中调用QTSS_AddService函数来将服务添加到服务器内部的服务数据库中,代码如下所示:

void MyAddService()
{
    QTSS_Error theErr = QTSS_AddService("MyService", &MyServiceFunction);
}

这里的MyServiceFunction 对应于一个函数名称,必须在同一模块中加以实现。下面是MyServiceFunction函数的一个stub实现:

QTSS_Error MyServiceFunction(MyServiceArgs* inArgs)
{
    // Each service function must take a single void* argument
    // Implement the service here.
    // Return a QTSS_Error.
}

模块必须调用QTSS_IDForService函数,并在调用时提供服务名称作为参数,来获得服务的ID,才能使用服务。有了服务的ID,模块就可以调用QTSS_DoService函数来运行服务,如列表1-1所示。


Listing 1-1 Starting a service
void MyInvokeService()
{
    // Service functions take a single void* parameter that corresponds
    // to a parameter block specific to the service.
    MyServiceParamBlock theParamBlock;

    // Initialize service-specific parameters in the parameter block.
    theParamBlock.myArgument = xxx;
    QTSS_ServiceID theServiceID = qtssIllegalServiceID;
    // Get the service ID by providing the name of the service.
    QTSS_Error theErr = QTSS_IDForService(‘MyService’, &theServiceID);
    if (theErr != QTSS_NoErr)
        return; // The service isn’t available.

    // Run the service.
    theErr = QTSS_DoService(theServiceID, &theParamBlock);
}

内置服务

QuickTime流媒体服务器提供一些内置的服务,模块可以通过服务例程来调用这些服务。在这个版本的QTSS编程接口中,有一个内置的服务:

    #define QTSS_REREAD_PREFS_SERVICE "RereadPreferences"

调用Reread Preferences服务可以使服务器重新读取其预置信息,并调用每个模块的Reread Preferences角色--如果该模块注册了这个角色的话。

调用内置服务时,首先调用QTSS_IDForService函数来获得服务的ID,然后调用QTSS_DoService 函数运行该服务。


四、命名规则


QTSS编程接口使用一个命名规则来命名它所定义的数据类型。这个规则使用数据类型的尺寸作为名字的一部分。下面是QTSS编程接口使用的数据类型:

  • Bool16 — 16位布尔值
  • SInt64 — 有符号的64位整形数值
  • SInt32 — 有符号的32位整形数值
  • UInt16 — 无符号的16位整形数值
  • UInt32 — 无符号的32位整形数值

QTSS编程接口定义的回调函数的参数遵循下面这些命名规则:

  • 输入参数以in开头
  • 输出参数以out开头
  • 既用于输入也用于输出的参数以io开头
友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内