XBMC分析系列文章:
XBMC源代码分析
4:视频播放器(dvdplayer)-解码器(以ffmpeg为例)
XBMC源代码简析 5:视频播放器(dvdplayer)-解复用器(以ffmpeg为例)
本文我们分析XBMC中视频播放器(dvdplayer)中的文件头部分。文件头部分里包含的是封装Dll用到的头文件。由于文件头种类很多,不可能一一分析,因此还是以ffmpeg文件头为例进行分析。
XBMC中文件头部分文件目录结构如下图所示。
在这里我们看一下封装AVCodec和AVFormat结构体的头文件,分别是DllAvCodec.h和DllAvFormat.h。
DllAvFormat.h内容如下。其中包含了2个主要的类:DllAvFormatInterface和DllAvFormat。
其中DllAvFormatInterface是一个纯虚类,里面全是纯虚函数。
DllAvFormat中包含很多已经定义过的宏,稍后我们分析一下这些宏的含义。
/* * 雷霄骅 * leixiaohua1020@126.com * 中国传媒大学/数字电视技术 * */ //接口的作用 class DllAvFormatInterface { public: virtual ~DllAvFormatInterface() {} virtual void av_register_all_dont_call(void)=0; virtual void avformat_network_init_dont_call(void)=0; virtual void avformat_network_deinit_dont_call(void)=0; virtual AVInputFormat *av_find_input_format(const char *short_name)=0; virtual void avformat_close_input(AVFormatContext **s)=0; virtual int av_read_frame(AVFormatContext *s, AVPacket *pkt)=0; virtual void av_read_frame_flush(AVFormatContext *s)=0; virtual int av_read_play(AVFormatContext *s)=0; virtual int av_read_pause(AVFormatContext *s)=0; virtual int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)=0; #if (!defined USE_EXTERNAL_FFMPEG) && (!defined TARGET_DARWIN) virtual int avformat_find_stream_info_dont_call(AVFormatContext *ic, AVDictionary **options)=0; #endif virtual int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)=0; virtual AVIOContext *avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), int (*write_packet)(void *opaque, uint8_t *buf, int buf_size), offset_t (*seek)(void *opaque, offset_t offset, int whence))=0; virtual AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened)=0; virtual AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score_max)=0; virtual int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, const char *filename, void *logctx, unsigned int offset, unsigned int max_probe_size)=0; virtual void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output)=0; virtual int avio_open(AVIOContext **s, const char *filename, int flags)=0; virtual int avio_close(AVIOContext *s)=0; virtual int avio_open_dyn_buf(AVIOContext **s)=0; virtual int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)=0; virtual offset_t avio_seek(AVIOContext *s, offset_t offset, int whence)=0; virtual int avio_read(AVIOContext *s, unsigned char *buf, int size)=0; virtual void avio_w8(AVIOContext *s, int b)=0; virtual void avio_write(AVIOContext *s, const unsigned char *buf, int size)=0; virtual void avio_wb24(AVIOContext *s, unsigned int val)=0; virtual void avio_wb32(AVIOContext *s, unsigned int val)=0; virtual void avio_wb16(AVIOContext *s, unsigned int val)=0; virtual AVFormatContext *avformat_alloc_context(void)=0; virtual int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat, const char *format_name, const char *filename) = 0; virtual AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)=0; virtual AVOutputFormat *av_guess_format(const char *short_name, const char *filename, const char *mime_type)=0; virtual int avformat_write_header (AVFormatContext *s, AVDictionary **options)=0; virtual int av_write_trailer(AVFormatContext *s)=0; virtual int av_write_frame (AVFormatContext *s, AVPacket *pkt)=0; #if defined(AVFORMAT_HAS_STREAM_GET_R_FRAME_RATE) virtual AVRational av_stream_get_r_frame_rate(const AVStream *s)=0; #endif }; //封装的Dll,继承了DllDynamic,以及接口 class DllAvFormat : public DllDynamic, DllAvFormatInterface { DECLARE_DLL_WRAPPER(DllAvFormat, DLL_PATH_LIBAVFORMAT) LOAD_SYMBOLS() DEFINE_METHOD0(void, av_register_all_dont_call) DEFINE_METHOD0(void, avformat_network_init_dont_call) DEFINE_METHOD0(void, avformat_network_deinit_dont_call) DEFINE_METHOD1(AVInputFormat*, av_find_input_format, (const char *p1)) DEFINE_METHOD1(void, avformat_close_input, (AVFormatContext **p1)) DEFINE_METHOD1(int, av_read_play, (AVFormatContext *p1)) DEFINE_METHOD1(int, av_read_pause, (AVFormatContext *p1)) DEFINE_METHOD1(void, av_read_frame_flush, (AVFormatContext *p1)) DEFINE_FUNC_ALIGNED2(int, __cdecl, av_read_frame, AVFormatContext *, AVPacket *) DEFINE_FUNC_ALIGNED4(int, __cdecl, av_seek_frame, AVFormatContext*, int, int64_t, int) DEFINE_FUNC_ALIGNED2(int, __cdecl, avformat_find_stream_info_dont_call, AVFormatContext*, AVDictionary **) DEFINE_FUNC_ALIGNED4(int, __cdecl, avformat_open_input, AVFormatContext **, const char *, AVInputFormat *, AVDictionary **) DEFINE_FUNC_ALIGNED2(AVInputFormat*, __cdecl, av_probe_input_format, AVProbeData*, int) DEFINE_FUNC_ALIGNED3(AVInputFormat*, __cdecl, av_probe_input_format2, AVProbeData*, int, int*) DEFINE_FUNC_ALIGNED6(int, __cdecl, av_probe_input_buffer, AVIOContext *, AVInputFormat **, const char *, void *, unsigned int, unsigned int) DEFINE_FUNC_ALIGNED3(int, __cdecl, avio_read, AVIOContext*, unsigned char *, int) DEFINE_FUNC_ALIGNED2(void, __cdecl, avio_w8, AVIOContext*, int) DEFINE_FUNC_ALIGNED3(void, __cdecl, avio_write, AVIOContext*, const unsigned char *, int) DEFINE_FUNC_ALIGNED2(void, __cdecl, avio_wb24, AVIOContext*, unsigned int) DEFINE_FUNC_ALIGNED2(void, __cdecl, avio_wb32, AVIOContext*, unsigned int) DEFINE_FUNC_ALIGNED2(void, __cdecl, avio_wb16, AVIOContext*, unsigned int) DEFINE_METHOD7(AVIOContext *, avio_alloc_context, (unsigned char *p1, int p2, int p3, void *p4, int (*p5)(void *opaque, uint8_t *buf, int buf_size), int (*p6)(void *opaque, uint8_t *buf, int buf_size), offset_t (*p7)(void *opaque, offset_t offset, int whence))) DEFINE_METHOD4(void, av_dump_format, (AVFormatContext *p1, int p2, const char *p3, int p4)) DEFINE_METHOD3(int, avio_open, (AVIOContext **p1, const char *p2, int p3)) DEFINE_METHOD1(int, avio_close, (AVIOContext *p1)) DEFINE_METHOD1(int, avio_open_dyn_buf, (AVIOContext **p1)) DEFINE_METHOD2(int, avio_close_dyn_buf, (AVIOContext *p1, uint8_t **p2)) DEFINE_METHOD3(offset_t, avio_seek, (AVIOContext *p1, offset_t p2, int p3)) DEFINE_METHOD0(AVFormatContext *, avformat_alloc_context) DEFINE_METHOD4(int, avformat_alloc_output_context2, (AVFormatContext **p1, AVOutputFormat *p2, const char *p3, const char *p4)) DEFINE_METHOD2(AVStream *, avformat_new_stream, (AVFormatContext *p1, AVCodec *p2)) DEFINE_METHOD3(AVOutputFormat *, av_guess_format, (const char *p1, const char *p2, const char *p3)) DEFINE_METHOD2(int, avformat_write_header , (AVFormatContext *p1, AVDictionary **p2)) DEFINE_METHOD1(int, av_write_trailer, (AVFormatContext *p1)) DEFINE_METHOD2(int, av_write_frame , (AVFormatContext *p1, AVPacket *p2)) #if defined(AVFORMAT_HAS_STREAM_GET_R_FRAME_RATE) DEFINE_METHOD1(AVRational, av_stream_get_r_frame_rate, (const AVStream *p1)) #endif BEGIN_METHOD_RESOLVE() RESOLVE_METHOD_RENAME(av_register_all, av_register_all_dont_call) RESOLVE_METHOD_RENAME(avformat_network_init, avformat_network_init_dont_call) RESOLVE_METHOD_RENAME(avformat_network_deinit, avformat_network_deinit_dont_call) RESOLVE_METHOD(av_find_input_format) RESOLVE_METHOD(avformat_close_input) RESOLVE_METHOD(av_read_frame) RESOLVE_METHOD(av_read_play) RESOLVE_METHOD(av_read_pause) RESOLVE_METHOD(av_read_frame_flush) RESOLVE_METHOD(av_seek_frame) RESOLVE_METHOD_RENAME(avformat_find_stream_info, avformat_find_stream_info_dont_call) RESOLVE_METHOD(avformat_open_input) RESOLVE_METHOD(avio_alloc_context) RESOLVE_METHOD(av_probe_input_format) RESOLVE_METHOD(av_probe_input_format2) RESOLVE_METHOD(av_probe_input_buffer) RESOLVE_METHOD(av_dump_format) RESOLVE_METHOD(avio_open) RESOLVE_METHOD(avio_close) RESOLVE_METHOD(avio_open_dyn_buf) RESOLVE_METHOD(avio_close_dyn_buf) RESOLVE_METHOD(avio_seek) RESOLVE_METHOD(avio_read) RESOLVE_METHOD(avio_w8) RESOLVE_METHOD(avio_write) RESOLVE_METHOD(avio_wb24) RESOLVE_METHOD(avio_wb32) RESOLVE_METHOD(avio_wb16) RESOLVE_METHOD(avformat_alloc_context) RESOLVE_METHOD(avformat_alloc_output_context2) RESOLVE_METHOD(avformat_new_stream) RESOLVE_METHOD(av_guess_format) RESOLVE_METHOD(avformat_write_header) RESOLVE_METHOD(av_write_trailer) RESOLVE_METHOD(av_write_frame) #if defined(AVFORMAT_HAS_STREAM_GET_R_FRAME_RATE) RESOLVE_METHOD(av_stream_get_r_frame_rate) #endif END_METHOD_RESOLVE() /* dependencies of libavformat */ DllAvCodec m_dllAvCodec; // DllAvUtil loaded implicitely by m_dllAvCodec public: void av_register_all() { CSingleLock lock(DllAvCodec::m_critSection); av_register_all_dont_call(); } int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { CSingleLock lock(DllAvCodec::m_critSection); return avformat_find_stream_info_dont_call(ic, options); } virtual bool Load() { if (!m_dllAvCodec.Load()) return false; bool loaded = DllDynamic::Load(); CSingleLock lock(DllAvCodec::m_critSection); if (++m_avformat_refcnt == 1 && loaded) avformat_network_init_dont_call(); return loaded; } virtual void Unload() { CSingleLock lock(DllAvCodec::m_critSection); if (--m_avformat_refcnt == 0 && DllDynamic::IsLoaded()) avformat_network_deinit_dont_call(); DllDynamic::Unload(); } protected: static int m_avformat_refcnt; }; #endif
这些宏的含义如下:
DEFINE_METHOD0(result, name) 定义一个方法(不包含参数) DEFINE_METHOD1(result, name, args) 定义一个方法(1个参数) DEFINE_METHOD2(result, name, args) 定义一个方法(2个参数) DEFINE_METHOD3(result, name, args) 定义一个方法(3个参数) DEFINE_METHOD4(result, name, args) 定义一个方法(4个参数) 以此类推... DEFINE_FUNC_ALIGNED0(result, linkage, name) 定义一个方法(不包含参数) DEFINE_FUNC_ALIGNED1(result, linkage, name, t1) 定义一个方法(1个参数) DEFINE_FUNC_ALIGNED2(result, linkage, name, t1, t2) 定义一个方法(2个参数) 以此类推...
可以看一下这些宏的定义。看了一会,感觉宏的定义太多了,好乱。在这里仅举一个例子:RESOLVE_METHOD
#define RESOLVE_METHOD(method) \ if (!m_dll->ResolveExport( #method , & m_##method##_ptr )) \ return false;
从定义中可以看出,调用了m_dll的方法ResolveExport()。但是在DllAvFormat中并没有m_dll变量。实际上m_dll位于DllAvFormat的父类DllDynamic里面。
DllAvFormat继承了DllDynamic。DllDynamic是用于加载Dll的类。我们可以看一下它的定义:
//Dll动态加载类 class DllDynamic { public: DllDynamic(); DllDynamic(const CStdString& strDllName); virtual ~DllDynamic(); virtual bool Load();//加载 virtual void Unload();//卸载 virtual bool IsLoaded() const { return m_dll!=NULL; }//是否加载 bool CanLoad(); bool EnableDelayedUnload(bool bOnOff); bool SetFile(const CStdString& strDllName);//设置文件 const CStdString &GetFile() const { return m_strDllName; } protected: virtual bool ResolveExports()=0; virtual bool LoadSymbols() { return false; } bool m_DelayUnload; LibraryLoader* m_dll; CStdString m_strDllName; };
其中有一个变量LibraryLoader* m_dll。是用于加载Dll的。
可以看一DllDynamic中主要的几个函数,就能明白这个类的作用了。
//加载 bool DllDynamic::Load() { if (m_dll) return true; if (!(m_dll=CSectionLoader::LoadDLL(m_strDllName, m_DelayUnload, LoadSymbols()))) return false; if (!ResolveExports()) { CLog::Log(LOGERROR, "Unable to resolve exports from dll %s", m_strDllName.c_str()); Unload(); return false; } return true; }
//卸载 void DllDynamic::Unload() { if(m_dll) CSectionLoader::UnloadDLL(m_strDllName); m_dll=NULL; }
可以看看LibraryLoader的定义。LibraryLoader本身是一个纯虚类,具体方法的实现在其子类里面。
//Dll加载类 class LibraryLoader { public: LibraryLoader(const char* libraryFile); virtual ~LibraryLoader(); virtual bool Load() = 0; virtual void Unload() = 0; virtual int ResolveExport(const char* symbol, void** ptr, bool logging = true) = 0; virtual int ResolveOrdinal(unsigned long ordinal, void** ptr); virtual bool IsSystemDll() = 0; virtual HMODULE GetHModule() = 0; virtual bool HasSymbols() = 0; char* GetName(); // eg "mplayer.dll" char* GetFileName(); // "special://xbmcbin/system/mplayer/players/mplayer.dll" char* GetPath(); // "special://xbmcbin/system/mplayer/players/" int IncrRef(); int DecrRef(); int GetRef(); private: LibraryLoader(const LibraryLoader&); LibraryLoader& operator=(const LibraryLoader&); char* m_sFileName; char* m_sPath; int m_iRefCount; };
LibraryLoader的继承关系如下图所示。
由于自己的操作系统是Windows下的,因此可以看看Win32DllLoader的定义。
//Windows下的Dll加载类 class Win32DllLoader : public LibraryLoader { public: class Import { public: void *table; DWORD function; }; Win32DllLoader(const char *dll); ~Win32DllLoader(); virtual bool Load();//加载 virtual void Unload();//卸载 virtual int ResolveExport(const char* symbol, void** ptr, bool logging = true); virtual bool IsSystemDll(); virtual HMODULE GetHModule(); virtual bool HasSymbols(); private: void OverrideImports(const CStdString &dll); void RestoreImports(); static bool ResolveImport(const char *dllName, const char *functionName, void **fixup); static bool ResolveOrdinal(const char *dllName, unsigned long ordinal, void **fixup); bool NeedsHooking(const char *dllName); HMODULE m_dllHandle; bool bIsSystemDll; std::vector<Import> m_overriddenImports; std::vector<HMODULE> m_referencedDlls; };
其中加载Dll使用Load(),卸载Dll使用Unload()。可以看看这两个函数具体的代码。
//加载 bool Win32DllLoader::Load() { if (m_dllHandle != NULL) return true; //文件路径 CStdString strFileName = GetFileName(); CStdStringW strDllW; g_charsetConverter.utf8ToW(CSpecialProtocol::TranslatePath(strFileName), strDllW, false, false, false); //加载库 m_dllHandle = LoadLibraryExW(strDllW.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (!m_dllHandle) { LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, 0, (LPTSTR) &lpMsgBuf, 0, NULL ); CLog::Log(LOGERROR, "%s: Failed to load %s with error %d:%s", __FUNCTION__, CSpecialProtocol::TranslatePath(strFileName).c_str(), dw, lpMsgBuf); LocalFree(lpMsgBuf); return false; } // handle functions that the dll imports if (NeedsHooking(strFileName.c_str())) OverrideImports(strFileName); else bIsSystemDll = true; return true; } //卸载 void Win32DllLoader::Unload() { // restore our imports RestoreImports(); //卸载库 if (m_dllHandle) { if (!FreeLibrary(m_dllHandle)) CLog::Log(LOGERROR, "%s Unable to unload %s", __FUNCTION__, GetName()); } m_dllHandle = NULL; }
XBMC源代码分析 6:视频播放器(dvdplayer)-文件头(以ffmpeg为例)的更多相关文章
-
XBMC源代码分析 7:视频播放器(dvdplayer)-输入流(以libRTMP为例)
前文分析了XBMC的基本结构: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分 ...
-
XBMC源代码分析 4:视频播放器(dvdplayer)-解码器(以ffmpeg为例)
XBMC分析系列文章: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 本文我们分析XBMC中视 ...
-
转:XBMC源代码分析
1:整体结构以及编译方法 XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0 ...
-
XBMC源代码分析 3:核心部分(core)-综述
前文分析了XBMC的整体结构以及皮肤部分: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) 本文以及以后的文章主要分析XBMC的VC工程中的源代码. ...
-
XBMC源代码分析 2:Addons(皮肤Skin)
前文已经对XBMC源代码的整体架构进行了分析: XBMC源代码分析 1:整体结构以及编译方法 从这篇文章开始,就要对XBMC源代码进行具体分析了.首先先不分析其C++代码,分析一下和其皮肤相关的代码. ...
-
XBMC源代码分析 1:整体结构以及编译方法
XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0系统.我自己下载了一个然后 ...
-
从源代码分析modelDriven拦截器和params拦截器和拦截器prepare 和paramsPrepareParamsStack拦截器栈(让你的Struts2代码更简洁——如何培养框架设计能力
源代码文件:Web App Libraries/struts2-core-2.3.15.3.jar/struts-default.xml 拦截器modelDriven: <interceptor ...
-
XBMC源代码简析 5:视频播放器(dvdplayer)-解复用器(以ffmpeg为例)
XBMC分析系列文章: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分析 4: ...
-
FFmpeg的HEVC解码器源代码简单分析:解析器(Parser)部分
===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...
随机推荐
-
ORACLE 各种连接
数据说明: select * from dave;ID NAME 安庆 dave bl bl dave dba sf-express dmm select * from b1;ID NAME dave ...
-
Nodejs中Async模块的流程控制方法
首先,使用Asycn模块需要安装,它不是node自带的.其次,该模块有大约20多个流程控制方法,我们在这里仅分析常用的series, parallel, waterfall, auto这四种,并且尽量 ...
-
XCode6无论如何都无法升级为XCode8为什么呀?
因为开发微信支付需要IOS9.0版本,但是本来的XCode是6.0版本,所以最高的是8.3版本,所以要进行升级更新,但是打开更新中心发现没有更新提示,所以到AppStore里面进行下载,因为本机已经安 ...
-
docker中如何制作自己的基础镜像
一.本地镜像 举个例子:现在把自己的开发环境打包,取名为centos6-base.tar,然后在docker中,以centos6-base.tar作为基准镜像. 1.创建自己的镜像,放置于/root目 ...
-
TCP长连接与短连接
1.概念区别 所谓TCP短连接,是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接.也就是说TCP连接维持的时间比较短.一般银行网页数据交互都使用短连接.再比如说htt ...
-
USB硬件远程共享解决iphone已停用
悲剧的在iphone拆过电池之后,再开机显示iphone已停用,请在23000000分钟后再试一次 算算这得45年了,可以留给孙子用了... 网上除了刷机和有同步过的电脑貌似没有别的办法了 因是旧系统 ...
-
字符串匹配算法-BM
在用于查找子字符串的算法中,BM(Boyer-Moore)算法是当前有效且应用比较广泛的一种算法,各种文本编辑器的“查找”功能(Ctrl+F),大多采用Boyer-Moore算法.比我们学习的KMP算 ...
-
zend framework 配置连接数据库
Zend_Db_Adapter是zend frmaeword的数据库抽象层api.基于pdo, 你可以使用Zend_Db_Adapter连接和处理多种 数据库,包括:microsoft SQL ...
-
CSS实现无外边框列表效果
方法一:使用外层容器切割 给每一个 li 设定右边框和下边框线 把ul放置在一个外层div中,设定div的宽高,通过overflow:hidden将一部分li的边框隐藏 此方法只需要计算父容器的宽高, ...
-
Linux安装配置JDK1.7
1 在/usr/local 文件夹下新建一个文件夹software ,将JDK放到此文件夹中 并在此文件夹下解压执行命令 tar zxvf jdk-8u144-linux-x64.tar. ...