XBMC原始碼分析 6:視頻播放器(dvdplayer)-檔案頭(以ffmpeg為例)

來源:互聯網
上載者:User

XBMC分析系列文章:

XBMC原始碼分析 1:整體結構以及編譯方法

XBMC原始碼分析 2:Addons(皮膚Skin)

XBMC原始碼分析 3:核心部分(core)-綜述

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_dllAvCodecpublic:  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;}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.