summaryrefslogtreecommitdiff
path: root/recipes/ffmpeg.recipe
blob: ed44d5f540318daa4c9130522935715cd7d9cedc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# -*- Mode: Python -*- vi:si:et:sw=4:sts=4:ts=4:syntax=python
from cerbero.tools.libtool import LibtoolLibrary

class Recipe(recipe.Recipe):
    name = 'ffmpeg'
    version = '4.4'
    licenses = [License.LGPLv2_1Plus]
    stype = SourceType.TARBALL
    url = 'https://ffmpeg.org/releases/%(name)s-%(version)s.tar.xz'
    tarball_checksum = '06b10a183ce5371f915c6bb15b7b1fffbe046e8275099c96affc29e17645d909'
    patches = []

    btype = BuildType.MAKEFILE
    configure_tpl = './configure --prefix=%(prefix)s --libdir=%(libdir)s \
        --ar="$AR" --as="$AS" --cc="$CC" --ld="$CC" --nm="$NM" --ranlib="$RANLIB" \
        --strip="$STRIP" --windres="$RC" \
        --enable-static --enable-pic --enable-shared \
        --disable-avdevice --disable-postproc --disable-swscale \
        --disable-programs --disable-ffplay --disable-ffprobe --disable-ffmpeg \
        --disable-encoder=flac --disable-protocols --disable-devices \
        --disable-network --disable-hwaccels --disable-dxva2 --disable-vdpau \
        --disable-filters --enable-filter=yadif --disable-doc --disable-d3d11va \
        --disable-audiotoolbox --disable-videotoolbox --disable-vaapi --disable-crystalhd \
        --disable-mediacodec --disable-mediafoundation --disable-nvenc --disable-mmal --disable-omx \
        --disable-omx-rpi --disable-cuda --disable-cuvid --disable-libmfx \
        --disable-libnpp --disable-iconv --disable-jni --disable-v4l2_m2m \
        --disable-vulkan --disable-large-tests --disable-stripping \
        --enable-optimizations --disable-nonfree --disable-version3 %(options)s'

    deps = ['bzip2', 'zlib']

    files_libs = ['libavcodec', 'libavformat', 'libavutil', 'libswresample', 'libavfilter']
    files_devel = []

    def prepare(self):
        # Populate self.files_devel
        files_devel_tpl = ['lib/{}.la', 'lib/pkgconfig/{}.pc', 'include/{}']
        # ffmpeg can only build either shared or static on Windows, not both
        if self.config.target_platform == Platform.WINDOWS:
            self.library_type = LibraryType.SHARED
        else:
            files_devel_tpl += ['lib/{}.a']
        for lib in self.files_libs:
            self.files_devel += [tpl.format(lib) for tpl in files_devel_tpl]

        # Default AS is $CC, except iOS (set below)
        if Architecture.is_arm(self.config.target_arch):
            if self.config.target_platform == Platform.IOS:
                gas = self.get_env('GAS')
                if gas:
                    self.set_env('AS', gas)
                    self.set_env('ASFLAGS', self.get_env('CPPFLAGS'))
            else:
                cc = self.get_env('CC')
                if cc:
                    self.set_env('AS', cc)

        libavextraconf = ''
        # Arch-specific flags
        if self.config.target_platform == Platform.ANDROID:
            if self.config.target_arch == Architecture.X86:
              # libav internally aligns stacks, while Android doesn't
                libavextraconf += " --extra-cflags='-mstackrealign'"
            if self.config.target_arch in [Architecture.X86]:
                # Fails to link into an android app with relocation warnings
                # in the custom assembly
                # https://stackoverflow.com/questions/34691970/ffmpeg-for-android-neon-build-has-text-relocations/34697703#34697703
                # https://issuetracker.google.com/issues/37067983
                # https://trac.ffmpeg.org/ticket/4928
                libavextraconf += " --disable-asm"
        elif self.config.target_platform == Platform.IOS:
            # Some optimisations that were previously silently disabled
            # cause warnings now. Ignore them
            libavextraconf += " --extra-cflags='-Wno-ignored-optimization-argument' "
            if self.config.target_arch == Architecture.X86:
                # Fails to link in gst-libav due to text relocations in
                # custom assembly:
                # ld: illegal text-relocation to 'anon' in libavfilter.a(vf_yadif.o)
                # from '_ff_yadif_filter_line_ssse3' in libavfilter.a(vf_yadif.o)
                # for architecture i386
                libavextraconf += ' --disable-asm  '

        # On windows, being a multilib toolchain, we have to always configure
        # the cross-prefix
        if self.config.cross_compiling() or \
                self.config.target_platform == Platform.WINDOWS:
            libavextraconf += ' --enable-cross-compile'
            target_os = self.config.target_platform
            if target_os == Platform.WINDOWS:
                target_os = 'mingw32'
            elif target_os == Platform.IOS:
                target_os = 'darwin'
            target_arch = self.config.host.split('-', 1)[0]
            if target_arch == 'aarch64':
                target_arch = 'arm64'
            libavextraconf += ' --target-os=' + target_os
            libavextraconf += ' --arch=' + target_arch
            libavextraconf += ' --cross-prefix={} '\
                    .format(self.config.tools_prefix or self.config.host)

        self.configure_options += libavextraconf
        # On Windows, make fails if V=1 is passed with:
        # `couldn't commit memory for cygwin heap, Win32 error 0`
        if self.config.platform == Platform.WINDOWS:
            self.make = ['make']

    async def configure(self):
        await super(recipe.Recipe, self).configure()
        libav_path = self.build_dir
        if self.config.target_platform in [Platform.DARWIN, Platform.IOS]:
            if self.config.target_arch == Architecture.X86:
                replacements = {'HAVE_EBX_AVAILABLE=yes': 'HAVE_EBX_AVAILABLE=no',
                                'HAVE_EBX_AVAILABLE 1': 'HAVE_EBX_AVAILABLE 0',}
                shell.replace(os.path.join(libav_path, 'ffbuild', 'config.mak'), replacements)
                shell.replace(os.path.join(libav_path, 'config.h'), replacements)
        # log2 and log2f are not provided by bionic, but they are not checked
        # properly
        elif self.config.target_platform == Platform.ANDROID:
                replacements = {'HAVE_LOG2 1': 'HAVE_LOG2 0',
                                'HAVE_LOG2F 1': 'HAVE_LOG2F 0',}
                shell.replace(os.path.join(libav_path, 'config.h'), replacements)

                v = DistroVersion.get_android_api_version(self.config.target_distro_version)
                if self.config.target_arch in [Architecture.ARM, Architecture.ARMv7, Architecture.X86] and v < 21:
                        replacements = {'-D_FILE_OFFSET_BITS=64': '',}
                        shell.replace(os.path.join(libav_path, 'ffbuild', 'config.mak'), replacements)

    def post_install(self):
        LibtoolLibrary('avutil', None, None, None,
                       self.config.libdir, self.config.target_platform).save()
        LibtoolLibrary('swresample', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avutil']).save()
        LibtoolLibrary('avcodec', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['swresample', 'avutil', 'z']).save()
        LibtoolLibrary('avformat', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avcodec', 'swresample', 'avutil', 'bz2', 'z']).save()
        LibtoolLibrary('avfilter', None, None, None,
                       self.config.libdir, self.config.target_platform,
                       deps=['avformat', 'avcodec', 'swresample', 'avutil']).save()
        super().post_install()