# Copyright 2015 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.

import("//build/config/linux/pkg_config.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/shim_headers.gni")
import("//third_party/openh264/openh264_args.gni")
import("//third_party/openh264/openh264_sources.gni")
import("//third_party/yasm/yasm_assemble.gni")

# Config shared by all openh264 targets.
config("config") {
  cflags = []

  if (is_chromeos && target_cpu == "arm") {
    # HAVE_NEON and __chromeos__ are needed for enabling NEON on ChromeOS
    # devices.
    defines = [
      "HAVE_NEON",
      "__chromeos__",
    ]
  }

  # GCC and clang flags. MSVS (is_win && !is_clang) does not use cflags.
  if (!is_win || is_clang) {
    cflags += [
      "-Wno-format",
      "-Wno-format-security",
      "-Wno-header-hygiene",
      "-Wno-unused-function",
      "-Wno-unused-value",
    ]
  }

  # Platform-specific defines.
  if (is_android) {
    # Android NDK is necessary for its cpufeatures and this define is what
    # OpenH264 code uses to check if it should be used.
    defines += [ "ANDROID_NDK" ]
  }
}

# YASM assembly is only checked to be working on Windows and Linux.
# Mac is known to fail certain tests when building, but actual assembly
# is believed to work.
# MSAN builds are flaky with assembler. crbug.com/685168

use_assembler = (is_win || is_linux) &&
                (target_cpu == "x86" || target_cpu == "x64") && !is_msan

# This IF statement will make the targets visible only on specific builds,
# which will lead to failures on other platforms if accidentally invoked.
if (use_assembler) {
  yasm_defines = []
  if (!is_component_build) {
    if (is_mac || is_ios) {
      yasm_defines += [ "WELS_PRIVATE_EXTERN=:private_extern" ]
    } else if (is_linux || is_android || is_fuchsia) {
      yasm_defines += [ "WELS_PRIVATE_EXTERN=:hidden" ]
    }
  }

  yasm_assemble("openh264_common_yasm") {
    include_dirs = openh264_common_include_dirs
    sources = openh264_common_sources_asm_x86
    defines = yasm_defines
    if (target_cpu == "x86") {
      defines += [ "X86_32" ]
    } else {  # x64
      if (is_mac) {
        defines += [
          "PREFIX",
          "UNIX64",
        ]
      } else if (is_win) {
        defines += [ "WIN64" ]
      } else if (is_linux) {
        defines += [ "UNIX64" ]
      }
    }
  }

  yasm_assemble("openh264_processing_yasm") {
    include_dirs = openh264_processing_include_dirs
    include_dirs += [ "./src/codec/common/x86" ]
    sources = openh264_processing_sources_asm_x86
    defines = yasm_defines
    if (target_cpu == "x86") {
      defines += [ "X86_32" ]
    } else {  # x64
      if (is_mac) {
        defines += [
          "PREFIX",
          "UNIX64",
        ]
      } else if (is_win) {
        defines += [ "WIN64" ]
      } else if (is_linux) {
        defines += [ "UNIX64" ]
      }
    }
  }

  yasm_assemble("openh264_encoder_yasm") {
    include_dirs = openh264_encoder_include_dirs
    include_dirs += [ "./src/codec/common/x86" ]
    sources = openh264_encoder_sources_asm_x86
    defines = yasm_defines
    if (target_cpu == "x86") {
      defines += [ "X86_32" ]
    } else {  # x64
      if (is_mac) {
        defines += [
          "PREFIX",
          "UNIX64",
        ]
      } else if (is_win) {
        defines += [ "WIN64" ]
      } else if (is_linux) {
        defines += [ "UNIX64" ]
      }
    }
  }
}  # if (is_win || is_linux)

source_set("bundled_common") {
  sources = openh264_common_sources
  if (is_chromeos && target_cpu == "arm") {
    sources += openh264_common_sources_asm_arm
  }
  include_dirs = openh264_common_include_dirs

  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]
  configs += [ ":config" ]
  deps = []
  if (use_assembler) {
    defines = [ "X86_ASM" ]
    deps += [ ":openh264_common_yasm" ]
  }
  if (is_android) {
    deps += [
      # Defines "android_get/setCpu..." functions. The original OpenH264 build
      # files replaces these using macros for "wels_..." versions of the same
      # functions. We do not have access to these and use the <cpu-features.h>
      # ones instead.
      "//third_party/android_tools:cpu_features",
    ]
  }
}

source_set("bundled_processing") {
  sources = openh264_processing_sources
  if (is_chromeos && target_cpu == "arm") {
    sources += openh264_processing_sources_asm_arm
  }
  include_dirs = openh264_processing_include_dirs

  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]
  configs += [ ":config" ]
  deps = [
    ":bundled_common",
  ]
  if (use_assembler) {
    defines = [ "X86_ASM" ]
    deps += [ ":openh264_processing_yasm" ]
  }
}

source_set("bundled_encoder") {
  sources = openh264_encoder_sources
  if (is_chromeos && target_cpu == "arm") {
    sources += openh264_encoder_sources_asm_arm
  }
  include_dirs = openh264_encoder_include_dirs

  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]
  configs += [ ":config" ]

  # TODO: Remove after fixing always-true condition
  # third_party/openh264/src/codec/encoder/core/src/encoder_ext.cpp:142.
  if (is_clang) {
    configs -= [ "//build/config/clang:extra_warnings" ]
  }
  deps = [
    ":bundled_common",
    ":bundled_processing",
  ]
  if (use_assembler) {
    defines = [ "X86_ASM" ]
    deps += [ ":openh264_encoder_yasm" ]
  }
}

if (use_system_openh264) {
  pkg_config("system_openh264") {
    packages = [ "openh264" ]
  }
}

shim_headers("openh264_shim") {
  prefix = "wels/"
  root_path = "src/codec/api/svc"
  headers = [
    "codec_api.h",
    "codec_app_def.h",
    "codec_def.h",
    "codec_ver.h",
  ]
}

group("common") {
  if (use_system_openh264) {
    deps = [ ":openh264_shim" ]
    public_configs = [ ":system_openh264" ]
  } else {
    public_deps = [ ":bundled_common" ]
  }
}

group("processing") {
  if (use_system_openh264) {
    deps = [ ":openh264_shim" ]
    public_configs = [ ":system_openh264" ]
  } else {
    public_deps = [ ":bundled_processing" ]
  }
}

group("encoder") {
  if (use_system_openh264) {
    deps = [ ":openh264_shim" ]
    public_configs = [ ":system_openh264" ]
  } else {
    public_deps = [ ":bundled_encoder" ]
  }
}
