`

XBMC源代码分析 6:视频播放器(dvdplayer)-文件头(以ffmpeg为例)

    博客分类:
  • XBMC
 
阅读更多

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_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;
}



 

分享到:
评论

相关推荐

    repository.xbmc-addons-chinese-1.2.1.zip

    标题“repository.xbmc-addons-chinese-1.2.1.zip”揭示了这是一个与XBMC(Xbox Media Center)相关的软件资源包,版本号为1.2.1,并且是针对中文用户定制的。XBMC是一款开源的媒体中心软件,后来更名为Kodi,允许...

    script.bluray.com:用于访问 blu-ray.com 功能的 Kodi (XBMC) 插件

    存储库的安装应通过 Kodi System::Settings::Add-ons::Install from zip 文件完成插件的安装应通过 Kodi System::Settings::Add-ons::Get Add-Ons::All Add-Ons::Program Add-Ons::Blu-ray.com 完成支持可在: : ...

    repository.xbmc-addons-chinese-2.0.0.zip

    标题中的"repository.xbmc-addons-chinese-2.0.0.zip"是一个针对KODI媒体中心的中文插件库的压缩包,版本号为2.0.0。这个压缩包包含了多款专为中国用户设计的KODI插件,旨在提升KODI在中文环境下的用户体验和功能...

    ffmpeg-2.8.5-Jarvis-rc1.tar.gz

    7. **FFmpeg-2.8.5-Jarvis-rc1**: 压缩包内的子文件夹可能包含了FFmpeg源代码、编译脚本、配置文件以及编译好的静态或动态库文件,这些都是构建xbmc/kodi时需要的资源。 8. **安装和使用**: 在Linux环境下,可以...

    ru:seppius-xbmc-repo(叉子)

    【标题】"ru:seppius-xbmc-repo(叉子)" 指的是一种基于XBMC或Kodi的俄罗斯开发者论坛扩展资源库的克隆版本。XBMC(Xbox Media Center)是一个开源的媒体中心软件,后来更名为Kodi,它允许用户组织和播放各种多媒体...

    xbmc-forum:XBMC论坛的源代码-Forum source code

    "xbmc-forum:XBMC论坛的源代码"这个标题表明我们讨论的是XBMC官方论坛的源代码,这意味着我们可以深入理解其背后的开发过程、社区互动机制以及论坛的构建方式。 源代码通常对开发者来说是非常宝贵的资源,因为它...

    aac-rtmp-red5

    如果你没有这个工具,可以自行编译或从源代码构建。 使用rtmpdump向Red5推送AAC流的命令通常会包括以下参数: ``` rtmpdump -r "rtmp://your-server-address/your-app/stream-name" -v -a "your-aac-stream-file....

    kodi中文插件最新2022 repository.xbmc-addons-chinese-2.0.0

    kodi中文插件最新2022 repository.xbmc-addons-chinese-2.0.0

    repository.xbmc-addons-chinese-2.0.1.zip亲测可用kodi中文插件库下载

    标题中的“repository.xbmc-addons-chinese-2.0.1.zip”是一个针对Kodi的中文插件库的压缩包,版本号为2.0.1。Kodi是一款开源的媒体中心软件,允许用户在各种设备上管理和播放多媒体内容,如视频、音乐和图片。这个...

    xbmc 移植到ANDROID 方法

    XBMC(Xbox Media Center)是一款开源媒体播放器应用,最初为Xbox游戏机开发,后来被移植到了多个操作系统上,包括Android。将XBMC移植到Android平台上需要进行一系列准备工作,包括设置Android开发环境、获取源代码...

    QtAV:基于Qt和FFmpeg(https:github.comwang-binavbuild)的跨平台多媒体框架。 高性能。 用户和开发人员友好。 支持Android,iOS,Windows应用商店和台式机。基于Qt和FFmpeg的跨平台高级音视频播放框架

    它可以帮助您以比以往更少的精力编写播放器。 QtAV已添加到FFmpeg项目页面 QtAV是根据LGPL v2.1条款获得许可的免费软件。 播放器示例已根据GPL v3许可。 如果您使用QtAV或其组成库,则必须遵守相关许可条款。 ...

    XBMC-OBD2:XBMC OBD2 插件-开源

    XBMC-OBD2 是一款基于XBMC(Xbox Media Center,现称为Kodi)平台的开源插件,专为汽车爱好者设计,它允许用户通过ELM327兼容的OBD2诊断适配器获取车辆的实时数据。下面将详细阐述这款插件的功能、工作原理以及如何...

    XBMC-Trailer-Downloader:抓取 hd-trailers.net 并下载用于 XBMC 和 Cinema Experience 脚本的预告片

    XBMC-Trailer-Downloader 抓取 hd-trailers.net 并下载用于 XBMC 和 Cinema Experience 脚本的预告片。 安装:pip install -r ... XBMC-Trailer-Downloader 可以完全静默运行,无需控制台输出或调试文件日志

    xbmc-bilibili-main.zip

    在这个xbmc-bilibili-main插件中,Python被用来编写与Bilibili API进行交互的代码,实现视频搜索、播放、评论等功能。 安装此插件的步骤一般包括以下几步: 1. 下载"xbmc-bilibili-main.zip"文件到本地。 2. 在Kodi...

    repository.kodi-chinese-addons:repository.kodi-chinese-addons xbmckodi用于中文插件的存储库

    这意味着用户将获得最新的插件和更新,开发者可以在这里找到最新的源代码以进行维护和开发。 通过这个仓库,Kodi用户可以轻松地安装和管理各种中文插件,比如: 1. **中文界面**:提供完全汉化的Kodi界面,让操作...

    ubuntu下的kodi(XBMC)编译

    标题中的“ubuntu下的kodi(XBMC)编译”指的是在Ubuntu操作系统环境下,对Kodi(以前称为XBMC,Xbox Media Center)媒体中心软件进行源代码编译的过程。Kodi是一款开源的多媒体中心应用,它能播放各种音频、视频格式...

    xbmc-12.1-Frodo-armeabi-v7a.apk

    XBMC最初为Xbox而开发,现在可以运行在Linux、OSX、Windows系统。 2003年,一些兴趣相投的程序员创建了这个项目。XBMC是一个非盈利的项目,由遍布世界各地的自愿者开发维护。超过50名软件开发人员为XBMC作出贡献,...

    kodi(xbmc)中文字幕插件

    在“repository.xbmc-addons-chinese”这个压缩包中,包含了一些为中国用户定制的Kodi插件,尤其是与中文字幕相关的插件。 安装插件的过程如下: 1. **打开Kodi**:启动你的Kodi应用程序,进入主界面。 2. **进入...

    screensaver.plugin.slideshow:适用于Kodi(XBMC)的插件幻灯片屏幕保护程序插件-插件中的图像幻灯片

    适用于Kodi(XBMC)的插件幻灯片屏幕保护程序插件-插件中的图像幻灯片 此插件允许使用图片插件作为图片幻灯片屏幕保护程序的源。 安装应该通过Kodi System :: Settings :: Add-ons :: Get Add-Ons :: All Add-Ons :...

    Ubuntu 11.04 安装后要做的20件事情.txt

    uudeview flac libmpeg3-1 mpeg3-utils mpg321 mpg123 libflac++6 ffmpeg libmp4v2-0 totem-mozilla icedax tagtool easytag id3tool lame nautilus-script-audio-convert libmad0 libjpeg-progs sudo apt-get ...

Global site tag (gtag.js) - Google Analytics