summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py')
-rwxr-xr-xchromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py462
1 files changed, 462 insertions, 0 deletions
diff --git a/chromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py b/chromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py
new file mode 100755
index 00000000000..86f1b935e27
--- /dev/null
+++ b/chromium/third_party/ffmpeg/chromium/scripts/build_ffmpeg.py
@@ -0,0 +1,462 @@
+#!/usr/bin/env python
+#
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import print_function
+
+import collections
+import functools
+import multiprocessing
+import optparse
+import os
+import platform
+import re
+import shutil
+import subprocess
+import sys
+
+
+SCRIPTS_DIR = os.path.abspath(os.path.dirname(__file__))
+FFMPEG_DIR = os.path.abspath(os.path.join(SCRIPTS_DIR, '..', '..'))
+
+
+USAGE = """Usage: %prog TARGET_OS TARGET_ARCH [options] -- [configure_args]
+
+Valid combinations are linux [ia32|x64|mipsel|arm|arm-neon]
+ linux-noasm [ia32|x64]
+ mac [ia32|x64]
+ win [ia32|x64]
+
+Platform specific build notes:
+ linux ia32/x64:
+ Script can run on a normal Ubuntu box.
+
+ linux mipsel:
+ Script can run on a normal Ubuntu box with MIPS cross-toolchain in $PATH.
+
+ linux arm/arm-neon:
+ Script must be run inside of ChromeOS chroot with BOARD=arm-generic.
+
+ mac:
+ Script must be run on OSX. Additionally, ensure the Chromium (not Apple)
+ version of clang is in the path; usually found under
+ src/third_party/llvm-build/Release+Asserts/bin
+
+ win:
+ Script must be run on Windows with VS2013 or higher under Cygwin (or MinGW,
+ but as of 1.0.11, it has serious performance issues with make which makes
+ building take hours).
+
+ Additionall, ensure you have the correct toolchain environment for building.
+ The x86 toolchain environment is required for ia32 builds and the x64 one
+ for x64 builds. This can be verified by running "cl.exe" and checking if
+ the version string ends with "for x64" or "for x86."
+
+ Building on Windows also requires some additional Cygwin packages plus a
+ wrapper script for converting Cygwin paths to DOS paths.
+ - Add these packages at install time: diffutils, yasm, make, python.
+ - Copy chromium/scripts/cygwin-wrapper to /usr/local/bin
+
+Resulting binaries will be placed in:
+ build.TARGET_ARCH.TARGET_OS/Chromium/out/
+ build.TARGET_ARCH.TARGET_OS/Chrome/out/
+ build.TARGET_ARCH.TARGET_OS/ChromiumOS/out/
+ build.TARGET_ARCH.TARGET_OS/ChromeOS/out/"""
+
+
+def PrintAndCheckCall(argv, *args, **kwargs):
+ print('Running %r' % argv)
+ subprocess.check_call(argv, *args, **kwargs)
+
+
+def DetermineHostOsAndArch():
+ if platform.system() == 'Linux':
+ host_os = 'linux'
+ elif platform.system() == 'Darwin':
+ host_os = 'mac'
+ elif platform.system() == 'Windows' or platform.system() == 'CYGWIN_NT-6.1':
+ host_os = 'win'
+ else:
+ return None
+
+ if re.match(r'i.86', platform.machine()):
+ host_arch = 'ia32'
+ elif platform.machine() == 'x86_64' or platform.machine() == 'AMD64':
+ host_arch = 'x64'
+ elif platform.machine().startswith('arm'):
+ host_arch = 'arm'
+ else:
+ return None
+
+ return (host_os, host_arch)
+
+
+def GetDsoName(target_os, dso_name, dso_version):
+ if target_os == 'linux':
+ return 'lib%s.so.%s' % (dso_name, dso_version)
+ elif target_os == 'mac':
+ return 'lib%s.%s.dylib' % (dso_name, dso_version)
+ elif target_os == 'win':
+ return '%s-%s.dll' % (dso_name, dso_version)
+ else:
+ raise ValueError('Unexpected target_os %s' % target_os)
+
+
+def RewriteFile(path, search, replace):
+ with open(path) as f:
+ contents = f.read()
+ with open(path, 'w') as f:
+ f.write(re.sub(search, replace, contents))
+
+
+def BuildFFmpeg(target_os, target_arch, host_os, host_arch, parallel_jobs,
+ config_only, config, configure_flags):
+ print('%s configure/build:' % config)
+
+ config_dir = 'build.%s.%s/%s' % (target_arch, target_os, config)
+ shutil.rmtree(config_dir, ignore_errors=True)
+ os.makedirs(os.path.join(config_dir, 'out'))
+
+ PrintAndCheckCall(
+ [os.path.join(FFMPEG_DIR, 'configure')] + configure_flags, cwd=config_dir)
+
+ if (target_os, target_arch) == ('mac', 'ia32'):
+ # Required to get Mac ia32 builds compiling with -fno-omit-frame-pointer,
+ # which is required for accurate stack traces. See http://crbug.com/115170.
+ #
+ # Without this, building without -fomit-frame-pointer on ia32 will result in
+ # the the inclusion of a number of inline assembly blocks that use too many
+ # registers for its input/output operands.
+ for name in ('config.h', 'config.asm'):
+ RewriteFile(os.path.join(config_dir, name),
+ 'HAVE_EBP_AVAILABLE 1',
+ 'HAVE_EBP_AVAILABLE 0')
+
+ if host_os == target_os and not config_only:
+ libraries = [
+ os.path.join('libavcodec', GetDsoName(target_os, 'avcodec', 55)),
+ os.path.join('libavformat', GetDsoName(target_os, 'avformat', 55)),
+ os.path.join('libavutil', GetDsoName(target_os, 'avutil', 52)),
+ ]
+ PrintAndCheckCall(
+ ['make', '-j%d' % parallel_jobs] + libraries, cwd=config_dir)
+ for lib in libraries:
+ shutil.copy(os.path.join(config_dir, lib),
+ os.path.join(config_dir, 'out'))
+ elif config_only:
+ print('Skipping build step as requested.')
+ else:
+ print('Skipping compile as host configuration differs from target.\n'
+ 'Please compare the generated config.h with the previous version.\n'
+ 'You may also patch the script to properly cross-compile.\n'
+ 'Host OS : %s\n'
+ 'Target OS : %s\n'
+ 'Host arch : %s\n'
+ 'Target arch : %s\n' % (host_os, target_os, host_arch, target_arch))
+
+ if target_arch in ('arm', 'arm-neon'):
+ RewriteFile(
+ os.path.join(config_dir, 'config.h'),
+ r'(#define HAVE_VFP_ARGS [01])',
+ r'/* \1 -- Disabled to allow softfp/hardfp selection at gyp time */')
+
+
+def main(argv):
+ parser = optparse.OptionParser(usage=USAGE)
+ parser.add_option('--config-only', action='store_true',
+ help='Skip the build step. Useful when a given platform '
+ 'is not necessary for generate_gyp.py')
+ options, args = parser.parse_args(argv)
+
+ if len(args) < 2:
+ parser.print_help()
+ return 1
+
+ target_os = args[0]
+ target_arch = args[1]
+ configure_args = args[2:]
+
+ if target_os not in ('linux', 'linux-noasm', 'win', 'win-vs2013', 'mac'):
+ parser.print_help()
+ return 1
+
+ host_tuple = DetermineHostOsAndArch()
+ if not host_tuple:
+ print('Unrecognized host OS and architecture.', file=sys.stderr)
+ return 1
+
+ host_os, host_arch = host_tuple
+ parallel_jobs = multiprocessing.cpu_count()
+
+ print('System information:\n'
+ 'Host OS : %s\n'
+ 'Target OS : %s\n'
+ 'Host arch : %s\n'
+ 'Target arch : %s\n'
+ 'Parallel jobs : %d\n' % (
+ host_os, target_os, host_arch, target_arch, parallel_jobs))
+
+ configure_flags = collections.defaultdict(list)
+
+ # Common configuration. Note: --disable-everything does not in fact disable
+ # everything, just non-library components such as decoders and demuxers.
+ configure_flags['Common'].extend([
+ '--disable-everything',
+ '--disable-all',
+ '--disable-doc',
+ '--disable-static',
+ '--enable-avcodec',
+ '--enable-avformat',
+ '--enable-avutil',
+ '--enable-fft',
+ '--enable-rdft',
+ '--enable-shared',
+
+ # Disable features.
+ '--disable-bzlib',
+ '--disable-error-resilience',
+ '--disable-iconv',
+ '--disable-lzo',
+ '--disable-network',
+ '--disable-symver',
+ '--disable-xlib',
+ '--disable-zlib',
+
+ # Disable hardware decoding options which will sometimes turn on
+ # via autodetect.
+ '--disable-dxva2',
+ '--disable-vaapi',
+ '--disable-vda',
+ '--disable-vdpau',
+
+ # Common codecs.
+ '--enable-decoder=theora,vorbis,vp8',
+ '--enable-decoder=pcm_u8,pcm_s16le,pcm_s24le,pcm_f32le',
+ '--enable-decoder=pcm_s16be,pcm_s24be,pcm_mulaw,pcm_alaw',
+ '--enable-demuxer=ogg,matroska,wav',
+ '--enable-parser=opus,vp3,vorbis,vp8',
+ ])
+
+ # --optflags doesn't append multiple entries, so set all at once.
+ if (target_os, target_arch) == ('mac', 'ia32'):
+ configure_flags['Common'].append('--optflags="-fno-omit-frame-pointer -O2"')
+ else:
+ configure_flags['Common'].append('--optflags="-O2"')
+
+ # Linux only.
+ if target_os in ('linux', 'linux-noasm'):
+ if target_arch == 'x64':
+ pass
+ elif target_arch == 'ia32':
+ configure_flags['Common'].extend([
+ '--arch=i686',
+ '--enable-yasm',
+ '--extra-cflags="-m32"',
+ '--extra-ldflags="-m32"',
+ ])
+ elif target_arch == 'arm':
+ if host_arch != 'arm':
+ configure_flags['Common'].extend([
+ # This if-statement essentially is for chroot tegra2.
+ '--enable-cross-compile',
+
+ # Location is for CrOS chroot. If you want to use this, enter chroot
+ # and copy ffmpeg to a location that is reachable.
+ '--cross-prefix=/usr/bin/armv7a-cros-linux-gnueabi-',
+ '--target-os=linux',
+ '--arch=arm',
+ ])
+
+ # TODO(ihf): ARM compile flags are tricky. The final options
+ # overriding everything live in chroot /build/*/etc/make.conf
+ # (some of them coming from src/overlays/overlay-<BOARD>/make.conf).
+ # We try to follow these here closely. In particular we need to
+ # set ffmpeg internal #defines to conform to make.conf.
+ # TODO(ihf): For now it is not clear if thumb or arm settings would be
+ # faster. I ran experiments in other contexts and performance seemed
+ # to be close and compiler version dependent. In practice thumb builds are
+ # much smaller than optimized arm builds, hence we go with the global
+ # CrOS settings.
+ configure_flags['Common'].extend([
+ '--enable-armv6',
+ '--enable-armv6t2',
+ '--enable-vfp',
+ '--enable-thumb',
+ '--disable-neon',
+ '--extra-cflags=-march=armv7-a',
+ '--extra-cflags=-mtune=cortex-a8',
+ '--extra-cflags=-mfpu=vfpv3-d16',
+ # NOTE: softfp/hardfp selected at gyp time.
+ '--extra-cflags=-mfloat-abi=hard',
+ ])
+ elif target_arch == 'arm-neon':
+ if host_arch != 'arm':
+ # This if-statement is for chroot arm-generic.
+ configure_flags['Common'].extend([
+ '--enable-cross-compile',
+ '--cross-prefix=/usr/bin/armv7a-cros-linux-gnueabi-',
+ '--target-os=linux',
+ '--arch=arm',
+ ])
+ configure_flags['Common'].extend([
+ '--enable-armv6',
+ '--enable-armv6t2',
+ '--enable-vfp',
+ '--enable-thumb',
+ '--enable-neon',
+ '--extra-cflags=-march=armv7-a',
+ '--extra-cflags=-mtune=cortex-a8',
+ '--extra-cflags=-mfpu=neon',
+ # NOTE: softfp/hardfp selected at gyp time.
+ '--extra-cflags=-mfloat-abi=hard',
+ ])
+ elif target_arch == 'mipsel':
+ configure_flags['Common'].extend([
+ '--enable-cross-compile',
+ '--cross-prefix=mips-linux-gnu-',
+ '--target-os=linux',
+ '--arch=mips',
+ '--extra-cflags=-mips32',
+ '--extra-cflags=-EL',
+ '--extra-ldflags=-mips32',
+ '--extra-ldflags=-EL',
+ '--disable-mipsfpu',
+ '--disable-mipsdspr1',
+ '--disable-mipsdspr2',
+ ])
+ else:
+ print('Error: Unknown target arch %r for target OS %r!' % (
+ target_arch, target_os), file=sys.stderr)
+ return 1
+
+ if target_os == 'linux-noasm':
+ configure_flags['Common'].extend([
+ '--disable-asm',
+ '--disable-inline-asm',
+ ])
+
+ if 'win' not in target_os:
+ configure_flags['Common'].append('--enable-pic')
+
+ # Should be run on Mac.
+ if target_os == 'mac':
+ if host_os != 'mac':
+ print('Script should be run on a Mac host. If this is not possible\n'
+ 'try a merge of config files with new linux ia32 config.h\n'
+ 'by hand.\n', file=sys.stderr)
+ return 1
+
+ configure_flags['Common'].extend([
+ '--enable-yasm',
+ '--cc=clang',
+ '--cxx=clang++',
+ ])
+ if target_arch == 'ia32':
+ configure_flags['Common'].extend([
+ '--arch=i686',
+ '--extra-cflags=-m32',
+ '--extra-ldflags=-m32',
+ ])
+ elif target_arch == 'x64':
+ configure_flags['Common'].extend([
+ '--arch=x86_64',
+ '--extra-cflags=-m64',
+ '--extra-ldflags=-m64',
+ ])
+ else:
+ print('Error: Unknown target arch %r for target OS %r!' % (
+ target_arch, target_os), file=sys.stderr)
+
+ # Should be run on Windows.
+ if target_os == 'win':
+ if host_os != 'win':
+ print('Script should be run on a Windows host.\n', file=sys.stderr)
+ return 1
+
+ configure_flags['Common'].extend([
+ '--toolchain=msvc',
+ '--enable-yasm',
+ '--extra-cflags=-I' + os.path.join(FFMPEG_DIR, 'chromium/include/win'),
+ ])
+
+ if platform.system() == 'CYGWIN_NT-6.1':
+ configure_flags['Common'].extend([
+ '--cc=cygwin-wrapper cl',
+ '--ld=cygwin-wrapper link',
+ '--nm=cygwin-wrapper dumpbin -symbols',
+ '--ar=cygwin-wrapper lib',
+ ])
+
+ # Google Chrome & ChromeOS specific configuration.
+ configure_flags['Chrome'].extend([
+ '--enable-decoder=aac,h264,mp3',
+ '--enable-demuxer=aac,mp3,mov',
+ '--enable-parser=aac,h264,mpegaudio',
+ ])
+
+ # ChromiumOS specific configuration.
+ # Warning: do *NOT* add avi, aac, h264, mp3, mp4, amr*
+ # Flac support.
+ configure_flags['ChromiumOS'].extend([
+ '--enable-demuxer=flac',
+ '--enable-decoder=flac',
+ '--enable-parser=flac',
+ ])
+
+ # Google ChromeOS specific configuration.
+ # We want to make sure to play everything Android generates and plays.
+ # http://developer.android.com/guide/appendix/media-formats.html
+ configure_flags['ChromeOS'].extend([
+ # Enable playing avi files.
+ '--enable-decoder=mpeg4',
+ '--enable-parser=h263,mpeg4video',
+ '--enable-demuxer=avi',
+ # Enable playing Android 3gp files.
+ '--enable-demuxer=amr',
+ '--enable-decoder=amrnb,amrwb',
+ # Flac support.
+ '--enable-demuxer=flac',
+ '--enable-decoder=flac',
+ '--enable-parser=flac',
+ # Wav files for playing phone messages.
+ '--enable-decoder=gsm_ms',
+ '--enable-demuxer=gsm',
+ '--enable-parser=gsm',
+ ])
+
+ do_build_ffmpeg = functools.partial(
+ BuildFFmpeg, target_os, target_arch, host_os, host_arch, parallel_jobs,
+ options.config_only)
+ do_build_ffmpeg('Chromium',
+ configure_flags['Common'] +
+ configure_flags['Chromium'] +
+ configure_args)
+ do_build_ffmpeg('Chrome',
+ configure_flags['Common'] +
+ configure_flags['Chrome'] +
+ configure_args)
+
+ if target_os == 'linux':
+ do_build_ffmpeg('ChromiumOS',
+ configure_flags['Common'] +
+ configure_flags['Chromium'] +
+ configure_flags['ChromiumOS'] +
+ configure_args)
+
+ # ChromeOS enables MPEG4 which requires error resilience :(
+ chrome_os_flags = (configure_flags['Common'] +
+ configure_flags['Chrome'] +
+ configure_flags['ChromeOS'] +
+ configure_args)
+ chrome_os_flags.remove('--disable-error-resilience')
+ do_build_ffmpeg('ChromeOS', chrome_os_flags)
+
+ print('Done. If desired you may copy config.h/config.asm into the '
+ 'source/config tree using copy_config.sh.')
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))