Android多媒体框架OpenCore(PacketVideo)介绍之二:OSCL和文件编解码
第三部分 OpenCore OSCL简介
OSCL,全称为Operating System Compatibility Library (操作系统兼容库),它包含了一些在不同操作系统中移植层的功能,其代码结构如下所示:
oscl/oscl
|-- config :配置的宏
|-- makefile
|-- makefile.pv
|-- osclbase :包含基本类型、宏以及一些STL容器类似的功能
|-- osclerror :错误处理的功能
|-- osclio :文件IO和Socket等功能
|-- oscllib :动态库接口等功能
|-- osclmemory :内存管理、自动指针等功能
|-- osclproc :线程、多任务通讯等功能
|-- osclregcli :注册客户端的功能
|-- osclregserv :注册服务器的功能
`-- osclutil :字符串等基本功能
在oscl的目录中,一般每一个目录表示一个模块。OSCL对应的功能是非常细致的,几乎对C语言中每一个细节的功能都进行封装,并使用了C++的接口提供给上层使用。事实上,OperCore中的PVMF、Engine部分都在使用OSCL,而整个OperCore的调用者也需要使用OSCL。在OSCL的实现中,很多典型的C语言函数被进行了简单的封装,例如:osclutil中与数学相关的功能在oscl_math.inl中被定义成为了内嵌(inline)的函数:
OSCL_COND_EXPORT_REF OSCL_INLINE double oscl_log(double value)
{
return (double) log(value);
}
OSCL_COND_EXPORT_REF OSCL_INLINE double oscl_log10(double value)
{
return (double) log10(value);
}
OSCL_COND_EXPORT_REF OSCL_INLINE double oscl_sqrt(double value)
{
return (double) sqrt(value);
}
oscl_math.inl文件又被oscl_math.h所包含,因此其结果是oscl_log()等功能的使用等价于原始的log()等函数。很多C语言标准库的句柄都被定义成为了C++类的形式,实现有一些繁琐,但是复杂性都不是很高。以oscllib为例,其代码结构如下所示:
oscl/oscl/oscllib/
|-- Android.mk
|-- build
| `-- make
| `-- makefile
`-- src
|-- oscl_library_common.h
|-- oscl_library_list.cpp
|-- oscl_library_list.h
|-- oscl_shared_lib_interface.h
|-- oscl_shared_library.cpp
`-- oscl_shared_library.h
oscl_shared_library.h是提供给上层使用的动态库的接口功能,它定义的接口如下所示:
class OsclSharedLibrary
{
public:
OSCL_IMPORT_REF OsclSharedLibrary();
OSCL_IMPORT_REF OsclSharedLibrary(const OSCL_String& aPath);
OSCL_IMPORT_REF ~OsclSharedLibrary();
OSCL_IMPORT_REF OsclLibStatus LoadLib(const OSCL_String& aPath);
OSCL_IMPORT_REF OsclLibStatus LoadLib();
OSCL_IMPORT_REF void SetLibPath(const OSCL_String& aPath);
OSCL_IMPORT_REF OsclLibStatus QueryInterface(const OsclUuid& aInterfaceId, OsclAny*& aInterfacePtr);
OSCL_IMPORT_REF OsclLibStatus Close();
OSCL_IMPORT_REF void AddRef();
OSCL_IMPORT_REF void RemoveRef();
}
这些接口显然都是与库的加载有关系的,而在oscl_shared_library.cpp 中其具体的功能是使用dlopen()等函数来实现的。
第四部分 文件格式处理和编解码部分简介
在多媒体方面,文件格式的处理和编解码(Codec)是很基础的两个方面的内容。多媒体应用的两个方面是媒体的播放(PlayBack)和媒体的记录(Recording)。
在媒体的播放过程中,通常情况是从对媒体文件的播放,必要的两个步骤为文件的解析和媒体流的解码。例如对于一个mp4的文件,其中可能包括AMR和AAC 的音频流,H263、MPEG4以及AVC(H264)的视频流,这些流被封装在3GP的包当中,媒体播放器要做的就是从文件中将这些流解析出来,然后对媒体流进行解码,解码后的数据才可以播放。
在媒体的记录过程中,通过涉及到视频、音频、图像的捕获功能。对于将视频加音频录制成文件功能,其过程与播放刚好相反,首先从硬件设备得到视频和音频的媒体流,然后对其进行编码,编码号的流还需要被分层次写入到文件之中,最终得到组成好的文件。OpenCore有关文件格式处理和编解码部分两部分的内容,分别在目录fileformats和codecs_v2当中。这两部分都属于基础性的功能,不涉及具体的逻辑,因此它们被别的模块调用来使用,例如:构建各种Node。
4.1 文件格式的处理
由于同时涉及播放文件和记录文件两种功能,因此OpenCore中的文件格式处理有两种类型,一种是parser(解析器),另一种是composer(组成器)。
fileformats的目录结构如下所示:
fileformats
|-- avi
| `-- parser
|-- common
| `-- parser
|-- id3parcom
| |-- Android.mk
| |-- build
| |-- include
| `-- src
|-- mp3
| `-- parser
|-- mp4
| |-- composer
| `-- parser
|-- rawaac
| `-- parser
|-- rawgsmamr
| `-- parser
`-- wav
`-- parser
目录包含各个子目录中,它们对应的是不同的文件格式,例如mp3、mp4和wav等。
4.2 编解码
编解码部分主要针对Audio和Video,codecs_v2的目录结构如下所示:
codecs_v2
|-- audio
| |-- aac
| |-- gsm_amr
| |-- mp3
| `-- sbc
|-- omx
| |-- factories
| |-- omx_aac
| |-- omx_amr
| |-- omx_common
| |-- omx_h264
| |-- omx_m4v
| |-- omx_mp3
| |-- omx_proxy
| `-- omx_queue
|-- utilities
| |-- colorconvert
| |-- m4v_config_parser
| `-- pv_video_config_parser
`-- video
|-- avc_h264
`-- m4v_h263
在audio 和video目录中,对应了针对各种流的子目录,其中可能包含dec和enc两个目录,分别对应解码和编码。video目录展开后的内容如下所示:
`-- video
|-- avc_h264
| |-- common
| |-- dec
| |-- enc
| `-- patent_disclaimer.txt
`-- m4v_h263
|-- dec
|-- enc
`-- patent_disclaimer.txt
codecs_v2目录的子目录omx实现了一个khronos,OpenMAX的功能。OpenMAX是一个多媒体应用程序的框架标准,由NVIDIA公司和Khronos在2006年推出。OpenMAX IL 1.0(集成层)技术规格定义了媒体组件接口,以便在嵌入式器件的流媒体框架中快速集成加速式编解码器。OpenMAX的设计实现可以让具有硬件编解码功能的平台提供统一的接口和框架,在OpenMAX中可以直接使用硬件加速的进行编解码乃至输出的功能,对外保持统一的接口。但是在此处的OpenMAX则是一个纯软件的实现。