VLC-2.2.8 Windows/Ubuntu18.04交叉编译


libvlc使用起来还是很方便的,但要是自己编译就相当恶心了。最近任务需要,要重新编译Windows-32位版本,并修改MP4和AVI的部分实现加密视频的正常播放。
网上流行的编译版本为vlc-2.2.1和vlc-2.2.4,但真正编译的时候坑很多。为了方便以后要编译的人,现分享编译方法。

一:环境搭建

  • Ubuntu18.04LTS-x64 (VMWare虚拟机)
  • VLC:vlc-2.2.8,vlc-contrib-i686-w64-mingw32-20160218.tar.bz2
  • 目标平台:Windows_Win32(交叉编译)

二:编译

2.1 编译环境

安装VMware虚拟机和Ubuntu18.04_x64。
确保虚拟机联网。

2.2 编译工具链和依赖库

sudo apt-get update
sudo apt-get install gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-tools
sudo apt-get install lua5.2 libtool automake autoconf autopoint make gettext pkg-config
sudo apt-get install qt4-dev-tools qt5-default git subversion cmake cvs
sudo apt-get install wine64-development-tools libwine-dev zip p7zip nsis bzip2
sudo apt-get install yasm ragel ant default-jdk protobuf-compiler dos2unix

运气好的话应该不会报错。(报错的话断网重连下试试)

2.3 第三方依赖库

VLC依赖第三方依赖库编码,为了方便官方已经将第三方依赖库提前编译好了。但有十分重要的问题需要注意:

  • 第三方依赖库放在:http://download.videolan.org/pub/videolan/contrib/i686-w64-mingw32/;
  • make prebuilt下载的是最新的第三方依赖库!例如当前VLC开发的最新版本是2.2.6,那么 make prebuilt 下载下来的 vlc-contrib-i686-w64-mingw32-latest.tar.bz2 是针对2.2.6版本的第三方依赖库;而假如要编译的是2.2.1,那么make prebuilt下载下来的依赖库很有可能不匹配。而具体哪个版本对应哪个第三方依赖库,目前没有找到说明文档,如果有这方面说明还请告知;
  • 建议的方式是:从http://download.videolan.org/pub/videolan/contrib/i686-w64-mingw32/下载对应的第三方依赖库,而不是使用 make prebuilt 自动下载。如果版本不匹配那么编译的时候肯定会报 ...has different size 的错误。
  • vlc-2.2.8 对应的第三方依赖库为:vlc-contrib-i686-w64-mingw32-20160218.tar.bz2

依次执行以下步骤:

// 下载 vlc-2.2.8
// 解压到 $HOME/Projects/

cd vlc-2.2.8/contrib/
mkdir win32

// 下载 vlc-contrib-i686-w64-mingw32-20160218.tar.bz2
// 拷贝到 win32并重命名为 "vlc-contrib-i686-w64-mingw32-latest.tar.bz2"

cd win32/
../bootstrap --host=i686-w64-mingw32
make prebuilt

rm -f ../i686-w64-mingw32/bin/moc ../i686-w64-mingw32/bin/uic ../i686-w64-mingw32/bin/rcc

2.4 VLC编译

// 回到vlc主目录,此步执行:
cd ../../

./bootstrap

// 新建编译输出目录
mkdir win32
cd win32/

// 配置环境变量
export PKG_CONFIG_LIBDIR=$HOME/Projects/vlc-2.2.8/contrib/i686-w64-mingw32/lib/pkgconfig

// 配置编译脚本
../extras/package/win32/configure.sh --host=i686-w64-mingw32 --build=x86_64-pc-linux-gnu

配置编译脚本很容易出问题,比如 configure: error: libavcodec versions 55 and later are not supported yet ,这就是因为第三方库太新,下载的第三方库和vlc版本不匹配问题(详见2.3)。
配置编译脚本成功后继续执行:

make

make报错有:

错误1:
`duplicate section xxx has different size`
这个错误还是因为第三方库不匹配,详见2.3。

错误2:
demux/mkv/.libs/libmkv_plugin_la-matroska_segment.o: In function `ZN18matroska_segment_c15ParseSimpleTagsEPN11libmatroska12KaxTagSimpleEi':
/home/nibiru/Projects/vlc-2.2.8/win32/modules/../../extras/package/win32/../../../modules/demux/mkv/matroska_segment.cpp:322: undefined reference to `libebml::EbmlString::operator std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&() const'`
...
...

错误1由于第三方库版本不匹配,详见2.3.
分析错误2: 错误2应该是string类型的强制转换出问题了。打开 modules/demux/mkv/matroska_segment.cpp ,找到错误代码:

...
else if(  MKV_IS_ID( el, KaxTagLangue ) )
{
	KaxTagLangue &language = *(KaxTagLangue*) el;
	language.ReadData( es.I_O(), SCOPE_ALL_DATA );
	p_simple->psz_lang = strdup( string( language ).c_str());
}

很显然,KaxTagLangue 强制转换成string时候出错了,即 KaxTagLangue 没有实现string输出,或者实现的有问题。使用SourceInsight分析vlc-2.2.8源码,并没有查找到 KaxTagLangue 的定义。因为 KaxTagLangue 引自第三方库,根据错误提示 libebml::EbmlString 推测它应该由 libebml 第三方库定义。继续分析 vlc-2.2.8/contrib/i686-w64-mingw32/include/ 第三方库头文件所在目录,在ebml和matroska文件夹继续查找 KaxTagLangue

// matroska/KaxSemantic.h
DECLARE_MKX_STRING(KaxTagLangue)
    
// matroska/KaxDefines.h
#define DECLARE_MKX_STRING(x)     DECLARE_MKX_CONTEXT(x) \
  class MATROSKA_DLL_API x : public EbmlString { \
    public: x(EBML_EXTRA_PARAM); \
    x(const x & ElementToClone) :EbmlString(ElementToClone) {} \
    EBML_CONCRETE_CLASS(x)

// ebml/EmblString.h
/*!
    \class EbmlString
    \brief Handle all operations on a printable string EBML element
*/
class EBML_DLL_API EbmlString : public EbmlElement {
  public:
    EbmlString();
    EbmlString(const std::string & aDefaultValue);
    EbmlString(const EbmlString & ElementToClone);

    virtual ~EbmlString() {}

    virtual bool ValidateSize() const {return IsFiniteSize() && GetSize() < 0x7FFFFFFF;} // any size is possible
    filepos_t RenderData(IOCallback & output, bool bForceRender, bool bWithDefault = false);
    filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA);
    filepos_t UpdateSize(bool bWithDefault = false, bool bForceRender = false);

    EbmlString & operator=(const std::string &);
    operator const std::string &() const;

    EbmlString &SetValue(std::string const &NewValue);
    std::string GetValue() const;

    void SetDefaultValue(std::string &);

    const std::string & DefaultVal() const;

    bool IsDefaultValue() const {
      return (DefaultISset() && Value == DefaultValue);
    }

#if defined(EBML_STRICT_API)
    private:
#else
    protected:
#endif
    std::string Value;  /// The actual value of the element
    std::string DefaultValue;
};

可见,KaxXXX类型强制转换string的依据是:operator const std::string &() const; 。但由于此重载不起作用,因此可以考虑在应用的时候使用 std::string GetValue() const; 将string重载替换掉,这样是没有问题的,查询 libebml 源码:

// EbmlString.cpp

EbmlString::operator const std::string &() const {return Value;}

std::string EbmlString::GetValue() const {
  return Value;
}

问题2原因找到并且有了解决方法,类似的报错还有几个,将报错的string强制转换全部替换成 GetValue 方式(注意函数调用里的强制转换),继续编译。

make

快完成时报错:

/qt4.cpp:36:
./ui/open.h:14:10: fatal error: QtWidgets/QAction: No such file or directory
 #include <QtWidgets/QAction>

显然,这是编译Qt-UI界面时候出现了错误,解决方法有两个:

  • 修改编译器脚本 ../extras/package/win32/configure.sh ,将 --enable-qt--enable-skins2 改为 --disable-qt--disable-skin2;
  • 安装qt环境,继续编译。

这里选择方案1。
继续编译:

make

大功告成!
生成库:

make package-win-common

三:库测试

将生成的库拷贝到Windows下,写程序测试是否正常可用。
之后基于源码做一些定制修改,继续编译测试的死循环。。。

参考:

Win32Compile - VideoLAN
http://download.videolan.org/pub/videolan/contrib/i686-w64-mingw32/
http://download.videolan.org/pub/videolan/vlc/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页