创建一个静态包含ffmpeg

时间:2017-10-08 11:05:50

标签: c++ ffmpeg shared-libraries static-libraries

我很难尝试创建一个共享库,其中ffmpeg库作为静态库“烘焙”。

考虑以下目录架构:

include/
  my own .h files
  ext/
    ffmpeg .h files
lib/
  libav*.a archive files (softlinks to the actual .a files)
  libValkka.so (my shared library)
test/
  mytest.cpp
bin/
  (binaries appear here)

我已经走了很长的路(见Including objects to a shared library from a C++ archive (.a))并且库编译好了:( [STUFF]为简洁起见省略了)

  

/ usr / bin / c ++ -fPIC -std = c ++ 14 -pthread -Iinclude / ext -I / usr / include / libdrm -g -shared -Wl,-soname,libValkka.so -o lib / libValkka .so CMakeFiles / Valkka.dir / src / avthread.cpp.o CMakeFiles / Valkka.dir / src / opengl.cpp.o CMakeFiles / Valkka.dir / src / openglthread.cpp.o [STUFF] CMakeFiles / Valkka.dir / src / filters.cpp.o -lX11 -lGLEW -lGLU -lGL -Wl, - allow-multiple-definition -Wl,-Bsymbolic -Wl, - whole-archive -Wreorder lib / libavdevice.a lib / libavfilter.a lib / libavformat.a lib / libavcodec.a lib / libavutil.a lib / libswscale.a lib / libswresample.a -Wl, - no-whole-archive

然而,在创建可执行文件时 - 他们的源代码不使用任何ffmpeg api(只是我自己的api) - 用:

  

c ++ -std = c ++ 14 -pthread -Iinclude -Iinclude / ext -Llib test / mytest.cpp -lValkka -g -o bin / mytest

我收到了关于缺少ffmpeg依赖项的大量错误。并非所有东西都缺失,只是一些奇怪的东西:

lib/libValkka.so: undefined reference to `pa_stream_get_index'
lib/libValkka.so: undefined reference to `deflateInit_'
lib/libValkka.so: undefined reference to `pa_stream_get_state'
lib/libValkka.so: undefined reference to `lzma_stream_decoder'
lib/libValkka.so: undefined reference to `BZ2_bzDecompress'
lib/libValkka.so: undefined reference to `vaInitialize'
lib/libValkka.so: undefined reference to `pa_stream_unref'
lib/libValkka.so: undefined reference to `deflateInit2_'
lib/libValkka.so: undefined reference to `snd_pcm_close'
...
lib/libValkka.so: undefined reference to `vaGetDisplayDRM'
lib/libValkka.so: undefined reference to `vaMaxNumEntrypoints'
lib/libValkka.so: undefined reference to `uncompress'
lib/libValkka.so: undefined reference to `pa_stream_drop'
lib/libValkka.so: undefined reference to `pa_context_connect'
lib/libValkka.so: undefined reference to `FT_Get_Kerning'
lib/libValkka.so: undefined reference to `ass_free_track'
lib/libValkka.so: undefined reference to `pa_operation_unref'
lib/libValkka.so: undefined reference to `FT_Stroker_Done'
lib/libValkka.so: undefined reference to `vaTerminate'
lib/libValkka.so: undefined reference to `ass_new_track'
lib/libValkka.so: undefined reference to `jack_client_close'
...
lib/libValkka.so: undefined reference to `xcb_xfixes_query_version'
lib/libValkka.so: undefined reference to `xcb_shape_rectangles'
lib/libValkka.so: undefined reference to `pa_mainloop_free'
lib/libValkka.so: undefined reference to `snd_device_name_hint'
lib/libValkka.so: undefined reference to `vaCreateImage'
lib/libValkka.so: undefined reference to `vaBeginPicture'
lib/libValkka.so: undefined reference to `DtsSetColorSpace'
lib/libValkka.so: undefined reference to `vaDestroyConfig'
lib/libValkka.so: undefined reference to `pa_stream_writable_size'
lib/libValkka.so: undefined reference to `snd_pcm_hw_params_get_buffer_size_max'
lib/libValkka.so: undefined reference to `ass_read_file'

这非常令人沮丧,特别是当我可以看到这些名称包含在共享库中时!...

  

nm lib / libValkka.so | grep“vaBeginPicture”

给出

  

U vaBeginPicture

等。我认为这可能是关于归档.a文件的依赖顺序的问题,并且还尝试使用:

  

..... -Wl, - allow-multiple-definition -Wl,-Bsymbolic -Wl, - start-group -Wl, - whole-archive -Wreorder lib / libavdevice.a lib / libavfilter。 lib / libavformat.a lib / libavcodec.a lib / libavutil.a lib / libswscale.a lib / libswresample.a -Wl, - no-whole-archive -Wl, - end-group

但问题仍然存在。

我已经成功创建了一个共享库,它可以“烘焙”那些.a档案,即动态依赖于ffmpeg库,并且没有这样的问题。

我感到困惑。我是否误解了一些基本的东西,忘记了一些恼人的链接选项,或两者兼而有之?帮助赞赏!

2 个答案:

答案 0 :(得分:2)

您需要将您的共享库链接到ffmpeg所需的第三方/系统库:libbz2,libva,libxcb,libass,freetype2等。实际列表应该位于ffmpeg分发/构建工件中的某个位置(automake' s .pc文件)

忽略 - 一切都不是一个好主意;您的应用程序可能运行正常,但这些未解决的项目仍然存在;一旦击中它们中的任何一个就会崩溃。我的猜测是,他们中的大多数都不会被击中,因为它们是用于你可能不会使用的libavdevice,但仍然是一个坏主意。另外,检查你是否真的需要libavdevice库 - 如果你摆脱那个库,你可能会修剪一下所需库的列表。

答案 1 :(得分:0)

在创建可执行文件时,告诉链接器忽略未解析的符号可以解决问题:

  

c ++ -std = c ++ 14 -pthread -Iinclude -Iinclude / ext -Llib test / mytest.cpp -lValkka -g -o bin / mytest -Wl, - unresolved-symbols = ignore-all

生成的可执行文件也运行正常。

然而..使用这样的链接器标志让我错误的方式。也许有更好的选择?为什么首先找不到这些符号?

修改

根据Andrey的建议,我借助ffmpeg的configure脚本从ffmpeg中剥离了所有外部库。这是一个有点尴尬的过程,所以我创建了一个很好的python脚本,自动完成它。这可能有点矫枉过正,但在这里:

#!/usr/bin/python3
"""
* Creates script "run_configure.bash" that launches ffmpeg's "configure" script with correct parameters (enabling/disabling stuff)
* Run in the same directory where you have ffmpeg's configure script
"""
import subprocess
import os
import re

def features(switch, adstring="", remove=[]):
  p=subprocess.Popen(["./configure",switch],stdout=subprocess.PIPE)
  st=p.stdout.read()
  fst=""
  for s in st.split():
    ss=s.decode("utf-8")
    ok=True
    for rem in remove:
      if (ss.find(rem)!=-1):
        ok=False
    if ok: fst+=adstring+ss+" "
  return fst


def disable_external():  
  p=subprocess.Popen(["./configure","-h"],stdout=subprocess.PIPE)
  st=p.stdout.read().decode("utf-8")

  # find some text tags from the configure output:
  # i1=st.find("External library support:")
  i1=st.find("themselves, not all their features will necessarily be usable by FFmpeg.")
  i2=st.find("Toolchain options:")
  st=st[i1:i2]
  """ # debugging ..
  print(st)
  stop
  """
  p=re.compile('--(enable|disable)-(\S*)')
  switches=[]
  for sw in p.findall(st):
    if (sw[1] not in switches):
      # print(sw[1]) # debugging
      switches.append(sw[1])
  fst=""
  for sw in switches:
    fst+="--disable-"+sw+" "
  return fst

st ="./configure "
st+="--disable-everything --disable-doc --disable-gpl --disable-pthreads --enable-static --enable-shared "
st+= disable_external()
st+= features("--list-decoders",adstring="--enable-decoder=", remove=["vdpau","crystalhd","zlib"])
st+= features("--list-muxers",  adstring="--enable-muxer=")
st+= features("--list-demuxers",adstring="--enable-demuxer=")
st+= features("--list-parsers", adstring="--enable-parser=")

f=open("run_configure.bash","w")
f.write("#!/bin/bash\n")
f.write(st+"\n")
f.close()
os.system("chmod a+x run_configure.bash")
print("\nNext run ./run_configure.bash\n")

"""
For cleaning up .a and .so files, use
find -name *.a -exec ls {} \;
find -name *.so* -exec ls {} \;
"""

希望有人发现它很有用。用python3运行。