├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── configs │ ├── .clang-format │ ├── .clang-format-ignore │ ├── .golangci.yaml │ ├── .hadolint.yaml │ ├── .ruff.toml │ └── .shellcheckrc ├── coverity │ ├── api │ │ ├── __init__.py │ │ ├── api.py │ │ └── parser.py │ ├── cov-analysis.sh │ ├── cov-build.sh │ ├── enviroment.sh │ ├── install_coverity.sh │ └── report.py ├── dependabot.yml └── workflows │ ├── base_build.yml │ ├── ci_documentation_update.yml │ ├── coverity_build.yml │ ├── coverity_reports.yml │ ├── dependency-review.yaml │ ├── docker_build.yml │ ├── linters.yml │ ├── scorecard.yml │ ├── scripts_test.yml │ └── trivy.yml ├── .gitignore ├── .gitmodules ├── .shellcheckrc ├── .sources ├── Dockerfile.sources └── README.md ├── ATTRIBUTION.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── SECURITY.md ├── build.sh ├── docker ├── app │ └── Dockerfile └── nmos │ └── Dockerfile ├── docs ├── README.md ├── architecture.md ├── attribution.md ├── build.md ├── building-commands.md ├── components │ ├── libraries-scans.md │ └── os-components-scans.md ├── host.md ├── images │ ├── all-in-one.png │ ├── hw-architecture.png │ ├── jpeg_xs-process.png │ ├── jpeg_xs.png │ ├── mcm_jpeg_xs.png │ ├── multiviewer-process.png │ ├── multiviewer.png │ ├── production-pipeline-example.png │ ├── raisr-upscaling.png │ ├── recorder-process.png │ ├── recorder.png │ ├── replay-process.png │ ├── replay.png │ ├── sw-architecture.png │ ├── upscale-process.png │ └── upscale.png ├── manual_bare_metal_installation_helper.md ├── plugins │ ├── media-communications-mesh.md │ ├── media-transport-library.md │ ├── svt-jpeg-xs.md │ └── video-super-resolution.md ├── run-know-how.md ├── run.md └── sphinx │ ├── Makefile │ ├── build_docs.md │ ├── conf.py │ └── make.bat ├── examples ├── intel-node-multiviewer-4-input.json ├── intel-node-rx-h265-2-streams.json ├── intel-node-rx-mcm-recorder.json ├── intel-node-rx-mcm-upscale.json ├── intel-node-rx-mcm.json ├── intel-node-rx-mtl.json ├── intel-node-tx-h265-2-streams.json ├── intel-node-tx-mcm-upscale.json ├── intel-node-tx-mcm.json ├── intel-node-tx-mtl.json └── run.md ├── index.rst ├── kahawai.json ├── launcher ├── .dockerignore ├── .gitignore ├── Dockerfile ├── PROJECT ├── README.md ├── api │ └── v1 │ │ ├── bcsconfig_types.go │ │ ├── groupversion_info.go │ │ └── zz_generated.deepcopy.go ├── cmd │ └── main.go ├── configuration_files │ ├── bcs-launcher.yaml │ ├── bcsconfig-crd.yaml │ ├── bcsconfig-k8s-custom-resource-example.yaml │ ├── bcslauncher-k8s-config-map.yaml │ ├── bcslauncher-static-config-custom-net-rx.yaml │ ├── bcslauncher-static-config-custom-net-tx.yaml │ ├── bcslauncher-static-config-host-net-rx.yaml │ ├── bcslauncher-static-config-host-net-tx-rx.yaml │ └── bcslauncher-static-config-host-net-tx.yaml ├── go.mod ├── go.sum ├── internal │ ├── container_controller │ │ └── container_controller.go │ └── controller │ │ ├── bcsconfig_controller.go │ │ ├── bcsconfig_controller_test.go │ │ └── suite_test.go ├── resources_library │ ├── parser │ │ └── parser.go │ ├── resources │ │ ├── bcs │ │ │ └── bcs_resources.go │ │ ├── general │ │ │ └── containers.go │ │ ├── mcm │ │ │ └── mcm_resources.go │ │ └── nmos │ │ │ └── nmos.go │ ├── utils │ │ ├── operations.go │ │ ├── operations_test.go │ │ └── parser_test.go │ └── workloads │ │ ├── workloads.go │ │ └── workloads_test.go └── test │ ├── e2e │ ├── e2e_suite_test.go │ └── e2e_test.go │ └── utils │ └── utils.go ├── patches ├── README.md └── ffmpeg │ ├── 0001-hwupload_async.diff_deprecated │ ├── 0002-qsv_aligned_malloc.diff │ ├── 0003-qsvvpp_async.diff_deprecated │ ├── 0004-filtergraph_async.diff_deprecated │ ├── 0005-ffmpeg_scheduler.diff_deprecated │ ├── kahawai_on_cartwheel.diff._ │ └── kahawai_on_cartwheel_nullsrc.diff._ ├── scripts ├── common.sh ├── entrypoint.sh └── first_run.sh ├── src ├── app │ ├── ffmpeg_pipeline_generator.cc │ └── ffmpeg_pipeline_generator.hpp ├── build_local.sh ├── common │ ├── FFmpeg_wrapper_client.h │ └── config_params.hpp ├── gRPC │ ├── CMakeLists.txt │ ├── CmdPassImpl.cc │ ├── CmdPassImpl.h │ ├── FFmpeg_wrapper_client.cc │ ├── FFmpeg_wrapper_service.cc │ ├── README.md │ ├── cmd_pass_client.cc │ ├── compile.sh │ ├── config_serialize_deserialize.hpp │ ├── ffmpeg_cmd_wrap.proto │ └── unit_test │ │ ├── CMakeLists.txt │ │ ├── FFmpeg_wrapper_service_UT.cc │ │ └── ffmpeg_pipeline_generator_test.cc └── nmos │ ├── NOTICE │ ├── README.md │ ├── RUN-SIMPLE-PIPELINE.md │ └── nmos-node │ ├── CMakeLists.txt │ ├── intel_config_parser.cpp │ ├── intel_config_parser.h │ ├── main.cpp │ ├── node_implementation.cpp │ ├── node_implementation.h │ └── unit_tests │ ├── CMakeLists.txt │ └── config_parser_tests.cc ├── tests ├── gRPC-k8s │ └── manifests.yaml ├── intel-node-multiviewer-h264.json ├── intel-node-multiviewer-h265.json ├── intel-node-multiviewer.json ├── intel-node-rx-h264.json ├── intel-node-rx-h265.json ├── intel-node-rx-mcm.json ├── intel-node-rx.json ├── intel-node-tx-1.json ├── intel-node-tx-2.json ├── intel-node-tx-h264.json ├── intel-node-tx-h265.json ├── intel-node-tx-mcm.json ├── intel-node-tx.json ├── nmos-is05-controller │ ├── README.md │ ├── receiver.json │ ├── sender.json │ └── threaded-nmos-controller05.py ├── nmos-k8s │ ├── bcs │ │ ├── bcs-rx.yaml │ │ └── bcs-tx.yaml │ └── testing-dev │ │ ├── nmos-is-05-controller.yaml │ │ ├── nmos-sample-registry.yaml │ │ └── nmos-testing.yaml ├── nmos-registry │ └── registry.json ├── test_docker_launcher_rx.sh ├── test_docker_launcher_rx_mcm.sh ├── test_docker_launcher_tx.sh ├── test_docker_launcher_tx_mcm.sh ├── test_docker_nmos_multiviewer.sh ├── test_docker_nmos_rx.sh ├── test_docker_nmos_rx_mcm.sh ├── test_docker_nmos_tx.sh └── test_docker_nmos_tx_mcm.sh └── versions.env /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .github/ 3 | .sources/ 4 | .pytest_cache/ 5 | 6 | src/gRPC/build/ 7 | src/nmos/nmos-cpp/Development/build/ 8 | src/nmos/nmos-node/build/ 9 | test/ 10 | tests/ 11 | docs/ 12 | 13 | *.md 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] " 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the Bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected Behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Environment (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Additional Context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Intel® Tiber™ Developer Cloud 4 | url: https://www.intel.com/content/www/us/en/developer/tools/devcloud/services.html 5 | about: Explore and evaluate the latest Intel® Tiber™ Developer Cloud products and learn about the Big Picture. 6 | 7 | - name: Project Documentation 8 | url: https://openvisualcloud.github.io/Intel-Tiber-Broadcast-Suite/ 9 | about: Check out our documentation for detailed information on how to use our project. 10 | 11 | - name: Security Vulnerabilities 12 | url: https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html 13 | about: Please report any security vulnerabilities in this project, [utilize the guidelines here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html), contact the [project owners](mailto:michal.swirydczuk@intel.com) or [software architect](mailto:piotr.wysocki@intel.com). 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] " 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/configs/.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | IndentWidth: 4 4 | --- 5 | Language: Cpp 6 | UseTab: Never 7 | ColumnLimit: 100 8 | BreakBeforeBraces: Custom 9 | BraceWrapping: 10 | AfterClass: false 11 | AfterNamespace: false 12 | AfterFunction: false 13 | AllowShortIfStatementsOnASingleLine: false 14 | AllowShortEnumsOnASingleLine: false 15 | IndentCaseLabels: false 16 | IncludeBlocks: Preserve 17 | SortIncludes: false 18 | ReferenceAlignment: Left 19 | AccessModifierOffset: -4 20 | --- 21 | # Don't format .proto files. 22 | Language: Proto 23 | DisableFormat: true 24 | -------------------------------------------------------------------------------- /.github/configs/.clang-format-ignore: -------------------------------------------------------------------------------- 1 | ./src/grpc 2 | ./src/gRPC/unit_test 3 | ./src/nmos/nmos-node/unit_tests 4 | ./src/nmos/nmos-cpp 5 | ./patches 6 | ./.github 7 | -------------------------------------------------------------------------------- /.github/configs/.golangci.yaml: -------------------------------------------------------------------------------- 1 | # https://golangci-lint.run/usage/configuration/ 2 | # https://github.com/oxsecurity/megalinter/blob/main/TEMPLATES/.golangci.yml 3 | linters: 4 | disable-all: true 5 | enable: 6 | - gofmt 7 | - gocritic 8 | - gosimple 9 | - govet 10 | - ineffassign 11 | - staticcheck 12 | - typecheck 13 | - unused 14 | -------------------------------------------------------------------------------- /.github/configs/.hadolint.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.astral.sh/ruff/settings/ 2 | ignored: 3 | 4 | - DL3002 # DL3002 Last user should not be root. 5 | - DL3006 # DL3006 Always tag the version of an image explicitly 6 | - DL3008 # DL3008⁠ Pin versions in apt-get install. 7 | - DL3013 # DL3013 Pin versions in pip. 8 | - DL3016 # DL3016 Pin versions in npm. 9 | - DL3018 # DL3018 Pin versions in apk add. Instead of apk add use apk add =. 10 | - DL3028 # DL3028 Pin versions in gem install. Instead of gem install use gem install : 11 | - SC2086 # SC2086 Double quote to prevent globbing and word splitting. 12 | - SC2046 # SC2046 false positive when RUN is the only command in line 13 | - DL4006 # DL4006 Set the SHELL option -o pipefail before RUN with a pipe in it. 14 | 15 | trustedRegistries: 16 | - docker.io 17 | - gcr.io 18 | - ghcr.io 19 | -------------------------------------------------------------------------------- /.github/configs/.ruff.toml: -------------------------------------------------------------------------------- 1 | # https://docs.astral.sh/ruff/settings/ 2 | [lint] 3 | # skip wildcard importss (`F403`). 4 | ignore = ["F403"] 5 | -------------------------------------------------------------------------------- /.github/configs/.shellcheckrc: -------------------------------------------------------------------------------- 1 | # https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md#rc-files 2 | # ignore var is referenced but not assigned. 3 | disable=SC2154 4 | external-sources=true 5 | -------------------------------------------------------------------------------- /.github/coverity/api/__init__.py: -------------------------------------------------------------------------------- 1 | from .parser import * 2 | from .api import * 3 | -------------------------------------------------------------------------------- /.github/coverity/api/parser.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | 4 | def issues_to_pandas(raw_response_data: dict) -> pd.DataFrame: 5 | """ 6 | Convert raw response data from Coverity API to a pandas DataFrame. 7 | 8 | Args: 9 | raw_response_data (dict): The raw response data from the Coverity API, 10 | expected to have a "rows" key containing a list of dictionaries. 11 | 12 | Returns: 13 | pd.DataFrame: A pandas DataFrame containing the converted response data, 14 | sorted by the "displayImpact" column with a categorical order of ["High", "Medium", "Low"]. 15 | """ 16 | converted_response = [] 17 | if raw_response_data["rows"]: 18 | for row in raw_response_data["rows"]: 19 | converted_dict = {item["key"]: item["value"] for item in row} 20 | converted_response.append(converted_dict) 21 | df = pd.DataFrame(converted_response) 22 | if "displayImpact" in df.columns: 23 | impact_order = ["High", "Medium", "Low"] 24 | df["displayImpact"] = pd.Categorical( 25 | df["displayImpact"], categories=impact_order 26 | ) 27 | df = df.sort_values(by="displayImpact") 28 | # remove abs path from displayFile 29 | df["displayFile"] = df["displayFile"].str.replace(r".*/_work/", "", regex=True) 30 | else: 31 | df = pd.DataFrame(columns=raw_response_data["columns"]) 32 | df.loc[0] = [" "] * len(raw_response_data["columns"]) 33 | df.iloc[0,0] = "no issues found" 34 | return df 35 | 36 | def is_report_clean(df): 37 | return df.iloc[0,0] == "no issues found" 38 | def is_grpc_record(x): 39 | return "gRPC" in x or "grpc" in x 40 | def is_launcher_record(x): 41 | return "Go" in x 42 | def filter_grpc_issues(df): 43 | if is_report_clean(df): 44 | return df 45 | else: 46 | return df[df["displayFile"].apply(is_grpc_record)] 47 | 48 | def filter_launcher_issues(df): 49 | if is_report_clean(df): 50 | return df 51 | else: 52 | return df[df["fileLanguage"].apply(is_launcher_record)] 53 | -------------------------------------------------------------------------------- /.github/coverity/cov-analysis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROOT_DIR="$(git rev-parse --show-toplevel)" 4 | . ${ROOT_DIR}/.github/coverity/enviroment.sh 5 | 6 | cd ${ROOT_DIR} 7 | 8 | tar -czvf ${COVERITY_PROJECT}.tgz cov-int 9 | 10 | curl \ 11 | --form token="${COVERITY_TOKEN}" \ 12 | --form email="${COVERITY_EMAIL}" \ 13 | --form file=@${COVERITY_PROJECT}.tgz \ 14 | --form version="${VERSION}" \ 15 | --form description="${DESCRIPTION}" \ 16 | "https://scan.coverity.com/builds?project=${COVERITY_PROJECT}" 17 | 18 | 19 | echo " Project URL: https://scan.coverity.com/builds?project=${COVERITY_PROJECT} \n\ 20 | Analysis branch/description: ${DESCRIPTION} \n\ 21 | Analysis commit/version: ${VERSION} \n\ 22 | submit date: $(date) \n" > analysis-details.txt 23 | -------------------------------------------------------------------------------- /.github/coverity/cov-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | 4 | 5 | ROOT_DIR="$(git rev-parse --show-toplevel)" 6 | . ${ROOT_DIR}/.github/coverity/enviroment.sh 7 | 8 | 9 | function coverity_cpp_build(){ 10 | local SCRIPT=${1} 11 | PWD=$(pwd) 12 | ${COVERITY_CPP_BIN_DIR}/cov-build "--dir" "${ROOT_DIR}/cov-int/" "--append-log" "${PWD}/${SCRIPT}" > "$(basename ${PWD}).log" 13 | log_info "cov-build ${FOLDER} done" 14 | } 15 | 16 | function coverity_other_build(){ 17 | local SCRIPT=${1} 18 | rm -rf cov/* 19 | PWD=$(pwd) 20 | ${COVERITY_OTHER_BIN_DIR}/cov-build "--dir" "${ROOT_DIR}/cov-int/" "--append-log" "${PWD}/${SCRIPT}" > "$(basename ${PWD}).log" 21 | log_info "cov-build ${FOLDER} done" 22 | } 23 | 24 | function usage(){ 25 | echo " Usage : $0 " 26 | echo " BUILD_TYPE : all | grpc | launcher" 27 | } 28 | 29 | 30 | function build_grpc(){ 31 | log_info "building gRPC" 32 | cd ${ROOT_DIR}/src/gRPC 33 | sed -i 's/make -C "${COMPILE_DIR}\/build"/make -B -C "${COMPILE_DIR}\/build"/' compile.sh 34 | coverity_cpp_build compile.sh 35 | } 36 | 37 | function build_launcher(){ 38 | log_info "building launcher" 39 | cd ${ROOT_DIR}/launcher 40 | echo "go build -a -o manager cmd/main.go" > build.sh 41 | chmod +x build.sh 42 | coverity_other_build build.sh 43 | } 44 | 45 | function build_all(){ 46 | log_info "starting cov-build" 47 | build_grpc 48 | build_launcher 49 | log_info "All builds have completed" 50 | } 51 | 52 | if [ $# -ne 1 ]; then 53 | usage 54 | exit 1 55 | fi 56 | 57 | case $1 in 58 | grpc) 59 | build_grpc 60 | ;; 61 | launcher) 62 | build_launcher 63 | ;; 64 | all) 65 | build_all 66 | ;; 67 | *) 68 | usage 69 | exit 1 70 | ;; 71 | esac 72 | -------------------------------------------------------------------------------- /.github/coverity/enviroment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | COV_CPP_VER="$(ls /opt/coverity/cxx)" 4 | COV_OTHER_VER="$(ls /opt/coverity/other)" 5 | COVERITY_CPP_BIN_DIR="/opt/coverity/cxx/$COV_CPP_VER/bin" 6 | COVERITY_OTHER_BIN_DIR="/opt/coverity/other/$COV_OTHER_VER/bin" 7 | COV_CPP_JAVA_HOME="${COVERITY_CPP_BIN_DIR}/jre/bin/java" 8 | COV_OTHER_JAVA_HOME="${COVERITY_OTHER_BIN_DIR}/jre/bin/java" 9 | 10 | function export_cpp_java(){ 11 | export JAVA_HOME="${COV_CPP_JAVA_HOME}" 12 | } 13 | function export_other_java(){ 14 | export JAVA_HOME="${COV_OTHER_JAVA_HOME}" 15 | } 16 | function log_info(){ 17 | echo "[INFO]: ${1}" 18 | } 19 | function log_warning(){ 20 | echo "[WARNING]: ${1} " 21 | } 22 | -------------------------------------------------------------------------------- /.github/coverity/install_coverity.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | COVERITY_URL="https://scan.coverity.com/download/${LANGUAGE}/linux64" 4 | COVERITY_TOOL_FILE="coverity_tool_${LANGUAGE}.tgz" 5 | 6 | # Check if required environment variables are set 7 | if [ -z "$COVERITY_PROJECT" ] || [ -z "$COVERITY_TOKEN" ] || [ -z "$LANGUAGE" ]; then 8 | echo "Error: COVERITY_PROJECT, COVERITY_TOKEN and LANGUAGE environment variables must be set." 9 | exit 1 10 | fi 11 | 12 | # Download Coverity Scan 13 | echo "Downloading ${LANGUAGE} Coverity Scan..." 14 | curl -L "${COVERITY_URL}" \ 15 | --output "${COVERITY_TOOL_FILE}" \ 16 | --data "token=${COVERITY_TOKEN}" \ 17 | --data "project=${COVERITY_PROJECT}" 18 | 19 | # Extract Coverity Scan 20 | sudo mkdir -p "/opt/coverity/${LANGUAGE}" 21 | echo "Extracting ${LANGUAGE} Coverity Scan..." 22 | sudo tar -xzf "${COVERITY_TOOL_FILE}" -C "/opt/coverity/${LANGUAGE}" 23 | 24 | echo "coverity installation completed successfully." 25 | echo "binary installed in /opt/coverity/${LANGUAGE}/bin/ folder" 26 | -------------------------------------------------------------------------------- /.github/coverity/report.py: -------------------------------------------------------------------------------- 1 | import api 2 | import sys 3 | import logging 4 | 5 | 6 | def main(): 7 | logging.basicConfig(level=logging.INFO) 8 | log = logging.getLogger(__name__) 9 | 10 | try: 11 | branch = sys.argv[1] 12 | commit = sys.argv[2] 13 | except IndexError: 14 | print("Usage: python report.py ") 15 | sys.exit(1) 16 | 17 | query = api.prepare_query() 18 | if not query: 19 | log.error("failed to init query") 20 | sys.exit(1) 21 | 22 | log.info(f"fetching snapshot for branch {branch} and commit {commit}") 23 | query["snapshot"] = api.get_snapshot(query, branch, commit) 24 | if query["snapshot"] == 0: 25 | log.error( 26 | "No snapshot found, for the branch:{branch} and commit:{commit}, the analysis might not be done yet" 27 | ) 28 | sys.exit(1) 29 | 30 | log.info("snapshot found") 31 | log.info(f"fetching issues for snapshot from {branch}/{commit}") 32 | 33 | issues = api.get_snapshot_issues(query) 34 | df = api.issues_to_pandas(issues) 35 | 36 | log.info("generating reports") 37 | df_grpc = api.filter_grpc_issues(df) 38 | df_launcher = api.filter_launcher_issues(df) 39 | df_grpc.to_csv("grpc_report.csv", index=False) 40 | df_launcher.to_csv("launcher_report.csv", index=False) 41 | 42 | log.info("fetching outstanding view issues") 43 | outstanding_issues = api.fetch_outstanding_view_issues(query) 44 | df_outstanding = api.issues_to_pandas(outstanding_issues) 45 | df_outstanding.to_csv("outstanding_issues.csv", index=False) 46 | log.info("Reports generated") 47 | 48 | 49 | if __name__ == "__main__": 50 | main() 51 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: /.github 5 | schedule: 6 | interval: "weekly" 7 | day: "sunday" 8 | 9 | - package-ecosystem: docker 10 | directory: / 11 | schedule: 12 | interval: "weekly" 13 | day: "sunday" 14 | -------------------------------------------------------------------------------- /.github/workflows/base_build.yml: -------------------------------------------------------------------------------- 1 | name: Base Build 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | pull_request: 7 | push: 8 | branches: [ "main" ] 9 | 10 | permissions: 11 | contents: read 12 | jobs: 13 | build: 14 | name: "Binaries build for Intel® Tiber™ Broadcast Suite" 15 | runs-on: ubuntu-22.04 16 | timeout-minutes: 120 17 | permissions: 18 | contents: read 19 | steps: 20 | - name: "OS-Configuration: Preparation: Harden Runner" 21 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 22 | with: 23 | egress-policy: audit 24 | 25 | - name: "Preparation: Repository Checkout" 26 | uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 27 | 28 | - name: "Build: gRPC and nmos" 29 | working-directory: "${{ github.workspace }}/src" 30 | run: | 31 | sudo rm /usr/local/bin/cmake 32 | sudo apt-get install -y git cmake=3.22* libboost-all-dev libcpprest-dev libavahi-client-dev libavahi-compat-libdnssd-dev libgtest-dev 33 | sudo ./build_local.sh -ut 34 | sudo chown -R $USER:$USER . 35 | - name: "grpc unit tests" 36 | working-directory: "${{ github.workspace }}/src/gRPC/unit_test/build" 37 | run: | 38 | ./FFmpegPipelineGeneratorTests 39 | ./FFmpegWrapperServiceTests 40 | 41 | - name: "nmos unit tests" 42 | working-directory: "${{ github.workspace }}/src/nmos/nmos-node/build/unit_tests" 43 | run: | 44 | ./NmosNodeTests 45 | 46 | - name: "list: gRPC and nmos" 47 | working-directory: "${{ github.workspace }}/src" 48 | run: | 49 | ls -la ${{ github.workspace }}/src/gRPC/build/ 50 | ls -la ${{ github.workspace }}/src/nmos/nmos-node/build/ 51 | - name: 'upload gRpc binaries' 52 | uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 53 | with: 54 | name: grpc-nmos-bin 55 | path: | 56 | ${{ github.workspace }}/src/gRPC/build/cmd_pass_client 57 | ${{ github.workspace }}/src/gRPC/build/FFmpeg_wrapper_service 58 | ${{ github.workspace }}/src/nmos/nmos-node/build/bcs-nmos-node 59 | 60 | - name: "Build: launcher" 61 | working-directory: "${{ github.workspace }}/launcher" 62 | run: 63 | go build -a -o manager cmd/main.go 64 | 65 | - name: 'upload launcher binaries' 66 | uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 67 | with: 68 | name: launcher-bin 69 | path: '${{ github.workspace }}/launcher/manager' 70 | -------------------------------------------------------------------------------- /.github/workflows/ci_documentation_update.yml: -------------------------------------------------------------------------------- 1 | name: Publish Github Pages Template 2 | 3 | on: 4 | push: 5 | branches: [ 'main' ] 6 | workflow_call: 7 | workflow_dispatch: 8 | inputs: 9 | branch: 10 | description: "Branch that will be used for documentation source." 11 | required: true 12 | default: main 13 | 14 | permissions: 15 | contents: read 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | publishGitHubPages: 23 | name: Publish GitHub Pages 24 | permissions: 25 | contents: read 26 | id-token: write 27 | pages: write 28 | environment: 29 | name: github-pages 30 | url: ${{ steps.deployment.outputs.page_url }} 31 | runs-on: ubuntu-22.04 32 | timeout-minutes: 20 33 | steps: 34 | - name: Secure the runner 35 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 36 | with: 37 | egress-policy: audit 38 | 39 | - name: Checkout 40 | uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 41 | with: 42 | branch: ${{ inputs.branch }} 43 | 44 | - name: Prepare operating system for documentation build 45 | run: | 46 | sudo apt-get update -y && \ 47 | sudo apt-get install -y --no-install-recommends make python3 python3-pip python3-sphinx 48 | 49 | - name: Prepare environment for documentation build 50 | run: python3 -m pip install sphinx_book_theme myst_parser sphinxcontrib.mermaid sphinx-copybutton 51 | 52 | - name: Build documentation 53 | run: make -C docs/sphinx html 54 | 55 | - name: Upload GitHub Pages artifact 56 | uses: actions/upload-pages-artifact@v3.0.1 57 | with: 58 | path: ./docs/_build/html 59 | 60 | - name: Publish to GitHub Pages 61 | id: deployment 62 | uses: actions/deploy-pages@v4 63 | -------------------------------------------------------------------------------- /.github/workflows/coverity_build.yml: -------------------------------------------------------------------------------- 1 | name: Coverity Build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | schedule: 7 | - cron: "0 0 * * *" 8 | workflow_dispatch: 9 | inputs: 10 | branch: 11 | description: 'Branch to run scans on' 12 | default: 'main' 13 | type: string 14 | 15 | permissions: 16 | contents: read 17 | env: 18 | COVERITY_PROJECT: 'Intel-Tiber-Broadcast-Suite' 19 | COVERITY_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }} 20 | COVERITY_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} 21 | DESCRIPTION: ${{ github.ref_name }} 22 | VERSION: ${{ github.sha }} 23 | jobs: 24 | build: 25 | name: 'coverity' 26 | runs-on: ubuntu-latest 27 | timeout-minutes: 90 28 | steps: 29 | - name: 'setup: cleanup worskpace' 30 | run: | 31 | ls -la ./ 32 | rm -rf ./* || true 33 | rm -rf ./.??* || true 34 | ls -la ./ 35 | 36 | - name: 'setup: checkout repo' 37 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 38 | with: 39 | ref: ${{ inputs.branch }} 40 | - name: install coverity tools for cpp and golang 41 | run: | 42 | export LANGUAGE=cxx 43 | .github/coverity/install_coverity.sh 44 | export LANGUAGE=other 45 | .github/coverity/install_coverity.sh 46 | 47 | - name: 'coverity: build code' 48 | run: .github/coverity/cov-build.sh all 49 | 50 | - name: 'coverity: server upload' 51 | if: github.event_name == 'schedule' 52 | run: .github/coverity/cov-analysis.sh 53 | 54 | - name: 'coverity: upload raw build artifacts' 55 | if: github.event_name == 'schedule' 56 | uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 57 | with: 58 | name: coverity-scan--details 59 | path: '${{ github.workspace }}/analysis-details.txt' 60 | -------------------------------------------------------------------------------- /.github/workflows/coverity_reports.yml: -------------------------------------------------------------------------------- 1 | name: Coverity reports 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | branch: 7 | description: 'scanned branch name' 8 | required: true 9 | type: string 10 | commit: 11 | description: 'scanned commit hash' 12 | type: string 13 | required: true 14 | permissions: 15 | contents: read 16 | jobs: 17 | generate_reports: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: 'setup: checkout repo' 21 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 22 | 23 | - name: 'coverity: setup python' 24 | run: pip3 install pandas 25 | 26 | - name: 'coverity: generate_reports' 27 | working-directory: ${{ github.workspace }}/.github/coverity 28 | run: python3 report.py ${{ inputs.branch }} ${{ inputs.commit }} 29 | env: 30 | COVERITY_BASE_URL: ${{ secrets.COVERITY_REPORTS_BASE_URL }} 31 | COVERITY_TOKEN: ${{ secrets.COVERITY_REPORTS_TOKEN }} 32 | COVERITY_PROJECT_NAME: 'Intel-Tiber-Broadcast-Suite' 33 | COVERITY_USER: ${{ secrets.COVERITY_REPORTS_USER }} 34 | COVERITY_OUTSTANDING_VIEW_ID: ${{ secrets.COVERITY_OUTSTANDING_VIEW_ID }} 35 | COVERITY_PROJECT_ID: ${{ secrets.COVERITY_PROJECT_ID }} 36 | 37 | - name: prepare artifacts 38 | if: success() 39 | run: | 40 | mkdir ${{ github.workspace }}/cov-reports && cd ${{ github.workspace }}/cov-reports 41 | mv ${{ github.workspace }}/.github/coverity/*.csv . 42 | echo "Coverity reports for ${{ inputs.branch }} ${{ inputs.commit }}" > details.txt 43 | - name: 'coverity: upload reports' 44 | if: success() 45 | uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 46 | with: 47 | name: coverity-reports 48 | path: '${{ github.workspace }}/cov-reports' 49 | 50 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yaml: -------------------------------------------------------------------------------- 1 | # Source repository: https://github.com/actions/dependency-review-action 2 | name: Dependency Review 3 | on: 4 | pull_request: 5 | branches: [ 'main' ] 6 | 7 | permissions: 8 | contents: read 9 | 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} 12 | cancel-in-progress: true 13 | 14 | jobs: 15 | dependency-review: 16 | runs-on: ubuntu-22.04 17 | steps: 18 | - name: 'Harden Runner' 19 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 20 | with: 21 | egress-policy: audit 22 | 23 | - name: 'Checkout Repository' 24 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 25 | 26 | - name: 'Dependency Review' 27 | uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3 28 | -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | name: Linter 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | pull_request: 7 | branches: [ 'main' ] 8 | push: 9 | branches: [ 'main' ] 10 | 11 | permissions: 12 | contents: read 13 | defaults: 14 | run: 15 | shell: bash 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | linter: 22 | name: 'code space lint' 23 | permissions: 24 | contents: read 25 | runs-on: ubuntu-22.04 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | BASH_SEVERITY: "warning" 29 | steps: 30 | - name: 'setup: harden runner' 31 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 32 | with: 33 | egress-policy: audit 34 | 35 | - name: 'setup: checkout repo' 36 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 37 | with: 38 | fetch-depth: 0 39 | 40 | - name: Lint Code Base 41 | uses: super-linter/super-linter/slim@e1cb86b6e8d119f789513668b4b30bf17fe1efe4 # v7.2.0 x-release-please-version 42 | env: 43 | VALIDATE_CPP: false 44 | VALIDATE_JSCPD: false 45 | VALIDATE_JSON: false 46 | VALIDATE_JSON_PRETTIER: false 47 | VALIDATE_MARKDOWN_PRETTIER: false 48 | VALIDATE_MARKDOWN: false 49 | VALIDATE_CHECKOV: false 50 | VALIDATE_BASH_EXEC: false 51 | VALIDATE_CSS_PRETTIER: false 52 | VALIDATE_ENV: false 53 | VALIDATE_GIT_COMMITLINT: false 54 | VALIDATE_GIT_MERGE_CONFLICT_MARKERS: false 55 | VALIDATE_GITHUB_ACTIONS: false 56 | VALIDATE_GITLEAKS: false 57 | VALIDATE_NATURAL_LANGUAGE: false 58 | VALIDATE_PYTHON: false 59 | VALIDATE_PYTHON_BLACK: false 60 | VALIDATE_PYTHON_FLAKE8: false 61 | VALIDATE_PYTHON_ISORT: false 62 | VALIDATE_PYTHON_MYPY: false 63 | VALIDATE_PYTHON_PYINK: false 64 | VALIDATE_PYTHON_PYLINT: false 65 | VALIDATE_KUBERNETES_KUBECONFORM: false 66 | VALIDATE_SHELL_SHFMT: false 67 | VALIDATE_YAML_PRETTIER: false 68 | VALIDATE_YAML: false 69 | VALIDATE_GO_MODULES: false 70 | VALIDATE_GO: false # linter does not use config files 71 | VALIDATE_CLANG_FORMAT: false # TODO: clang still see the same errors after running formatter on code base 72 | LINTER_RULES_PATH: .github/configs 73 | PYTHON_RUFF_CONFIG_FILE: .ruff.toml 74 | DOCKERFILE_HADOLINT_FILE_NAME: .hadolint.yaml 75 | BASH_FILE_NAME: .shellcheckrc 76 | CLANG_FORMAT_FILE_NAME: .clang-format 77 | -------------------------------------------------------------------------------- /.github/workflows/scorecard.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. They are provided 2 | # by a third-party and are governed by separate terms of service, privacy 3 | # policy, and support documentation. 4 | 5 | name: Scorecard supply-chain security 6 | on: 7 | workflow_dispatch: 8 | inputs: 9 | branch: 10 | required: true 11 | default: "main" 12 | # For Branch-Protection check. Only the default branch is supported. See 13 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection 14 | branch_protection_rule: 15 | # To guarantee Maintained check is occasionally updated. See 16 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained 17 | schedule: 18 | - cron: '45 0 * * *' 19 | push: 20 | branches: [ "main" ] 21 | 22 | permissions: 23 | contents: read 24 | 25 | concurrency: 26 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} 27 | cancel-in-progress: true 28 | 29 | jobs: 30 | analysis: 31 | name: Scorecard analysis 32 | runs-on: ubuntu-latest 33 | if: ${{ github.repository == 'OpenVisualCloud/Intel-Tiber-Broadcast-Suite' }} 34 | permissions: 35 | security-events: write 36 | id-token: write 37 | contents: read 38 | actions: read 39 | steps: 40 | - name: "scorecard: Harden Runner security" 41 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 42 | with: 43 | egress-policy: audit 44 | 45 | - name: "scorecard: Checkout code" 46 | uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 47 | with: 48 | persist-credentials: false 49 | 50 | - name: "scorecard: Run analysis" 51 | uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 52 | with: 53 | results_file: "scorecard-scan-results-${{ github.event.pull_request.number || github.sha }}.sarif" 54 | results_format: sarif 55 | repo_token: ${{ secrets.GITHUB_TOKEN }} 56 | publish_results: true 57 | 58 | # Upload the results as artifacts (optional). 59 | - name: "scorecard: Upload results artifact" 60 | uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 61 | with: 62 | name: "scorecard-scan-results-${{ github.event.pull_request.number || github.sha }}" 63 | path: "scorecard-scan-results-${{ github.event.pull_request.number || github.sha }}.sarif" 64 | retention-days: 5 65 | 66 | - name: "scorecard: Upload results to code-scanning" 67 | uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 68 | with: 69 | sarif_file: "scorecard-scan-results-${{ github.event.pull_request.number || github.sha }}.sarif" 70 | -------------------------------------------------------------------------------- /.github/workflows/scripts_test.yml: -------------------------------------------------------------------------------- 1 | name: Scripts Test 2 | 3 | on: 4 | workflow_call: 5 | workflow_dispatch: 6 | pull_request: 7 | push: 8 | branches: [ "main" ] 9 | 10 | permissions: 11 | contents: read 12 | 13 | env: 14 | BUILD_TYPE: "CI" 15 | LOCAL_INSTALL: "true" 16 | CMAKE_BUILD_TYPE: "Release" 17 | DEBIAN_FRONTEND: "noninteractive" 18 | TERM: "xterm" 19 | 20 | jobs: 21 | build: 22 | name: "Test Script for Environment Setup - Intel® Tiber™ Broadcast Suite" 23 | runs-on: ["self-hosted", "coverity", "Linux"] 24 | timeout-minutes: 120 25 | permissions: 26 | contents: read 27 | steps: 28 | - name: "OS-Configuration: Preparation: Harden Runner" 29 | uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1 30 | with: 31 | egress-policy: audit 32 | 33 | - name: "Preparation: Repository Checkout" 34 | uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 35 | 36 | - name: "Test first_run script" 37 | working-directory: "${{ github.workspace }}" 38 | run: | 39 | sudo ./scripts/first_run.sh -d 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | docs/_build 2 | _build 3 | build 4 | src/gRPC/build 5 | src/gRPC/unit_test/build 6 | src/gRPC/unit_test/Testing 7 | file*.json 8 | .reports 9 | NVMUpdatePackage 10 | *.a 11 | *.sdp 12 | grpc 13 | nmos-cpp* 14 | src/nmos/nmos-is05-controller/receiver.json 15 | src/nmos/nmos-is05-controller/sender.json 16 | 17 | # pipeline configuration and input files 18 | *.yuv 19 | VARIABLES.rc 20 | 21 | # local installation directory 22 | local_debians 23 | .temp.env 24 | __pycache__ 25 | *.csv 26 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | [submodule "src/nmos/nmos-cpp"] 3 | path = src/nmos/nmos-cpp 4 | url = https://github.com/sony/nmos-cpp.git 5 | [submodule "submodules/Video-Super-Resolution-Library"] 6 | path = submodules/Video-Super-Resolution-Library 7 | url = https://github.com/OpenVisualCloud/Video-Super-Resolution-Library 8 | [submodule "submodules/SVT-JPEG-XS"] 9 | path = submodules/SVT-JPEG-XS 10 | url = https://github.com/OpenVisualCloud/SVT-JPEG-XS 11 | [submodule "submodules/Media-Communications-Mesh"] 12 | path = submodules/Media-Communications-Mesh 13 | url = https://github.com/OpenVisualCloud/Media-Communications-Mesh 14 | -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | external-sources=true 2 | -------------------------------------------------------------------------------- /.sources/README.md: -------------------------------------------------------------------------------- 1 | # Intel® Tiber™ Broadcast Suite Source Browser Docker 2 | 3 | ## Overview 4 | 5 | This Docker image is created solely for the purpose of browsing the source code of the Intel® Tiber™ Broadcast Suite. It contains all the source files but does not provide any functionality or executable binaries. 6 | 7 | ## ⚠️ Warning 8 | 9 | > **This Docker image has no functionality and only contains the source files.** 10 | > It is not intended for running or testing the Intel® Tiber™ Broadcast Suite. 11 | > If you are looking to build and run the suite, please refer to the [README](../docs/README.md). 12 | 13 | ## Prerequisites 14 | - Docker installed on your machine. 15 | 16 | ## Build Instructions 17 | 18 | To build the Docker image, use the following command: 19 | 20 | ```bash 21 | # access the root of the folder 22 | cd Intel-Tiber-Broadcast-Suite 23 | 24 | # build the sources docker 25 | ENV_PROXY_ARGS=() 26 | while IFS='' read -r line; do 27 | ENV_PROXY_ARGS+=("--build-arg") 28 | ENV_PROXY_ARGS+=("${line}=${!line}") 29 | done < <(compgen -e | grep -E "_(proxy|PROXY)") 30 | docker build "${ENV_PROXY_ARGS[@]}" "$@" -f .sources/Dockerfile.sources -t 2024.1.0-sources . 31 | ``` 32 | 33 | ## Usage 34 | 35 | To use this Docker image: 36 | 37 | ```bash 38 | docker run -it 2024.1.0-sources 39 | ``` 40 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Summary of Changes for Intel® Tiber™ Broadcast Suite - 25.04 Release: 2 | 3 | ### What's Changed 4 | 5 | - Transitioned from a single-container architecture based on FFmpeg to an advanced architecture featuring a processing component with a pre-configured FFmpeg pipeline generator and a control component based on NMOS 6 | - Added NMOS support for IS-04 and IS-05 standards 7 | - Enabled Kubernetes-managed runtime environment for improved scalability and deployment 8 | - Introduced a Launcher as a centralized point for user interaction 9 | - Implemented gRPC-based communication between the Application container and the NMOS container 10 | - Optimized installation scripts and updated user guides for better usability 11 | - Updated the supported version of Media Transport Library (MTL) to 25.02.1 12 | - Updated the supported version of Media Communication Mesh to 25.03 13 | 14 | 15 | # Summary of Changes for Intel® Tiber™ Broadcast Suite - 24.10 Release: 16 | 17 | ### What's Changed 18 | 19 | - Support Nvidia GPU (CUDA filters) 20 | - Uploaded Intel® Tiber™ Broadcast Suite to the Docker Hub 21 | - Enabled build of Intel® Tiber™ Broadcast Suite from Debian packages 22 | - Updated supported FFmpeg version to 7.0 23 | - Updated documentation 24 | - Updated build.sh 25 | 26 | 27 | # Summary of Changes for Intel® Tiber™ Broadcast Suite - 24.07 Release: 28 | 29 | ### What's Changed 30 | 31 | - Move the lcore management to mtl-manager 32 | - Remove unnecessary MTL patch and adjust tag 33 | - Minor update to build.md 34 | 35 | 36 | # Summary of Changes for Intel® Tiber™ Broadcast Suite - Initial Release: 37 | 38 | ### New Features: 39 | 40 | - Comprehensive Integration with FFmpeg: Enhanced version of FFmpeg tailored with Intel's patches for optimized media handling. 41 | - Advanced Media Processing: Integration of Intel® QSV and OneVPL for GPU-accelerated processing. 42 | - SMPTE ST 2110 Compliance: Full support for media transport protocols ensuring high compatibility and performance in professional environments. 43 | - JPEG XS Support: Includes encoding and decoding capabilities for JPEG XS, optimizing bandwidth and storage. 44 | - GPU Media Rendering: Utilizes Intel Flex GPU cards for efficient media rendering tasks. 45 | - Intel® QSV and OneVPL libraries: These libraries support hardware-accelerated media processing with Intel Flex GPU cards, enhancing the performance of the Suite. 46 | - DPC++ kernels: Although not supported in this release, the Suite is designed to enable custom effect filters used in video production in future releases. 47 | - OpenGL/Vulcan feature integration. 48 | - Performance features: The Suite includes several performance features such as memory management optimizations for page-aligned surface allocations, asynchronous execution of video pipeline filters to maximize GPU utilization, and high-throughput GPU-CPU memory data transfers. 49 | - Mesh Plugin: This plugin allows single or multiple instances of FFmpeg with Mesh Plugin to connect to selected Media Proxy instance, enhancing the efficiency of the Suite. 50 | - Support for PTP Time synchronization: This feature uses Media Transport Library PTP Time synchronization feature, enhancing the synchronization of the Suite. 51 | - Support for changing input and output streams Payload ID: This feature adds flexibility to the deployment of the Suite. 52 | 53 | 54 | ### Enhancements: 55 | 56 | - Optimized Memory Management: Improvements in memory allocation that enhance performance and reduce latency. 57 | - Asynchronous Execution: Video pipeline filters operate asynchronously to maximize GPU utilization. 58 | - High-Throughput Transfers: Enhanced GPU-CPU memory data transfers for high-performance media streaming. 59 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [lukasz.cybura@intel.com](mailto:lukasz.cybura@intel.com) or at e-mail of project owners. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) 44 | 45 | For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Intel® Tiber™ Broadcast Suite 2 | 3 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | - Becoming a maintainer 10 | 11 | ## We Develop with Github 12 | 13 | We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. 14 | 15 | ## Pull Requests 16 | 17 | Please follow these steps to have your contribution considered by the maintainers: 18 | 19 | 1. Fork the repo and create your branch from `main`. 20 | 2. If you've added code that should be tested, add tests. 21 | 3. Ensure the test suite passes. 22 | 4. Make sure your code lints. 23 | 5. Issue that pull request! 24 | 25 | ## Any contributions you make will be under the BSD 3-Clause Software License 26 | 27 | In short, when you submit code changes, your submissions are understood to be under the same [BSD 3-Clause License](LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. 28 | 29 | ## Report bugs using Github's [issues](https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/issues) 30 | 31 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/issues/new); it's that easy! 32 | 33 | ## Write bug reports with detail, background, and sample code 34 | 35 | **Great Bug Reports** tend to have: 36 | 37 | - A quick summary and/or background 38 | - Steps to reproduce 39 | - Be specific! 40 | - Give sample code if you can. 41 | - What you expected would happen 42 | - What actually happens 43 | - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) 44 | 45 | People *love* thorough bug reports. 46 | 47 | ## Use a Consistent Coding Style 48 | 49 | * You can use an automatic formatter like `prettier`. 50 | * Run linters to check your code. 51 | * Follow the `super-linter` example provided in the README. 52 | 53 | ## License 54 | 55 | By contributing, you agree that your contributions will be licensed under its BSD 3-Clause License. 56 | 57 | ## References 58 | 59 | This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/master/CONTRIBUTING.md). 60 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # BSD 3-Clause License 2 | 3 | Copyright (c) 2024, Intel Corporation 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. 3 | 4 | ## Reporting a Vulnerability 5 | Please report any security vulnerabilities in this project [utilizing the guidelines here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). -------------------------------------------------------------------------------- /docs/host.md: -------------------------------------------------------------------------------- 1 | # Hardware and software requirements 2 | 3 | ## 1. Hardware requirements 4 | 5 | Intel® Tiber™ Broadcast Suite is developed and tested on following platforms: 6 | 7 | Platform | CPU | GPU | NIC 8 | --- | --- | --- | --- 9 | Intel® Server System M50CYP Family| Intel® Xeon® Platinum 8358 CPU | Intel® Data Center GPU Flex Series 140/170 | Intel® E810 Series Ethernet Adapter 10 | Inspur NF5280M7 | Intel® Xeon® Platinum 8490H CPU | Intel® Data Center GPU Flex Series 140/170 | Intel® E810 Series Ethernet Adapter 11 | 12 | ![Hardware architecture diagram](images/hw-architecture.png) 13 | 14 | ## 2. Software requirements 15 | 16 | Intel® Tiber™ Broadcast Suite is developed and tested on: 17 | * __Ubuntu 22.04__ with kernel __5.15.0-136-generic__ 18 | -------------------------------------------------------------------------------- /docs/images/all-in-one.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/all-in-one.png -------------------------------------------------------------------------------- /docs/images/hw-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/hw-architecture.png -------------------------------------------------------------------------------- /docs/images/jpeg_xs-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/jpeg_xs-process.png -------------------------------------------------------------------------------- /docs/images/jpeg_xs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/jpeg_xs.png -------------------------------------------------------------------------------- /docs/images/mcm_jpeg_xs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/mcm_jpeg_xs.png -------------------------------------------------------------------------------- /docs/images/multiviewer-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/multiviewer-process.png -------------------------------------------------------------------------------- /docs/images/multiviewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/multiviewer.png -------------------------------------------------------------------------------- /docs/images/production-pipeline-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/production-pipeline-example.png -------------------------------------------------------------------------------- /docs/images/raisr-upscaling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/raisr-upscaling.png -------------------------------------------------------------------------------- /docs/images/recorder-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/recorder-process.png -------------------------------------------------------------------------------- /docs/images/recorder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/recorder.png -------------------------------------------------------------------------------- /docs/images/replay-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/replay-process.png -------------------------------------------------------------------------------- /docs/images/replay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/replay.png -------------------------------------------------------------------------------- /docs/images/sw-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/sw-architecture.png -------------------------------------------------------------------------------- /docs/images/upscale-process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/upscale-process.png -------------------------------------------------------------------------------- /docs/images/upscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/d04492e42da11efdff285c2c69a492ae2b5c6e98/docs/images/upscale.png -------------------------------------------------------------------------------- /docs/run-know-how.md: -------------------------------------------------------------------------------- 1 | # Docker command breakdown 2 | 3 | Full Intel® Tiber™ Broadcast Suite pipeline command consists of `docker run [docker_parameters] video_production_image [broadcast_suite_parameters]`. 4 | This document describes a docker-related part of command - all `[docker_parameters]` switches until the name of the image, called `video_production_image`. 5 | 6 | Information about the `[broadcast_suite_parameters]` part of the command may be found, depending on the plugin, under: 7 | - [FFmpeg Media Communications Mesh Muxer Parameters Table](plugins/media-communications-mesh.md) 8 | - [Media Transport Library](plugins/media-transport-library.md) 9 | - [FFmpeg Intel® JPEG XS Parameters Table](plugins/svt-jpeg-xs.md) 10 | - [Raisr FFmpeg Filter Plugin Parameters Table](plugins/video-super-resolution.md) 11 | 12 | 13 | ## Command example 14 | 15 | > **Note:** The example below is based on [../pipelines/jpeg_xs_rx.sh](pipelines/jpeg_xs_rx.sh). Some of the pipelines may require a different number of parameters in order to run. 16 | 17 | ```bash 18 | docker run -it \ 19 | --user root\ 20 | --privileged \ 21 | --device=/dev/vfio:/dev/vfio \ 22 | --device=/dev/dri:/dev/dri \ 23 | --cap-add ALL \ 24 | -v "$(pwd)":/videos \ 25 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 26 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 27 | -v /var/run/imtl:/var/run/imtl \ 28 | -v /dev/null:/dev/null \ 29 | -v /tmp/hugepages:/tmp/hugepages \ 30 | -v /hugepages:/hugepages \ 31 | --network=my_net_801f0 \ 32 | --ip=192.168.2.2 \ 33 | --expose=20000-20170 \ 34 | --ipc=host -v /dev/shm:/dev/shm \ 35 | video_production_image [broadcast_suite_parameters] 36 | ``` 37 | 38 | ## Docker parameters breakdown 39 | 40 | - `-it`: Runs the container in interactive mode with a TTY for interaction. 41 | - `--user root`: Sets the user inside the container to `root`. 42 | - `--privileged`: Grants the container full access to the host system. 43 | - `--device=/dev/vfio:/dev/vfio`: Mounts the host's `/dev/vfio` directory inside the container. 44 | - `--device=/dev/dri:/dev/dri`: Mounts the host's `/dev/dri` directory inside the container. 45 | - `--cap-add ALL`: Gives the container all capabilities, similar to root access. 46 | - `-v "$(pwd)":/videos`: Binds the current working directory on the host to `/videos` inside the container. 47 | - `-v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/`: Mounts the host's DRI drivers into the container. 48 | - `-v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock`: Shares a lock file between the host and the container. 49 | - `-v /var/run/imtl:/var/run/imtl`: Shares a MTL Manager socket between the host and the container. 50 | - `-v /dev/null:/dev/null`: Makes `/dev/null` available inside the container. 51 | - `-v /tmp/hugepages:/tmp/hugepages`: Shares the hugepages directory for memory management optimizations. 52 | - `-v /hugepages:/hugepages`: Shares another hugepages directory. 53 | - `--network=my_net_801f0`: Connects the container to the `my_net_801f0` network. 54 | - `--ip=192.168.2.2`: Assigns the IP address `192.168.2.2` to the container. 55 | - `--expose=20000-20170`: Exposes a range of ports for the container. 56 | - `--ipc=host -v /dev/shm:/dev/shm`: Shares the host's IPC namespace and mounts the shared memory directory. 57 | - `--cpuset-cpus=20-40`: Limits the container to specific CPUs on the host machine. 58 | - `video_production_image`: Specifies the Docker image to be used for the container. 59 | -------------------------------------------------------------------------------- /docs/sphinx/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | # Copyright 2024 Intel Corporation 4 | # Intel® Tiber™ Broadcast Suite 5 | 6 | # Minimal makefile for Sphinx documentation 7 | 8 | SPHINXOPTS ?= --conf-dir . 9 | SPHINXBUILD ?= sphinx-build 10 | SOURCEDIR = ../../ 11 | BUILDDIR = ../_build 12 | 13 | help: 14 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 15 | 16 | .PHONY: help Makefile 17 | 18 | # Catch-all target: route all unknown targets to Sphinx using the new 19 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 20 | %: Makefile 21 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 22 | -------------------------------------------------------------------------------- /docs/sphinx/build_docs.md: -------------------------------------------------------------------------------- 1 | # Build documentation guide 2 | 3 | ## 1. Prerequisites 4 | 5 | ```bash 6 | apt install make python3 python3-pip python3-sphinx 7 | ``` 8 | ```bash 9 | python -m pip install sphinx_book_theme myst_parser sphinxcontrib.mermaid sphinx-copybutton 10 | ``` 11 | 12 | ## 2. Build documentation (html) 13 | 14 | ```bash 15 | cd {project_dir}/docs/sphinx 16 | ``` 17 | ```bash 18 | make html 19 | ``` 20 | 21 | ## 3. Open built documentation (html) 22 | 23 | ```bash 24 | cd {project_dir}/docs/_build/html 25 | ``` 26 | 27 | Open index.html via web browser 28 | 29 | ### 3.1. Alternative run nginx server 30 | 31 | ```bash 32 | docker run -it --rm -d -p 8080:80 --name web -v ./docs/_build/html:/usr/share/nginx/html nginx 33 | ``` 34 | 35 | Open index.html via web browser using `http://:8080/` or using local address `http://127.0.0.1:8080/` 36 | -------------------------------------------------------------------------------- /docs/sphinx/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | # Copyright 2024 Intel Corporation 5 | # Intel® Tiber™ Broadcast Suite 6 | 7 | # Sphinx documentation build configuration file 8 | 9 | # General configuration --------------------------------------------------- 10 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 11 | 12 | from __future__ import annotations 13 | 14 | import os 15 | import sys 16 | 17 | 18 | def git_describe_tag(): 19 | try: 20 | return os.popen('git describe --tags').read().strip() 21 | except Exception as e: 22 | print(f"Error getting git tag: {e}") 23 | return "" 24 | 25 | 26 | project = 'Intel® Tiber™ Broadcast Suite' 27 | copyright = '2024, Intel Corporation' 28 | author = 'Intel Corporation' 29 | release = git_describe_tag() 30 | 31 | extensions = [ 32 | 'myst_parser', 33 | # 'sphinx.ext.autodoc', 34 | # 'sphinx.ext.doctest', 35 | # 'sphinx.ext.todo', 36 | # 'sphinx.ext.autosummary', 37 | # 'sphinx.ext.extlinks', 38 | # 'sphinx.ext.intersphinx', 39 | # 'sphinx.ext.viewcode', 40 | # 'sphinx.ext.inheritance_diagram', 41 | # 'sphinx.ext.coverage', 42 | 'sphinx.ext.graphviz', 43 | 'sphinxcontrib.mermaid', 44 | 'sphinx_copybutton' 45 | ] 46 | 47 | coverage_statistics_to_report = coverage_statistics_to_stdout = True 48 | 49 | inline_highlight_respect_highlight = False 50 | inline_highlight_literals = False 51 | 52 | templates_path = ['_templates'] 53 | exclude_patterns = ['_build/*', 'tests/*', 'patches/*', 'Thumbs.db', '.DS_Store'] 54 | 55 | # -- Options for HTML output ------------------------------------------------- 56 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 57 | 58 | html_theme = 'sphinx_book_theme' 59 | html_static_path = ['../images'] 60 | language = "en_US" 61 | 62 | # Options for myst_html_meta output ------------------------------------------------- 63 | 64 | myst_html_meta = { 65 | "description lang=en": "Intel® Tiber™ Broadcast Suite", 66 | "keywords": "Intel®, Intel, Tiber™, Tiber, st20, st22", 67 | "property=og:locale": "en_US" 68 | } 69 | myst_enable_extensions = [ "strikethrough" ] 70 | myst_fence_as_directive = [ "mermaid" ] 71 | 72 | suppress_warnings = ["myst.xref_missing", "myst.strikethrough"] 73 | 74 | source_suffix = { 75 | '.rst': 'restructuredtext', 76 | '.txt': 'restructuredtext', 77 | '.md': 'markdown', 78 | } 79 | 80 | sys.path.insert(0, os.path.abspath('..')) 81 | sys.path.insert(0, os.path.abspath('../../')) 82 | -------------------------------------------------------------------------------- /docs/sphinx/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | @REM SPDX-License-Identifier: BSD-3-Clause 4 | @REM Copyright 2024 Intel Corporation 5 | @REM Intel® Tiber™ Broadcast Suite 6 | @REM # https://www.sphinx-doc.org/ 7 | 8 | pushd %~dp0 9 | 10 | REM Command file for Sphinx documentation 11 | 12 | if "%SPHINXBUILD%" == "" ( 13 | set SPHINXBUILD=sphinx-build 14 | set SPHINXOPTS="--conf-dir ." 15 | ) 16 | set SOURCEDIR=../../ 17 | set BUILDDIR=../_build 18 | 19 | %SPHINXBUILD% >NUL 2>NUL 20 | if errorlevel 9009 ( 21 | echo. 22 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 23 | echo.installed, then set the SPHINXBUILD environment variable to point 24 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 25 | echo.may add the Sphinx directory to PATH. 26 | echo. 27 | echo.If you don't have Sphinx installed, grab it from 28 | echo.https://www.sphinx-doc.org/ 29 | exit /b 1 30 | ) 31 | 32 | if "%1" == "" goto help 33 | 34 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 35 | goto end 36 | 37 | :help 38 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 39 | 40 | :end 41 | popd 42 | -------------------------------------------------------------------------------- /examples/intel-node-multiviewer-4-input.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": -10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "multiviewer", 9 | "activate_senders": false, 10 | "multiviewer_columns": 2, 11 | "gpu_hw_acceleration": "intel", 12 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "192.168.2.6", 15 | "ffmpeg_grpc_server_port": "50056", 16 | "receiver_payload_type":112, 17 | "receiver": [{ 18 | "stream_payload": { 19 | "video": { 20 | "frame_width": 1920, 21 | "frame_height": 1080, 22 | "frame_rate": { "numerator": 60, "denominator": 1 }, 23 | "pixel_format": "yuv422p10le", 24 | "video_type": "rawvideo" 25 | }, 26 | "audio": { 27 | "channels": 2, 28 | "sampleRate": 48000, 29 | "format": "pcm_s24be", 30 | "packetTime": "1ms" 31 | } 32 | }, 33 | "stream_type": { 34 | "st2110" : { 35 | "transport" : "st2110-20", 36 | "payloadType" : 112, 37 | "queues_cnt": 0 38 | } 39 | } 40 | }, 41 | { 42 | "stream_payload": { 43 | "video": { 44 | "frame_width": 1920, 45 | "frame_height": 1080, 46 | "frame_rate": { "numerator": 60, "denominator": 1 }, 47 | "pixel_format": "yuv422p10le", 48 | "video_type": "rawvideo" 49 | }, 50 | "audio": { 51 | "channels": 2, 52 | "sampleRate": 48000, 53 | "format": "pcm_s24be", 54 | "packetTime": "1ms" 55 | } 56 | }, 57 | "stream_type": { 58 | "st2110" : { 59 | "transport" : "st2110-20", 60 | "payloadType" : 112, 61 | "queues_cnt": 0 62 | } 63 | } 64 | }, 65 | { 66 | "stream_payload": { 67 | "video": { 68 | "frame_width": 1920, 69 | "frame_height": 1080, 70 | "frame_rate": { "numerator": 60, "denominator": 1 }, 71 | "pixel_format": "yuv422p10le", 72 | "video_type": "rawvideo" 73 | }, 74 | "audio": { 75 | "channels": 2, 76 | "sampleRate": 48000, 77 | "format": "pcm_s24be", 78 | "packetTime": "1ms" 79 | } 80 | }, 81 | "stream_type": { 82 | "st2110" : { 83 | "transport" : "st2110-20", 84 | "payloadType" : 112, 85 | "queues_cnt": 0 86 | } 87 | } 88 | }, 89 | { 90 | "stream_payload": { 91 | "video": { 92 | "frame_width": 1920, 93 | "frame_height": 1080, 94 | "frame_rate": { "numerator": 60, "denominator": 1 }, 95 | "pixel_format": "yuv422p10le", 96 | "video_type": "rawvideo" 97 | }, 98 | "audio": { 99 | "channels": 2, 100 | "sampleRate": 48000, 101 | "format": "pcm_s24be", 102 | "packetTime": "1ms" 103 | } 104 | }, 105 | "stream_type": { 106 | "st2110" : { 107 | "transport" : "st2110-20", 108 | "payloadType" : 112, 109 | "queues_cnt": 0 110 | } 111 | } 112 | }], 113 | "sender": [{ 114 | "stream_payload": { 115 | "video": { 116 | "frame_width": 1920, 117 | "frame_height": 1080, 118 | "frame_rate": { "numerator": 60, "denominator": 1 }, 119 | "pixel_format": "yuv422p10le", 120 | "video_type": "rawvideo" 121 | }, 122 | "audio": { 123 | "channels": 2, 124 | "sampleRate": 48000, 125 | "format": "pcm_s24be", 126 | "packetTime": "1ms" 127 | } 128 | }, 129 | "stream_type": { 130 | "file": { 131 | "path": "/videos/recv", 132 | "filename": "out_4_input_multiviewer.yuv" 133 | } 134 | } 135 | }] 136 | } -------------------------------------------------------------------------------- /examples/intel-node-rx-h265-2-streams.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": [ 7 | "rx" 8 | ] 9 | }, 10 | "function": "rx", 11 | "gpu_hw_acceleration": "intel", 12 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "192.168.2.6", 15 | "ffmpeg_grpc_server_port": "50056", 16 | "sender_payload_type": 0, 17 | "sender": [ 18 | { 19 | "stream_payload": { 20 | "video": { 21 | "frame_width": 1920, 22 | "frame_height": 1080, 23 | "frame_rate": { 24 | "numerator": 50, 25 | "denominator": 1 26 | }, 27 | "pixel_format": "yuv422p10le", 28 | "video_type": "hevc_qsv", 29 | "preset": "veryfast", 30 | "profile": "main" 31 | }, 32 | "audio": { 33 | "channels": 2, 34 | "sampleRate": 48000, 35 | "format": "pcm_s24be", 36 | "packetTime": "1ms" 37 | } 38 | }, 39 | "stream_type": { 40 | "file": { 41 | "path": "/videos/recv", 42 | "filename": "out_1920x1080_yuv422p10le_1.h265" 43 | } 44 | } 45 | }, 46 | { 47 | "stream_payload": { 48 | "video": { 49 | "frame_width": 1920, 50 | "frame_height": 1080, 51 | "frame_rate": { 52 | "numerator": 50, 53 | "denominator": 1 54 | }, 55 | "pixel_format": "yuv422p10le", 56 | "video_type": "hevc_qsv", 57 | "preset": "veryfast", 58 | "profile": "main" 59 | }, 60 | "audio": { 61 | "channels": 2, 62 | "sampleRate": 48000, 63 | "format": "pcm_s24be", 64 | "packetTime": "1ms" 65 | } 66 | }, 67 | "stream_type": { 68 | "file": { 69 | "path": "/videos/recv", 70 | "filename": "out_1920x1080_yuv422p10le_2.h265" 71 | } 72 | } 73 | } 74 | ], 75 | "receiver": [ 76 | { 77 | "stream_payload": { 78 | "video": { 79 | "frame_width": 1920, 80 | "frame_height": 1080, 81 | "frame_rate": { 82 | "numerator": 50, 83 | "denominator": 1 84 | }, 85 | "pixel_format": "yuv422p10le", 86 | "video_type": "rawvideo" 87 | }, 88 | "audio": { 89 | "channels": 2, 90 | "sampleRate": 48000, 91 | "format": "pcm_s24be", 92 | "packetTime": "1ms" 93 | } 94 | }, 95 | "stream_type": { 96 | "st2110": { 97 | "transport": "st2110-20", 98 | "payloadType": 112, 99 | "queues_cnt": 2 100 | } 101 | } 102 | }, 103 | { 104 | "stream_payload": { 105 | "video": { 106 | "frame_width": 1920, 107 | "frame_height": 1080, 108 | "frame_rate": { 109 | "numerator": 50, 110 | "denominator": 1 111 | }, 112 | "pixel_format": "yuv422p10le", 113 | "video_type": "rawvideo" 114 | }, 115 | "audio": { 116 | "channels": 2, 117 | "sampleRate": 48000, 118 | "format": "pcm_s24be", 119 | "packetTime": "1ms" 120 | } 121 | }, 122 | "stream_type": { 123 | "st2110": { 124 | "transport": "st2110-20", 125 | "payloadType": 112, 126 | "queues_cnt": 2 127 | } 128 | } 129 | } 130 | ] 131 | } 132 | -------------------------------------------------------------------------------- /examples/intel-node-rx-mcm-recorder.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "recorder", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "intel", 11 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50058", 15 | "receiver_payload_type":112, 16 | "receiver": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "mcm": { 34 | "conn_type": "st2110", 35 | "transport": "st2110-20", 36 | "urn": "NULL", 37 | "transportPixelFormat": "yuv422p10rfc4175" 38 | } 39 | } 40 | }], 41 | "sender": [{ 42 | "stream_payload": { 43 | "video": { 44 | "frame_width": 1920, 45 | "frame_height": 1080, 46 | "frame_rate": { "numerator": 60, "denominator": 1 }, 47 | "pixel_format": "yuv422p10le", 48 | "video_type": "hevc_qsv" 49 | }, 50 | "audio": { 51 | "channels": 2, 52 | "sampleRate": 48000, 53 | "format": "pcm_s24be", 54 | "packetTime": "1ms" 55 | } 56 | }, 57 | "stream_type": { 58 | "file": { 59 | "path": "/videos/recv", 60 | "filename": "out_1920x1080_yuv422p10le_h265.mp4" 61 | } 62 | } 63 | }, 64 | { 65 | "stream_payload": { 66 | "video": { 67 | "frame_width": 960, 68 | "frame_height": 540, 69 | "frame_rate": { "numerator": 60, "denominator": 1 }, 70 | "pixel_format": "yuv422p10le", 71 | "video_type": "hevc_qsv" 72 | }, 73 | "audio": { 74 | "channels": 2, 75 | "sampleRate": 48000, 76 | "format": "pcm_s24be", 77 | "packetTime": "1ms" 78 | } 79 | }, 80 | "stream_type": { 81 | "file": { 82 | "path": "/videos/recv", 83 | "filename": "out_960x540_yuv422p10le_h265.mp4" 84 | } 85 | } 86 | }] 87 | } -------------------------------------------------------------------------------- /examples/intel-node-rx-mcm-upscale.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "upscale", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "intel", 11 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50058", 15 | "receiver_payload_type":112, 16 | "receiver": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "mcm": { 34 | "conn_type": "st2110", 35 | "transport": "st2110-20", 36 | "urn": "NULL", 37 | "transportPixelFormat": "yuv422p10rfc4175" 38 | } 39 | } 40 | }], 41 | "sender": [{ 42 | "stream_payload": { 43 | "video": { 44 | "frame_width": 3840, 45 | "frame_height": 2160, 46 | "frame_rate": { "numerator": 60, "denominator": 1 }, 47 | "pixel_format": "yuv422p10le", 48 | "video_type": "rawvideo" 49 | }, 50 | "audio": { 51 | "channels": 2, 52 | "sampleRate": 48000, 53 | "format": "pcm_s24be", 54 | "packetTime": "1ms" 55 | } 56 | }, 57 | "stream_type": { 58 | "file": { 59 | "path": "/videos/recv", 60 | "filename": "out_3840x2160_yuv422p10le.yuv" 61 | } 62 | } 63 | }] 64 | } -------------------------------------------------------------------------------- /examples/intel-node-rx-mcm.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "rx", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "none", 11 | "domain": "local", 12 | "ffmpeg_grpc_server_address": "localhost", 13 | "ffmpeg_grpc_server_port": "50058", 14 | "receiver_payload_type":112, 15 | "sender": [{ 16 | "stream_payload": { 17 | "video": { 18 | "frame_width": 1920, 19 | "frame_height": 1080, 20 | "frame_rate": { "numerator": 60, "denominator": 1 }, 21 | "pixel_format": "yuv422p10le", 22 | "video_type": "rawvideo" 23 | }, 24 | "audio": { 25 | "channels": 2, 26 | "sampleRate": 48000, 27 | "format": "pcm_s24be", 28 | "packetTime": "1ms" 29 | } 30 | }, 31 | "stream_type": { 32 | "file": { 33 | "path": "/videos/recv", 34 | "filename": "out_1920x1080_yuv422p10le.yuv" 35 | } 36 | } 37 | }], 38 | "receiver": [{ 39 | "stream_payload": { 40 | "video": { 41 | "frame_width": 1920, 42 | "frame_height": 1080, 43 | "frame_rate": { "numerator": 60, "denominator": 1 }, 44 | "pixel_format": "yuv422p10le", 45 | "video_type": "rawvideo" 46 | }, 47 | "audio": { 48 | "channels": 2, 49 | "sampleRate": 48000, 50 | "format": "pcm_s24be", 51 | "packetTime": "1ms" 52 | } 53 | }, 54 | "stream_type": { 55 | "mcm": { 56 | "conn_type": "st2110", 57 | "transport": "st2110-20", 58 | "urn": "NULL", 59 | "transportPixelFormat": "yuv422p10rfc4175" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /examples/intel-node-rx-mtl.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": [ 7 | "rx" 8 | ] 9 | }, 10 | "function": "rx", 11 | "activate_senders": false, 12 | "gpu_hw_acceleration": "none", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "192.168.2.6", 15 | "ffmpeg_grpc_server_port": "50053", 16 | "sender_payload_type": 0, 17 | "sender": [ 18 | { 19 | "stream_payload": { 20 | "video": { 21 | "frame_width": 1920, 22 | "frame_height": 1080, 23 | "frame_rate": { 24 | "numerator": 60, 25 | "denominator": 1 26 | }, 27 | "pixel_format": "yuv422p10le", 28 | "video_type": "rawvideo" 29 | }, 30 | "audio": { 31 | "channels": 2, 32 | "sampleRate": 48000, 33 | "format": "pcm_s24be", 34 | "packetTime": "1ms" 35 | } 36 | }, 37 | "stream_type": { 38 | "file": { 39 | "path": "/videos/recv", 40 | "filename": "out_1920x1080_yuv422p10le.yuv" 41 | } 42 | } 43 | } 44 | ], 45 | "receiver": [ 46 | { 47 | "stream_payload": { 48 | "video": { 49 | "frame_width": 1920, 50 | "frame_height": 1080, 51 | "frame_rate": { 52 | "numerator": 60, 53 | "denominator": 1 54 | }, 55 | "pixel_format": "yuv422p10le", 56 | "video_type": "rawvideo" 57 | }, 58 | "audio": { 59 | "channels": 2, 60 | "sampleRate": 48000, 61 | "format": "pcm_s24be", 62 | "packetTime": "1ms" 63 | } 64 | }, 65 | "stream_type": { 66 | "st2110": { 67 | "transport": "st2110-20", 68 | "payloadType": 112, 69 | "queues_cnt": 0 70 | } 71 | } 72 | } 73 | ] 74 | } -------------------------------------------------------------------------------- /examples/intel-node-tx-h265-2-streams.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite-tx", 5 | "device_tags": { 6 | "pipeline": [ 7 | "tx" 8 | ] 9 | }, 10 | "activate_senders": false, 11 | "function": "tx", 12 | "stream_loop": 0, 13 | "gpu_hw_acceleration": "intel", 14 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 15 | "domain": "local", 16 | "ffmpeg_grpc_server_address": "192.168.2.4", 17 | "ffmpeg_grpc_server_port": "50055", 18 | "sender_payload_type": 112, 19 | "sender": [ 20 | { 21 | "stream_payload": { 22 | "video": { 23 | "frame_width": 1920, 24 | "frame_height": 1080, 25 | "frame_rate": { 26 | "numerator": 50, 27 | "denominator": 1 28 | }, 29 | "pixel_format": "y210le", 30 | "video_type": "rawvideo" 31 | }, 32 | "audio": { 33 | "channels": 2, 34 | "sampleRate": 48000, 35 | "format": "pcm_s24be", 36 | "packetTime": "1ms" 37 | } 38 | }, 39 | "stream_type": { 40 | "st2110": { 41 | "transport": "st2110-20", 42 | "payloadType": 112, 43 | "queues_cnt": 2 44 | } 45 | } 46 | }, 47 | { 48 | "stream_payload": { 49 | "video": { 50 | "frame_width": 1920, 51 | "frame_height": 1080, 52 | "frame_rate": { 53 | "numerator": 50, 54 | "denominator": 1 55 | }, 56 | "pixel_format": "y210le", 57 | "video_type": "rawvideo" 58 | }, 59 | "audio": { 60 | "channels": 2, 61 | "sampleRate": 48000, 62 | "format": "pcm_s24be", 63 | "packetTime": "1ms" 64 | } 65 | }, 66 | "stream_type": { 67 | "st2110": { 68 | "transport": "st2110-20", 69 | "payloadType": 112, 70 | "queues_cnt": 2 71 | } 72 | } 73 | } 74 | ], 75 | "receiver": [ 76 | { 77 | "stream_payload": { 78 | "video": { 79 | "frame_width": 1920, 80 | "frame_height": 1080, 81 | "frame_rate": { 82 | "numerator": 50, 83 | "denominator": 1 84 | }, 85 | "pixel_format": "", 86 | "video_type": "hevc_qsv", 87 | "preset": "veryfast", 88 | "profile": "main" 89 | }, 90 | "audio": { 91 | "channels": 2, 92 | "sampleRate": 48000, 93 | "format": "pcm_s24be", 94 | "packetTime": "1ms" 95 | } 96 | }, 97 | "stream_type": { 98 | "file": { 99 | "path": "/videos", 100 | "filename": "in_1920x1080_yuv422p10le_h265.h265" 101 | } 102 | } 103 | }, 104 | { 105 | "stream_payload": { 106 | "video": { 107 | "frame_width": 1920, 108 | "frame_height": 1080, 109 | "frame_rate": { 110 | "numerator": 50, 111 | "denominator": 1 112 | }, 113 | "pixel_format": "", 114 | "video_type": "hevc_qsv", 115 | "preset": "veryfast", 116 | "profile": "main" 117 | }, 118 | "audio": { 119 | "channels": 2, 120 | "sampleRate": 48000, 121 | "format": "pcm_s24be", 122 | "packetTime": "1ms" 123 | } 124 | }, 125 | "stream_type": { 126 | "file": { 127 | "path": "/videos", 128 | "filename": "in_1920x1080_yuv422p10le_h265.h265" 129 | } 130 | } 131 | } 132 | ] 133 | } 134 | -------------------------------------------------------------------------------- /examples/intel-node-tx-mcm-upscale.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "upscale", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "intel", 11 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50057", 15 | "sender_payload_type":112, 16 | "sender": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 3840, 20 | "frame_height": 2160, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "mcm": { 34 | "conn_type": "st2110", 35 | "transport": "st2110-20", 36 | "urn": "NULL", 37 | "transportPixelFormat": "yuv422p10rfc4175" 38 | } 39 | } 40 | }], 41 | "receiver": [{ 42 | "stream_payload": { 43 | "video": { 44 | "frame_width": 1920, 45 | "frame_height": 1080, 46 | "frame_rate": { "numerator": 60, "denominator": 1 }, 47 | "pixel_format": "yuv422p10le", 48 | "video_type": "rawvideo" 49 | }, 50 | "audio": { 51 | "channels": 2, 52 | "sampleRate": 48000, 53 | "format": "pcm_s24be", 54 | "packetTime": "1ms" 55 | } 56 | }, 57 | "stream_type": { 58 | "file": { 59 | "path": "/videos", 60 | "filename": "in_1920x1080_yuv422p10le.yuv" 61 | } 62 | } 63 | }] 64 | } -------------------------------------------------------------------------------- /examples/intel-node-tx-mcm.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "none", 11 | "domain": "local", 12 | "ffmpeg_grpc_server_address": "localhost", 13 | "ffmpeg_grpc_server_port": "50057", 14 | "sender_payload_type":112, 15 | "sender": [{ 16 | "stream_payload": { 17 | "video": { 18 | "frame_width": 1920, 19 | "frame_height": 1080, 20 | "frame_rate": { "numerator": 60, "denominator": 1 }, 21 | "pixel_format": "yuv422p10le", 22 | "video_type": "rawvideo" 23 | }, 24 | "audio": { 25 | "channels": 2, 26 | "sampleRate": 48000, 27 | "format": "pcm_s24be", 28 | "packetTime": "1ms" 29 | } 30 | }, 31 | "stream_type": { 32 | "mcm": { 33 | "conn_type": "st2110", 34 | "transport": "st2110-20", 35 | "urn": "NULL", 36 | "transportPixelFormat": "yuv422p10rfc4175" 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "in_1920x1080_yuv422p10le.yuv" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /examples/intel-node-tx-mtl.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 5004, 4 | "label": "intel-broadcast-suite-tx", 5 | "device_tags": { 6 | "pipeline": [ 7 | "tx" 8 | ] 9 | }, 10 | "function": "tx", 11 | "activate_senders": false, 12 | "stream_loop": -1, 13 | "gpu_hw_acceleration": "none", 14 | "domain": "local", 15 | "ffmpeg_grpc_server_address": "192.168.2.4", 16 | "ffmpeg_grpc_server_port": "50051", 17 | "sender_payload_type": 112, 18 | "sender": [ 19 | { 20 | "stream_payload": { 21 | "video": { 22 | "frame_width": 1920, 23 | "frame_height": 1080, 24 | "frame_rate": { 25 | "numerator": 60, 26 | "denominator": 1 27 | }, 28 | "pixel_format": "yuv422p10le", 29 | "video_type": "rawvideo" 30 | }, 31 | "audio": { 32 | "channels": 2, 33 | "sampleRate": 48000, 34 | "format": "pcm_s24be", 35 | "packetTime": "1ms" 36 | } 37 | }, 38 | "stream_type": { 39 | "st2110": { 40 | "transport": "st2110-20", 41 | "payloadType": 112, 42 | "queues_cnt": 0 43 | } 44 | } 45 | } 46 | ], 47 | "receiver": [ 48 | { 49 | "stream_payload": { 50 | "video": { 51 | "frame_width": 1920, 52 | "frame_height": 1080, 53 | "frame_rate": { 54 | "numerator": 60, 55 | "denominator": 1 56 | }, 57 | "pixel_format": "yuv422p10le", 58 | "video_type": "rawvideo" 59 | }, 60 | "audio": { 61 | "channels": 2, 62 | "sampleRate": 48000, 63 | "format": "pcm_s24be", 64 | "packetTime": "1ms" 65 | } 66 | }, 67 | "stream_type": { 68 | "file": { 69 | "path": "/videos", 70 | "filename": "in_1920x1080_yuv422p10le.yuv" 71 | } 72 | } 73 | } 74 | ] 75 | } -------------------------------------------------------------------------------- /examples/run.md: -------------------------------------------------------------------------------- 1 | # Pipelines guide 2 | Here is a quick guide on how to run sample Intel® Tiber™ Broadcast Suite 3 | pipelines. 4 | - [Run guide](../docs/run.md) 5 | 6 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | .. Intel® Tiber™ Broadcast Suite documentation master file, created by 2 | sphinx-quickstart 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. # Intel® Tiber™ Broadcast Suite 1.0.0 5 | 6 | SPDX-License-Identifier: BSD-3-Clause 7 | Copyright(©) 2024 Intel Corporation 8 | Intel® Tiber™ Broadcast Suite 9 | 10 | 11 | Intel® Tiber™ Broadcast Suite documentation 12 | ====================================================== 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | Introduction 18 | 19 | Contents 20 | -------- 21 | 22 | .. toctree:: 23 | :maxdepth: 2 24 | :caption: Contents: 25 | 26 | docs/architecture 27 | docs/host 28 | docs/build 29 | docs/run 30 | 31 | Plugins 32 | -------- 33 | 34 | .. toctree:: 35 | :maxdepth: 2 36 | :caption: Plugins: 37 | 38 | docs/plugins/media-communications-mesh 39 | docs/plugins/media-transport-library 40 | docs/plugins/svt-jpeg-xs 41 | docs/plugins/video-super-resolution 42 | 43 | 44 | Know-How 45 | -------- 46 | 47 | .. toctree:: 48 | :maxdepth: 2 49 | :caption: Know-How: 50 | 51 | docs/building-commands 52 | docs/run-know-how 53 | Documentation Build 54 | CONTRIBUTING 55 | CODE_OF_CONDUCT 56 | 57 | Security 58 | -------- 59 | 60 | .. toctree:: 61 | :maxdepth: 2 62 | :caption: Security: 63 | 64 | docs/components/os-components-scans 65 | docs/components/libraries-scans 66 | Security 67 | 68 | Other 69 | -------- 70 | 71 | .. toctree:: 72 | :maxdepth: 2 73 | :caption: Other: 74 | 75 | License 76 | Third Party License 77 | Third Party License Links 78 | Changelog 79 | -------------------------------------------------------------------------------- /kahawai.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | { 4 | "enabled": 0, 5 | "name": "intopix_jpegxs_cpu", 6 | "path": "/usr/local/lib/x86_64-linux-gnu/libst_plugin_intopix_cpu.so" 7 | }, 8 | { 9 | "enabled": 0, 10 | "name": "st22_ffmpeg", 11 | "path": "/usr/local/lib/x86_64-linux-gnu/libst_plugin_st22_ffmpeg.so" 12 | }, 13 | { 14 | "enabled": 0, 15 | "name": "st22_ffmpeg", 16 | "path": "/usr/local/lib64/libst_plugin_st22_ffmpeg.so" 17 | }, 18 | { 19 | "enabled": 0, 20 | "name": "st22_sample", 21 | "path": "/usr/local/lib/x86_64-linux-gnu/libst_plugin_st22_sample.so" 22 | }, 23 | { 24 | "enabled": 0, 25 | "name": "st22_sample", 26 | "path": "/usr/local/lib64/libst_plugin_st22_sample.so" 27 | }, 28 | { 29 | "enabled": 0, 30 | "name": "convert_sample", 31 | "path": "/usr/local/lib/x86_64-linux-gnu/libst_plugin_convert_sample.so" 32 | }, 33 | { 34 | "enabled": 0, 35 | "name": "convert_sample", 36 | "path": "/usr/local/lib64/libst_plugin_convert_sample.so" 37 | }, 38 | { 39 | "enabled": 1, 40 | "name": "st22_svt_jpeg_xs", 41 | "path": "/usr/local/lib/x86_64-linux-gnu/libst_plugin_st22_svt_jpeg_xs.so" 42 | }, 43 | { 44 | "enabled": 1, 45 | "name": "st22_svt_jpeg_xs", 46 | "path": "/usr/local/lib64/libst_plugin_st22_svt_jpeg_xs.so" 47 | } 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /launcher/.dockerignore: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 8 | # Ignore build and test binaries. 9 | bin/ 10 | -------------------------------------------------------------------------------- /launcher/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.exe~ 10 | *.dll 11 | *.so 12 | *.dylib 13 | bin/* 14 | Dockerfile.cross 15 | 16 | # Test binary, built with `go test -c` 17 | *.test 18 | 19 | # Output of the go coverage tool, specifically when used with LiteIDE 20 | *.out 21 | 22 | # Go workspace file 23 | go.work 24 | 25 | # Kubernetes Generated files - skip generated files, except for vendored files 26 | !vendor/**/zz_generated.* 27 | 28 | # editor and IDE paraphernalia 29 | .idea 30 | .vscode 31 | *.swp 32 | *.swo 33 | *~ 34 | -------------------------------------------------------------------------------- /launcher/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2024. 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # Unless required by applicable law or agreed to in writing, software 7 | # distributed under the License is distributed on an "AS IS" BASIS, 8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9 | # See the License for the specific language governing permissions and 10 | # limitations under the License. 11 | 12 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 13 | # 14 | # SPDX-License-Identifier: BSD-3-Clause 15 | 16 | # Build the manager binary 17 | FROM golang:1.23@sha256:ec5612bbd9e96d5b80a8b968cea06a4a9b985fe200ff6da784bf607063273c59 AS builder 18 | ARG TARGETOS 19 | ARG TARGETARCH 20 | 21 | WORKDIR /workspace 22 | # Copy the Go Modules manifests 23 | COPY go.mod go.mod 24 | COPY go.sum go.sum 25 | RUN go mod download 26 | 27 | # Copy the go source 28 | COPY cmd/main.go cmd/main.go 29 | COPY api/ api/ 30 | COPY internal/ internal/ 31 | COPY resources_library/ resources_library/ 32 | 33 | # Build 34 | # the GOARCH has not a default value to allow the binary be built according to the host where the command 35 | # was called. 36 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go 37 | 38 | # # Use distroless as minimal base image to package the manager binary 39 | # # Refer to https://github.com/GoogleContainerTools/distroless for more details 40 | FROM gcr.io/distroless/static:nonroot@sha256:c0f429e16b13e583da7e5a6ec20dd656d325d88e6819cafe0adb0828976529dc 41 | WORKDIR / 42 | COPY --from=builder /workspace/manager . 43 | USER 65532:65532 44 | 45 | HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ 46 | CMD [ "sh", "-c", "curl -f http://localhost:8081/healthz || exit 1" ] 47 | 48 | ENTRYPOINT ["/manager"] 49 | -------------------------------------------------------------------------------- /launcher/PROJECT: -------------------------------------------------------------------------------- 1 | # Copyright 2024. 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # Unless required by applicable law or agreed to in writing, software 7 | # distributed under the License is distributed on an "AS IS" BASIS, 8 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9 | # See the License for the specific language governing permissions and 10 | # limitations under the License. 11 | 12 | 13 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 14 | # 15 | # SPDX-License-Identifier: BSD-3-Clause 16 | 17 | domain: bcs.intel 18 | layout: 19 | - go.kubebuilder.io/v4 20 | plugins: 21 | manifests.sdk.operatorframework.io/v2: {} 22 | scorecard.sdk.operatorframework.io/v2: {} 23 | projectName: bcs-launcher 24 | repo: bcs.pod.launcher.intel 25 | resources: 26 | - api: 27 | crdVersion: v1 28 | namespaced: true 29 | controller: true 30 | domain: bcs.intel 31 | group: bcs 32 | kind: BcsConfig 33 | path: bcs.pod.launcher.intel/api/v1 34 | version: v1 35 | version: "3" 36 | -------------------------------------------------------------------------------- /launcher/api/v1/bcsconfig_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 19 | * 20 | * SPDX-License-Identifier: BSD-3-Clause 21 | */ 22 | 23 | package v1 24 | 25 | import ( 26 | "bcs.pod.launcher.intel/resources_library/resources/bcs" 27 | "bcs.pod.launcher.intel/resources_library/resources/nmos" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | ) 30 | 31 | type BcsConfigSpec struct { 32 | Name string `json:"name"` 33 | Namespace string `json:"namespace"` 34 | App App `json:"app"` 35 | Nmos Nmos `json:"nmos"` 36 | ScheduleOnNode []string `json:"scheduleOnNode,omitempty"` 37 | DoNotScheduleOnNode []string `json:"doNotScheduleOnNode,omitempty"` 38 | } 39 | 40 | type App struct { 41 | Image string `json:"image"` 42 | GrpcPort int `json:"grpcPort"` 43 | EnvironmentVariables []EnvVar `json:"environmentVariables"` 44 | Volumes map[string]string `json:"volumes"` 45 | Resources bcs.HwResources `json:"resources,omitempty"` 46 | } 47 | 48 | type EnvVar struct { 49 | Name string `json:"name"` 50 | Value string `json:"value"` 51 | } 52 | 53 | type Nmos struct { 54 | Image string `json:"image"` 55 | Args []string `json:"args"` 56 | EnvironmentVariables []EnvVar `json:"environmentVariables"` 57 | NmosApiNodePort int `json:"nmosApiNodePort"` 58 | NmosInputFile nmos.Config `json:"nmosInputFile"` 59 | Resources bcs.HwResources `json:"resources,omitempty"` 60 | } 61 | 62 | // BcsConfigStatus defines the observed state of BcsConfig 63 | type BcsConfigStatus struct { 64 | } 65 | 66 | //+kubebuilder:object:root=true 67 | //+kubebuilder:subresource:status 68 | 69 | // BcsConfig is the Schema for the bcsconfigs API 70 | type BcsConfig struct { 71 | metav1.TypeMeta `json:",inline"` 72 | metav1.ObjectMeta `json:"metadata,omitempty"` 73 | 74 | Spec []BcsConfigSpec `json:"spec,omitempty"` 75 | Status BcsConfigStatus `json:"status,omitempty"` 76 | } 77 | 78 | //+kubebuilder:object:root=true 79 | 80 | // BcsConfigList contains a list of BcsConfig 81 | type BcsConfigList struct { 82 | metav1.TypeMeta `json:",inline"` 83 | metav1.ListMeta `json:"metadata,omitempty"` 84 | Items []BcsConfig `json:"items"` 85 | } 86 | 87 | func init() { 88 | SchemeBuilder.Register(&BcsConfig{}, &BcsConfigList{}) 89 | } 90 | -------------------------------------------------------------------------------- /launcher/api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 19 | * 20 | * SPDX-License-Identifier: BSD-3-Clause 21 | */ 22 | 23 | // Package v1 contains API Schema definitions for the bcs v1 API group 24 | // +kubebuilder:object:generate=true 25 | // +groupName=bcs.bcs.intel 26 | package v1 27 | 28 | import ( 29 | "k8s.io/apimachinery/pkg/runtime/schema" 30 | "sigs.k8s.io/controller-runtime/pkg/scheme" 31 | ) 32 | 33 | var ( 34 | // GroupVersion is group version used to register these objects 35 | GroupVersion = schema.GroupVersion{Group: "bcs.bcs.intel", Version: "v1"} 36 | 37 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 38 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 39 | 40 | // AddToScheme adds the types in this group-version to the given scheme. 41 | AddToScheme = SchemeBuilder.AddToScheme 42 | ) 43 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcsconfig-k8s-custom-resource-example.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | apiVersion: bcs.bcs.intel/v1 8 | kind: BcsConfig 9 | metadata: 10 | labels: 11 | app.kubernetes.io/name: bcs-launcher 12 | name: bcsconfig-sample 13 | namespace: bcs 14 | spec: 15 | - name: tiber-broadcast-suite 16 | namespace: bcs 17 | app: 18 | image: video_production_image:latest 19 | grpcPort: 50051 20 | resources: 21 | requests: 22 | cpu: "500m" 23 | memory: "256Mi" 24 | hugepages-1Gi: "1Ki" 25 | hugepages-2Mi: "2Ki" 26 | limits: 27 | cpu: "1000m" 28 | memory: "512Mi" 29 | hugepages-1Gi: "1Mi" 30 | hugepages-2Mi: "2Mi" 31 | environmentVariables: 32 | - name: "http_proxy" 33 | value: "" 34 | - name: "https_proxy" 35 | value: "" 36 | volumes: 37 | videos: /root/demo 38 | dri: /usr/lib/x86_64-linux-gnu/dri 39 | kahawaiLock: /tmp/kahawai_lcore.lock 40 | devNull: /dev/null 41 | imtl: /var/run/imtl 42 | shm: /dev/shm 43 | vfio: /dev/vfio 44 | dri-dev: /dev/dri 45 | nmos: 46 | image: tiber-broadcast-suite-nmos-node:latest 47 | args: ["config/config.json"] 48 | environmentVariables: 49 | - name: "http_proxy" 50 | value: "" 51 | - name: "https_proxy" 52 | value: "" 53 | - name: "VFIO_PORT_TX" 54 | value: "0000:ca:11.0" 55 | nmosApiNodePort: 30084 #node port for nmosInputFile.http_port 56 | resources: 57 | requests: 58 | cpu: "500m" 59 | memory: "256Mi" 60 | hugepages-1Gi: "1Ki" 61 | hugepages-2Mi: "2Ki" 62 | limits: 63 | cpu: "1000m" 64 | memory: "512Mi" 65 | hugepages-1Gi: "1Mi" 66 | hugepages-2Mi: "2Mi" 67 | nmosInputFile: 68 | logging_level: 10 69 | http_port: 5004 70 | label: intel-broadcast-suite-tx 71 | device_tags: 72 | pipeline: 73 | - tx 74 | function: tx 75 | activate_senders: false 76 | stream_loop: -1 77 | gpu_hw_acceleration: none 78 | domain: local 79 | sender_payload_type: 112 80 | sender: 81 | - stream_payload: 82 | video: 83 | frame_width: 1920 84 | frame_height: 1080 85 | frame_rate: 86 | numerator: 60 87 | denominator: 1 88 | pixel_format: yuv422p10le 89 | video_type: rawvideo 90 | audio: 91 | channels: 2 92 | sampleRate: 48000 93 | format: pcm_s24be 94 | packetTime: 1ms 95 | stream_type: 96 | st2110: 97 | transport: st2110-20 98 | payloadType: 112 99 | queues_cnt: 0 100 | receiver: 101 | - stream_payload: 102 | video: 103 | frame_width: 1920 104 | frame_height: 1080 105 | frame_rate: 106 | numerator: 60 107 | denominator: 1 108 | pixel_format: yuv422p10le 109 | video_type: rawvideo 110 | audio: 111 | channels: 2 112 | sampleRate: 48000 113 | format: pcm_s24be 114 | packetTime: 1ms 115 | stream_type: 116 | file: 117 | path: /videos 118 | filename: 1920x1080p10le_0.yuv 119 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcslauncher-k8s-config-map.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | apiVersion: v1 8 | kind: ConfigMap 9 | metadata: 10 | name: k8s-bcs-config 11 | namespace: bcs 12 | data: 13 | config.yaml: | 14 | k8s: true 15 | definition: 16 | meshAgent: 17 | image: "mcm/mesh-agent:latest" 18 | restPort: 8100 19 | grpcPort: 50051 20 | requests: 21 | cpu: "500m" 22 | memory: "256Mi" 23 | limits: 24 | cpu: "1000m" 25 | memory: "512Mi" 26 | scheduleOnNode: ["node-role.kubernetes.io/worker=true"] 27 | mediaProxy: 28 | image: mcm/media-proxy:latest 29 | command: ["media-proxy"] 30 | args: ["-d", "0000:ca:11.0", "-i", $(POD_IP)] 31 | grpcPort: 8001 32 | sdkPort: 8002 33 | requests: 34 | cpu: "2" 35 | memory: "8Gi" 36 | hugepages-1Gi: "1Gi" 37 | hugepages-2Mi: "2Gi" 38 | limits: 39 | cpu: "2" 40 | memory: "8Gi" 41 | hugepages-1Gi: "1Gi" 42 | hugepages-2Mi: "2Gi" 43 | volumes: 44 | memif: /tmp/mcm/memif 45 | vfio: /dev/vfio 46 | cache-size: 4Gi 47 | pvHostPath: /var/run/imtl 48 | pvStorageClass: manual 49 | pvStorage: 1Gi 50 | pvcAssignedName: mtl-pvc 51 | pvcStorage: 1Gi 52 | scheduleOnNode: ["node-role.kubernetes.io/worker=true"] 53 | mtlManager: 54 | image: mtl-manager:latest 55 | requests: 56 | cpu: "500m" 57 | memory: "256Mi" 58 | limits: 59 | cpu: "1000m" 60 | memory: "512Mi" 61 | volumes: 62 | imtlHostPath: /var/run/imtl 63 | bpfPath: /sys/fs/bpf 64 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcslauncher-static-config-custom-net-rx.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm MUST BE THE SAME WITHIN THE SAME NETWORK/SETUP 8 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm IS FOR ONE NODE SCENARIO ONLY 9 | k8s: false # use in both modes: k8s | docker 10 | configuration: # Configuration should be used only for docker mode 11 | runOnce: 12 | mediaProxyAgent: 13 | imageAndTag: mcm/mesh-agent:latest 14 | gRPCPort: 50081 # this is the port used by the agent 15 | restPort: 8100 16 | custom_network: # custom network = false means that the container will be run in the host docker network 17 | enable: true 18 | name: 19 | ip: 20 | mediaProxyMcm: 21 | imageAndTag: mcm/media-proxy:latest 22 | interfaceName: eth0 23 | volumes: 24 | - /dev/vfio:/dev/vfio 25 | custom_network: # custom network = false means that the container will be run in the host docker network 26 | enable: true 27 | name: 28 | ip: 29 | workloadToBeRun: 30 | - ffmpegPipeline: 31 | name: bcs-ffmpeg-pipeline-rx 32 | imageAndTag: tiber-broadcast-suite:latest 33 | gRPCPort: 50053 # this is the port used by the nmos container to communicate with ffmpeg pipeline 34 | environmentVariables: 35 | - "http_proxy=" 36 | - "https_proxy=" 37 | volumes: 38 | videos: /root #for videos 39 | dri: /usr/lib/x86_64-linux-gnu/dri 40 | kahawai: /tmp/kahawai_lcore.lock 41 | devnull: /dev/null 42 | tmpHugepages: /tmp/hugepages 43 | hugepages: /hugepages 44 | imtl: /var/run/imtl 45 | shm: /dev/shm 46 | devices: 47 | vfio: /dev/vfio 48 | dri: /dev/dri 49 | custom_network: # custom network = false means that the container will be run in the host docker network 50 | enable: true 51 | name: 52 | ip: 53 | nmosClient: 54 | name: bcs-ffmpeg-pipeline-nmos-client-rx 55 | imageAndTag: tiber-broadcast-suite-nmos-node:latest 56 | environmentVariables: 57 | - "http_proxy=" 58 | - "https_proxy=" 59 | - "VFIO_PORT_RX=0000:ca:11.1" # this is the PCI address of the vfio device - MENDATORY! 60 | nmosConfigPath: /root/path/to/intel-node-rx/json/file 61 | nmosPort: 5045 62 | nmosConfigFileName: intel-node-rx.json 63 | custom_network: # custom network = false means that the container will be run in the host docker network 64 | enable: true 65 | name: 66 | ip: 67 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcslauncher-static-config-custom-net-tx.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm MUST BE THE SAME WITHIN THE SAME NETWORK/SETUP 7 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm IS FOR ONE NODE SCENARIO ONLY 8 | k8s: false # use in both modes: k8s | docker 9 | configuration: # Configuration should be used only for docker mode 10 | runOnce: 11 | mediaProxyAgent: 12 | imageAndTag: mcm/mesh-agent:latest 13 | gRPCPort: 50081 # this is the port used by the agent 14 | restPort: 8100 15 | custom_network: # custom network = false means that the container will be run in the host docker network 16 | enable: false 17 | name: 18 | ip: 19 | mediaProxyMcm: 20 | imageAndTag: mcm/media-proxy:latest 21 | interfaceName: eth0 22 | volumes: 23 | - /dev/vfio:/dev/vfio 24 | custom_network: # custom network = false means that the container will be run in the host docker network 25 | enable: false 26 | name: 27 | ip: 28 | workloadToBeRun: 29 | - ffmpegPipeline: 30 | name: bcs-ffmpeg-pipeline-tx 31 | imageAndTag: tiber-broadcast-suite:latest 32 | gRPCPort: 50051 # this is the port used by the nmos container to communicate with ffmpeg pipeline 33 | environmentVariables: 34 | - "http_proxy=" 35 | - "https_proxy=" 36 | volumes: 37 | videos: /root #for videos 38 | dri: /usr/lib/x86_64-linux-gnu/dri 39 | kahawai: /tmp/kahawai_lcore.lock 40 | devnull: /dev/null 41 | tmpHugepages: /tmp/hugepages 42 | hugepages: /hugepages 43 | imtl: /var/run/imtl 44 | shm: /dev/shm 45 | devices: 46 | vfio: /dev/vfio 47 | dri: /dev/dri 48 | custom_network: # custom network = false means that the container will be run in the host docker network 49 | enable: true 50 | name: 51 | ip: 52 | nmosClient: 53 | name: bcs-ffmpeg-pipeline-nmos-client-tx 54 | imageAndTag: tiber-broadcast-suite-nmos-node:latest 55 | environmentVariables: 56 | - "http_proxy=" 57 | - "https_proxy=" 58 | - "VFIO_PORT_TX=0000:ca:11.0" # this is the PCI address of the vfio device - MENDATORY! 59 | nmosConfigPath: /root/path/to/intel-node-tx/json/file 60 | nmosConfigFileName: intel-node-tx.json 61 | nmosPort: 5044 62 | custom_network: # custom network = false means that the container will be run in the host docker network 63 | enable: true 64 | name: 65 | ip: 66 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcslauncher-static-config-host-net-rx.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm MUST BE THE SAME WITHIN THE SAME NETWORK/SETUP 8 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm IS FOR ONE NODE SCENARIO ONLY 9 | k8s: false # use in both modes: k8s | docker 10 | configuration: # Configuration should be used only for docker mode 11 | runOnce: 12 | mediaProxyAgent: 13 | imageAndTag: mcm/mesh-agent:latest 14 | gRPCPort: 50051 # this is the port used by the agent 15 | restPort: 8100 16 | custom_network: # custom network = false means that the container will be run in the host docker network 17 | enable: false 18 | mediaProxyMcm: 19 | imageAndTag: mcm/media-proxy:latest 20 | interfaceName: eth0 21 | volumes: 22 | - /dev/vfio:/dev/vfio 23 | custom_network: # custom network = false means that the container will be run in the host docker network 24 | enable: false 25 | workloadToBeRun: 26 | - ffmpegPipeline: 27 | name: bcs-ffmpeg-pipeline-rx 28 | imageAndTag: tiber-broadcast-suite:latest 29 | gRPCPort: 50044 # this is the port used by the nmos container to communicate with ffmpeg pipeline 30 | environmentVariables: 31 | - "http_proxy=" 32 | - "https_proxy=" 33 | volumes: 34 | videos: /root #for videos 35 | dri: /usr/lib/x86_64-linux-gnu/dri 36 | kahawai: /tmp/kahawai_lcore.lock 37 | devnull: /dev/null 38 | tmpHugepages: /tmp/hugepages 39 | hugepages: /hugepages 40 | imtl: /var/run/imtl 41 | shm: /dev/shm 42 | devices: 43 | vfio: /dev/vfio 44 | dri: /dev/dri 45 | custom_network: # custom network = false means that the container will be run in the host docker network 46 | enable: false 47 | ip: 10.123.x.x # this ip is crucial to e exposed explicitly to the nmos client. It should be the same as host IP address or localhost 48 | nmosClient: 49 | name: bcs-ffmpeg-pipeline-nmos-client-rx 50 | imageAndTag: tiber-broadcast-suite-nmos-node:latest 51 | environmentVariables: 52 | - "http_proxy=" 53 | - "https_proxy=" 54 | - "VFIO_PORT_RX=0000:ca:11.1" # this is the PCI address of the vfio device - MENDATORY! 55 | nmosConfigPath: /root/path/to/intel-node-rx/json/file 56 | nmosPort: 5044 57 | nmosConfigFileName: intel-node-rx.json 58 | custom_network: # custom network = false means that the container will be run in the host docker network 59 | enable: false 60 | -------------------------------------------------------------------------------- /launcher/configuration_files/bcslauncher-static-config-host-net-tx.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm MUST BE THE SAME WITHIN THE SAME NETWORK/SETUP 7 | # CONFIGURATION FOR mediaProxyAgent AND mediaProxyMcm IS FOR ONE NODE SCENARIO ONLY 8 | k8s: false # use in both modes: k8s | docker 9 | configuration: # Configuration should be used only for docker mode 10 | runOnce: 11 | mediaProxyAgent: 12 | imageAndTag: mcm/mesh-agent:latest 13 | gRPCPort: 50051 # this is the port used by the agent 14 | restPort: 8100 15 | custom_network: # custom network = false means that the container will be run in the host docker network 16 | enable: false 17 | mediaProxyMcm: 18 | imageAndTag: mcm/media-proxy:latest 19 | interfaceName: eth0 20 | volumes: 21 | - /dev/vfio:/dev/vfio 22 | custom_network: # custom network = false means that the container will be run in the host docker network 23 | enable: false 24 | workloadToBeRun: 25 | - ffmpegPipeline: 26 | name: bcs-ffmpeg-pipeline-tx 27 | imageAndTag: tiber-broadcast-suite:latest 28 | gRPCPort: 50088 # this is the port used by the nmos container to communicate with ffmpeg pipeline 29 | environmentVariables: 30 | - "http_proxy=" 31 | - "https_proxy=" 32 | volumes: 33 | videos: /root #for videos 34 | dri: /usr/lib/x86_64-linux-gnu/dri 35 | kahawai: /tmp/kahawai_lcore.lock 36 | devnull: /dev/null 37 | tmpHugepages: /tmp/hugepages 38 | hugepages: /hugepages 39 | imtl: /var/run/imtl 40 | shm: /dev/shm 41 | devices: 42 | vfio: /dev/vfio 43 | dri: /dev/dri 44 | custom_network: # custom network = false means that the container will be run in the host docker network 45 | enable: false 46 | ip: 10.123.x.x #this ip is crucial to be exposed explicitly to the nmos client. It should be the same as host IP address or localhost 47 | nmosClient: 48 | name: bcs-ffmpeg-pipeline-nmos-client-tx 49 | imageAndTag: tiber-broadcast-suite-nmos-node:latest 50 | environmentVariables: 51 | - "http_proxy=" 52 | - "https_proxy=" 53 | - "VFIO_PORT_TX=0000:ca:11.0" # this is the PCI address of the vfio device - MENDATORY! 54 | nmosConfigPath: /root/path/to/intel-node-tx/json/file 55 | nmosPort: 5045 # this is the port used by the nmos client to communicate with the nmos node 56 | nmosConfigFileName: intel-node-tx.json 57 | custom_network: # custom network = false means that the container will be run in the host docker network 58 | enable: false 59 | -------------------------------------------------------------------------------- /launcher/internal/controller/bcsconfig_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 19 | * 20 | * SPDX-License-Identifier: BSD-3-Clause 21 | */ 22 | 23 | package controller 24 | 25 | import ( 26 | "context" 27 | 28 | . "github.com/onsi/ginkgo/v2" 29 | . "github.com/onsi/gomega" 30 | "k8s.io/apimachinery/pkg/api/errors" 31 | "k8s.io/apimachinery/pkg/types" 32 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 33 | 34 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 35 | 36 | bcsv1 "bcs.pod.launcher.intel/api/v1" 37 | ) 38 | 39 | var _ = Describe("BcsConfig Controller", func() { 40 | Context("When reconciling a resource", func() { 41 | const resourceName = "test-resource" 42 | 43 | ctx := context.Background() 44 | 45 | typeNamespacedName := types.NamespacedName{ 46 | Name: resourceName, 47 | Namespace: "default", // TODO(user):Modify as needed 48 | } 49 | bcsconfig := &bcsv1.BcsConfig{} 50 | 51 | BeforeEach(func() { 52 | By("creating the custom resource for the Kind BcsConfig") 53 | err := k8sClient.Get(ctx, typeNamespacedName, bcsconfig) 54 | if err != nil && errors.IsNotFound(err) { 55 | resource := &bcsv1.BcsConfig{ 56 | ObjectMeta: metav1.ObjectMeta{ 57 | Name: resourceName, 58 | Namespace: "default", 59 | }, 60 | // TODO(user): Specify other spec details if needed. 61 | } 62 | Expect(k8sClient.Create(ctx, resource)).To(Succeed()) 63 | } 64 | }) 65 | 66 | AfterEach(func() { 67 | // TODO(user): Cleanup logic after each test, like removing the resource instance. 68 | resource := &bcsv1.BcsConfig{} 69 | err := k8sClient.Get(ctx, typeNamespacedName, resource) 70 | Expect(err).NotTo(HaveOccurred()) 71 | 72 | By("Cleanup the specific resource instance BcsConfig") 73 | Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) 74 | }) 75 | It("should successfully reconcile the resource", func() { 76 | By("Reconciling the created resource") 77 | controllerReconciler := &BcsConfigReconciler{ 78 | Client: k8sClient, 79 | Scheme: k8sClient.Scheme(), 80 | } 81 | 82 | _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ 83 | NamespacedName: typeNamespacedName, 84 | }) 85 | Expect(err).NotTo(HaveOccurred()) 86 | // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. 87 | // Example: If you expect a certain status condition after reconciliation, verify it here. 88 | }) 89 | }) 90 | }) 91 | -------------------------------------------------------------------------------- /launcher/internal/controller/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 19 | * 20 | * SPDX-License-Identifier: BSD-3-Clause 21 | */ 22 | 23 | package controller 24 | 25 | import ( 26 | "fmt" 27 | "path/filepath" 28 | "runtime" 29 | "testing" 30 | 31 | . "github.com/onsi/ginkgo/v2" 32 | . "github.com/onsi/gomega" 33 | 34 | "k8s.io/client-go/kubernetes/scheme" 35 | "k8s.io/client-go/rest" 36 | "sigs.k8s.io/controller-runtime/pkg/client" 37 | "sigs.k8s.io/controller-runtime/pkg/envtest" 38 | logf "sigs.k8s.io/controller-runtime/pkg/log" 39 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 40 | 41 | bcsv1 "bcs.pod.launcher.intel/api/v1" 42 | //+kubebuilder:scaffold:imports 43 | ) 44 | 45 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 46 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 47 | 48 | var cfg *rest.Config 49 | var k8sClient client.Client 50 | var testEnv *envtest.Environment 51 | 52 | func TestControllers(t *testing.T) { 53 | RegisterFailHandler(Fail) 54 | 55 | RunSpecs(t, "Controller Suite") 56 | } 57 | 58 | var _ = BeforeSuite(func() { 59 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 60 | 61 | By("bootstrapping test environment") 62 | testEnv = &envtest.Environment{ 63 | CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, 64 | ErrorIfCRDPathMissing: true, 65 | 66 | // The BinaryAssetsDirectory is only required if you want to run the tests directly 67 | // without call the makefile target test. If not informed it will look for the 68 | // default path defined in controller-runtime which is /usr/local/kubebuilder/. 69 | // Note that you must have the required binaries setup under the bin directory to perform 70 | // the tests directly. When we run make test it will be setup and used automatically. 71 | BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", 72 | fmt.Sprintf("1.29.0-%s-%s", runtime.GOOS, runtime.GOARCH)), 73 | } 74 | 75 | var err error 76 | // cfg is defined in this file globally. 77 | cfg, err = testEnv.Start() 78 | Expect(err).NotTo(HaveOccurred()) 79 | Expect(cfg).NotTo(BeNil()) 80 | 81 | err = bcsv1.AddToScheme(scheme.Scheme) 82 | Expect(err).NotTo(HaveOccurred()) 83 | 84 | //+kubebuilder:scaffold:scheme 85 | 86 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 87 | Expect(err).NotTo(HaveOccurred()) 88 | Expect(k8sClient).NotTo(BeNil()) 89 | 90 | }) 91 | 92 | var _ = AfterSuite(func() { 93 | By("tearing down the test environment") 94 | err := testEnv.Stop() 95 | Expect(err).NotTo(HaveOccurred()) 96 | }) 97 | -------------------------------------------------------------------------------- /launcher/resources_library/parser/parser.go: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | // This package is exploited SDBQ-1261 8 | package parser 9 | 10 | import ( 11 | "os" 12 | 13 | "bcs.pod.launcher.intel/resources_library/workloads" 14 | "gopkg.in/yaml.v2" 15 | ) 16 | 17 | // type WorkloadConfig struct { 18 | // FfmpegPipeline FfmpegPipelineConfig `yaml:"ffmpegPipeline"` 19 | // NmosClient NmosClientConfig `yaml:"nmosClient"` 20 | // } 21 | 22 | // type Volumes struct { 23 | // Videos string `yaml:"videos"` 24 | // Dri string `yaml:"dri"` 25 | // Kahawai string `yaml:"kahawai"` 26 | // Devnull string `yaml:"devnull"` 27 | // TmpHugepages string `yaml:"tmpHugepages,omitempty"` 28 | // Hugepages string `yaml:"hugepages,omitempty"` 29 | // Imtl string `yaml:"imtl"` 30 | // Shm string `yaml:"shm"` 31 | // } 32 | 33 | // type Devices struct { 34 | // Vfio string `yaml:"vfio"` 35 | // Dri string `yaml:"dri"` 36 | // } 37 | 38 | // type FfmpegPipelineConfig struct { 39 | // Name string `yaml:"name"` 40 | // ImageAndTag string `yaml:"imageAndTag"` 41 | // GRPCPort int `yaml:"gRPCPort"` 42 | // EnvironmentVariables []string `yaml:"environmentVariables"` 43 | // Volumes Volumes `yaml:"volumes"` 44 | // Devices Devices `yaml:"devices"` 45 | // Network NetworkConfig `yaml:"custom_network"` 46 | // } 47 | 48 | // type NmosClientConfig struct { 49 | // Name string `yaml:"name"` 50 | // ImageAndTag string `yaml:"imageAndTag"` 51 | // EnvironmentVariables []string `yaml:"environmentVariables"` 52 | // NmosConfigPath string `yaml:"nmosConfigPath"` 53 | // NmosConfigFileName string `yaml:"nmosConfigFileName"` 54 | // Network NetworkConfig `yaml:"custom_network"` 55 | // NmosPort int `yaml:"nmosPort"` 56 | // FfmpegConnectionAddress string `yaml:"ffmpegConnectionAddress"` 57 | // FfmpegConnectionPort string `yaml:"ffmpegConnectionPort"` 58 | // } 59 | 60 | // type NetworkConfig struct { 61 | // Enable bool `yaml:"enable"` 62 | // Name string `yaml:"name"` 63 | // IP string `yaml:"ip"` 64 | // } 65 | type Config struct { 66 | ModeK8s bool `yaml:"k8s"` 67 | Configuration Configuration `yaml:"configuration"` 68 | } 69 | 70 | type Configuration struct { 71 | RunOnce RunOnce `yaml:"runOnce"` 72 | WorkloadToBeRun []workloads.WorkloadConfig `yaml:"workloadToBeRun"` 73 | } 74 | 75 | type RunOnce struct { 76 | MediaProxyAgent workloads.MediaProxyAgentConfig `yaml:"mediaProxyAgent"` 77 | MediaProxyMcm workloads.MediaProxyMcmConfig `yaml:"mediaProxyMcm"` 78 | } 79 | 80 | func ParseLauncherMode(filename string) (bool, error) { 81 | data, err := os.ReadFile(filename) 82 | if err != nil { 83 | return false, err 84 | } 85 | var config Config 86 | err = yaml.Unmarshal(data, &config) 87 | if err != nil { 88 | return false, err 89 | } 90 | return config.ModeK8s, nil 91 | } 92 | 93 | func ParseLauncherConfiguration(filename string) (Configuration, error) { 94 | data, err := os.ReadFile(filename) 95 | if err != nil { 96 | return Configuration{}, err 97 | } 98 | var config Config 99 | err = yaml.Unmarshal(data, &config) 100 | if err != nil { 101 | return Configuration{}, err 102 | } 103 | return config.Configuration, nil 104 | } 105 | -------------------------------------------------------------------------------- /launcher/resources_library/resources/bcs/bcs_resources.go: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | package bcs 8 | 9 | import "bcs.pod.launcher.intel/resources_library/resources/general" 10 | 11 | type BcsApp struct { 12 | Name string 13 | Namespace string 14 | Containers general.Containers 15 | } 16 | 17 | type HwResources struct { 18 | Requests struct { 19 | CPU string `yaml:"cpu"` 20 | Memory string `yaml:"memory"` 21 | Hugepages1Gi string `yaml:"hugepages-1Gi,omitempty"` 22 | Hugepages2Mi string `yaml:"hugepages-2Mi,omitempty"` 23 | } `yaml:"requests"` 24 | Limits struct { 25 | CPU string `yaml:"cpu"` 26 | Memory string `yaml:"memory"` 27 | Hugepages1Gi string `yaml:"hugepages-1Gi,omitempty"` 28 | Hugepages2Mi string `yaml:"hugepages-2Mi,omitempty"` 29 | } `yaml:"limits"` 30 | } 31 | -------------------------------------------------------------------------------- /launcher/resources_library/resources/general/containers.go: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | package general 8 | 9 | import "bcs.pod.launcher.intel/resources_library/workloads" 10 | 11 | type Workload int 12 | type NetworkMode string 13 | 14 | const ( 15 | NetworkModeHost NetworkMode = "host" 16 | ) 17 | 18 | const ( 19 | MediaProxyAgent Workload = iota 20 | MediaProxyMCM 21 | BcsPipelineFfmpeg 22 | BcsPipelineNmosClient 23 | ) 24 | 25 | func (w Workload) String() string { 26 | return [...]string{"MediaProxyAgent", "MediaProxyMCM", "BcsPipelineFfmpeg", "BcsPipelineNmosClient"}[w] 27 | } 28 | 29 | type ContainersConfig struct { 30 | MediaProxyAgentConfig workloads.MediaProxyAgentConfig 31 | MediaProxyMcmConfig workloads.MediaProxyMcmConfig 32 | WorkloadConfig workloads.WorkloadConfig 33 | } 34 | 35 | type Containers struct { 36 | Type Workload 37 | // Configuration ContainersConfig 38 | ContainerName string 39 | Image string // image + tag 40 | Id int 41 | // Command string 42 | // ContainerName string 43 | // Ip string 44 | // ExposedPort []string // "format should be: 80/tcp" 45 | // BindingHostPort []string 46 | // NetworkMode string 47 | // Overridden string 48 | // Privileged bool 49 | // VolumeMount []string 50 | // EnviromentVariables []string 51 | // Network string 52 | // DeviceDri string 53 | // DeviceVfio string 54 | } 55 | -------------------------------------------------------------------------------- /launcher/resources_library/resources/mcm/mcm_resources.go: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | package mcm 8 | 9 | import "bcs.pod.launcher.intel/resources_library/resources/general" 10 | 11 | type McmApp struct { 12 | Name string 13 | Namespace string 14 | Containers general.Containers 15 | } 16 | -------------------------------------------------------------------------------- /launcher/resources_library/resources/nmos/nmos.go: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | 7 | package nmos 8 | 9 | type Config struct { 10 | LoggingLevel int `json:"logging_level"` 11 | HttpPort int `json:"http_port"` 12 | Label string `json:"label"` 13 | DeviceTags DeviceTags `json:"device_tags"` 14 | Function string `json:"function"` 15 | ActivateSenders bool `json:"activate_senders"` 16 | MultiviewerColumns int `json:"multiviewer_columns,omitempty"` 17 | StreamLoop int `json:"stream_loop"` 18 | GpuHwAcceleration string `json:"gpu_hw_acceleration"` 19 | GpuHwAccelerationDevice string `json:"gpu_hw_acceleration_device,omitempty"` 20 | Domain string `json:"domain"` 21 | FfmpegGrpcServerAddress string `json:"ffmpeg_grpc_server_address,omitempty"` 22 | FfmpegGrpcServerPort string `json:"ffmpeg_grpc_server_port,omitempty"` 23 | SenderPayloadType int `json:"sender_payload_type"` 24 | Sender []Sender `json:"sender"` 25 | Receiver []Receiver `json:"receiver"` 26 | } 27 | 28 | type DeviceTags struct { 29 | Pipeline []string `json:"pipeline"` 30 | } 31 | 32 | type Sender struct { 33 | StreamPayload StreamPayload `json:"stream_payload"` 34 | StreamType StreamType `json:"stream_type"` 35 | } 36 | 37 | type Receiver struct { 38 | StreamPayload StreamPayload `json:"stream_payload"` 39 | StreamType StreamType `json:"stream_type"` 40 | } 41 | 42 | type StreamPayload struct { 43 | Video Video `json:"video,omitempty"` 44 | Audio Audio `json:"audio,omitempty"` 45 | } 46 | 47 | type Video struct { 48 | FrameWidth int `json:"frame_width"` 49 | FrameHeight int `json:"frame_height"` 50 | FrameRate FrameRate `json:"frame_rate"` 51 | PixelFormat string `json:"pixel_format"` 52 | VideoType string `json:"video_type"` 53 | Preset string `json:"preset,omitempty"` 54 | Profile string `json:"profile,omitempty"` 55 | } 56 | 57 | type FrameRate struct { 58 | Numerator int `json:"numerator"` 59 | Denominator int `json:"denominator"` 60 | } 61 | 62 | type Audio struct { 63 | Channels int `json:"channels"` 64 | SampleRate int `json:"sampleRate"` 65 | Format string `json:"format"` 66 | PacketTime string `json:"packetTime"` 67 | } 68 | 69 | type StreamType struct { 70 | St2110 *St2110 `json:"st2110,omitempty"` 71 | Mcm *Mcm `json:"mcm,omitempty"` 72 | File *File `json:"file,omitempty"` 73 | } 74 | 75 | type St2110 struct { 76 | Transport string `json:"transport"` 77 | Payload_type int `json:"payloadType"` 78 | QueuesCount int `json:"queues_cnt"` 79 | } 80 | 81 | type Mcm struct { 82 | ConnType string `json:"conn_type"` 83 | Transport string `json:"transport"` 84 | Urn string `json:"urn"` 85 | TransportPixelFormat string `json:"transportPixelFormat"` 86 | } 87 | 88 | type File struct { 89 | Path string `json:"path"` 90 | Filename string `json:"filename"` 91 | } -------------------------------------------------------------------------------- /launcher/resources_library/workloads/workloads.go: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | 7 | package workloads 8 | 9 | type MediaProxyAgentConfig struct { 10 | ImageAndTag string `yaml:"imageAndTag"` 11 | GRPCPort string `yaml:"gRPCPort"` 12 | RestPort string `yaml:"restPort"` 13 | Network NetworkConfig `yaml:"custom_network"` 14 | } 15 | 16 | type MediaProxyMcmConfig struct { 17 | ImageAndTag string `yaml:"imageAndTag"` 18 | InterfaceName string `yaml:"interfaceName"` 19 | Volumes []string `yaml:"volumes"` 20 | Network NetworkConfig `yaml:"custom_network"` 21 | } 22 | 23 | type WorkloadConfig struct { 24 | FfmpegPipeline FfmpegPipelineConfig `yaml:"ffmpegPipeline"` 25 | NmosClient NmosClientConfig `yaml:"nmosClient"` 26 | } 27 | 28 | type Volumes struct { 29 | Videos string `yaml:"videos"` 30 | Dri string `yaml:"dri"` 31 | Kahawai string `yaml:"kahawai"` 32 | Devnull string `yaml:"devnull"` 33 | TmpHugepages string `yaml:"tmpHugepages,omitempty"` 34 | Hugepages string `yaml:"hugepages,omitempty"` 35 | Imtl string `yaml:"imtl"` 36 | Shm string `yaml:"shm"` 37 | } 38 | 39 | type Devices struct { 40 | Vfio string `yaml:"vfio"` 41 | Dri string `yaml:"dri"` 42 | } 43 | 44 | type FfmpegPipelineConfig struct { 45 | Name string `yaml:"name"` 46 | ImageAndTag string `yaml:"imageAndTag"` 47 | GRPCPort int `yaml:"gRPCPort"` 48 | EnvironmentVariables []string `yaml:"environmentVariables"` 49 | Volumes Volumes `yaml:"volumes"` 50 | Devices Devices `yaml:"devices"` 51 | Network NetworkConfig `yaml:"custom_network"` 52 | } 53 | 54 | type NmosClientConfig struct { 55 | Name string `yaml:"name"` 56 | ImageAndTag string `yaml:"imageAndTag"` 57 | EnvironmentVariables []string `yaml:"environmentVariables"` 58 | NmosConfigPath string `yaml:"nmosConfigPath"` 59 | NmosConfigFileName string `yaml:"nmosConfigFileName"` 60 | Network NetworkConfig `yaml:"custom_network"` 61 | NmosPort int `yaml:"nmosPort"` 62 | FfmpegConnectionAddress string `yaml:"ffmpegConnectionAddress"` 63 | FfmpegConnectionPort string `yaml:"ffmpegConnectionPort"` 64 | } 65 | 66 | type NetworkConfig struct { 67 | Enable bool `yaml:"enable"` 68 | Name string `yaml:"name,omitempty"` 69 | IP string `yaml:"ip,omitempty"` 70 | } 71 | -------------------------------------------------------------------------------- /launcher/resources_library/workloads/workloads_test.go: -------------------------------------------------------------------------------- 1 | // 2 | // SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | // 6 | 7 | package workloads 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/stretchr/testify/assert" 13 | "gopkg.in/yaml.v3" 14 | ) 15 | 16 | func TestNmosClientConfig_UnmarshalYAML(t *testing.T) { 17 | t.Run("Valid NmosClientConfig YAML", func(t *testing.T) { 18 | yamlContent := ` 19 | name: "nmos-client" 20 | imageAndTag: "nmos-client:latest" 21 | environmentVariables: 22 | - "ENV_VAR1=value1" 23 | - "ENV_VAR2=value2" 24 | nmosConfigPath: "/etc/nmos" 25 | nmosConfigFileName: "config.yaml" 26 | network: 27 | enable: true 28 | name: "nmos-network" 29 | ip: "192.168.1.100" 30 | ffmpegConnectionAddress: "192.168.1.101" 31 | ffmpegConnectionPort: "8080" 32 | ` 33 | var config NmosClientConfig 34 | err := yaml.Unmarshal([]byte(yamlContent), &config) 35 | assert.NoError(t, err) 36 | 37 | assert.Equal(t, "nmos-client", config.Name) 38 | assert.Equal(t, "nmos-client:latest", config.ImageAndTag) 39 | assert.Equal(t, []string{"ENV_VAR1=value1", "ENV_VAR2=value2"}, config.EnvironmentVariables) 40 | assert.Equal(t, "/etc/nmos", config.NmosConfigPath) 41 | assert.Equal(t, "config.yaml", config.NmosConfigFileName) 42 | assert.True(t, config.Network.Enable) 43 | assert.Equal(t, "nmos-network", config.Network.Name) 44 | assert.Equal(t, "192.168.1.100", config.Network.IP) 45 | assert.Equal(t, "192.168.1.101", config.FfmpegConnectionAddress) 46 | assert.Equal(t, "8080", config.FfmpegConnectionPort) 47 | }) 48 | 49 | t.Run("Invalid NmosClientConfig YAML", func(t *testing.T) { 50 | yamlContent := ` 51 | name: "nmos-client" 52 | imageAndTag: "nmos-client:latest" 53 | environmentVariables: "not-an-array" 54 | ` 55 | var config NmosClientConfig 56 | err := yaml.Unmarshal([]byte(yamlContent), &config) 57 | assert.Error(t, err) 58 | }) 59 | } 60 | 61 | func TestNmosClientConfig_DefaultValues(t *testing.T) { 62 | t.Run("Default values for missing fields", func(t *testing.T) { 63 | yamlContent := ` 64 | name: "nmos-client" 65 | imageAndTag: "nmos-client:latest" 66 | ` 67 | var config NmosClientConfig 68 | err := yaml.Unmarshal([]byte(yamlContent), &config) 69 | assert.NoError(t, err) 70 | 71 | assert.Equal(t, "nmos-client", config.Name) 72 | assert.Equal(t, "nmos-client:latest", config.ImageAndTag) 73 | assert.Nil(t, config.EnvironmentVariables) 74 | assert.Empty(t, config.NmosConfigPath) 75 | assert.Empty(t, config.NmosConfigFileName) 76 | assert.False(t, config.Network.Enable) 77 | assert.Empty(t, config.Network.Name) 78 | assert.Empty(t, config.Network.IP) 79 | assert.Empty(t, config.FfmpegConnectionAddress) 80 | assert.Empty(t, config.FfmpegConnectionPort) 81 | }) 82 | } 83 | -------------------------------------------------------------------------------- /launcher/test/e2e/e2e_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /* 18 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 19 | * 20 | * SPDX-License-Identifier: BSD-3-Clause 21 | */ 22 | 23 | package e2e 24 | 25 | import ( 26 | "fmt" 27 | "testing" 28 | 29 | . "github.com/onsi/ginkgo/v2" 30 | . "github.com/onsi/gomega" 31 | ) 32 | 33 | // Run e2e tests using the Ginkgo runner. 34 | func TestE2E(t *testing.T) { 35 | RegisterFailHandler(Fail) 36 | fmt.Fprintf(GinkgoWriter, "Starting bcs-launcher suite\n") 37 | RunSpecs(t, "e2e suite") 38 | } 39 | -------------------------------------------------------------------------------- /patches/README.md: -------------------------------------------------------------------------------- 1 | # Video Production Pipeline Project 2 | 3 | In this directory there are patches used internally by docker during make image. -------------------------------------------------------------------------------- /patches/ffmpeg/0002-qsv_aligned_malloc.diff: -------------------------------------------------------------------------------- 1 | From 66386a5cbf993c485116fb1b1f2d6cc41e5e6fc6 Mon Sep 17 00:00:00 2001 2 | From: Tomasz Szumski 3 | Date: Mon, 26 Aug 2024 11:53:24 +0200 4 | Subject: [PATCH 2/5] qsv_aligned_malloc 5 | 6 | --- 7 | libavutil/mem.c | 13 +++++++++---- 8 | 1 file changed, 9 insertions(+), 4 deletions(-) 9 | 10 | diff --git a/libavutil/mem.c b/libavutil/mem.c 11 | index 62163b4cb3..2b87c1f62e 100644 12 | --- a/libavutil/mem.c 13 | +++ b/libavutil/mem.c 14 | @@ -96,21 +96,26 @@ static int size_mult(size_t a, size_t b, size_t *r) 15 | void *av_malloc(size_t size) 16 | { 17 | void *ptr = NULL; 18 | + size_t alignment = ALIGN; 19 | 20 | if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed)) 21 | return NULL; 22 | 23 | +#if CONFIG_QSV 24 | + if ((size > 1024*1024) & (alignment < 4096)) 25 | + alignment = 4096; 26 | +#endif 27 | #if HAVE_POSIX_MEMALIGN 28 | if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation 29 | - if (posix_memalign(&ptr, ALIGN, size)) 30 | + if (posix_memalign(&ptr, alignment, size)) 31 | ptr = NULL; 32 | #elif HAVE_ALIGNED_MALLOC 33 | - ptr = _aligned_malloc(size, ALIGN); 34 | + ptr = _aligned_malloc(size, alignment); 35 | #elif HAVE_MEMALIGN 36 | #ifndef __DJGPP__ 37 | - ptr = memalign(ALIGN, size); 38 | + ptr = memalign(alignment, size); 39 | #else 40 | - ptr = memalign(size, ALIGN); 41 | + ptr = memalign(size, alignment); 42 | #endif 43 | /* Why 64? 44 | * Indeed, we should align it: 45 | -- 46 | 2.45.1.windows.1 47 | 48 | -------------------------------------------------------------------------------- /scripts/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if a configuration file is provided as an argument 4 | if [ "$#" -ne 1 ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | CONFIG_FILE="$1" 10 | 11 | # Check if the provided file exists 12 | if [ ! -f "$CONFIG_FILE" ]; then 13 | echo "Error: Configuration file '$CONFIG_FILE' does not exist." 14 | exit 1 15 | fi 16 | 17 | # Start the mDNSResponder service 18 | echo -e "\nStarting mDNSResponder service" 19 | /etc/init.d/mdns start 20 | 21 | # Run the bcs-nmos-node with the provided configuration file 22 | echo -e "\nRunning bcs-nmos-node with configuration: $CONFIG_FILE" 23 | cat $CONFIG_FILE 24 | ./bcs-nmos-node $CONFIG_FILE 25 | -------------------------------------------------------------------------------- /src/app/ffmpeg_pipeline_generator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #include 8 | 9 | #include "config_params.hpp" 10 | 11 | #ifndef _FFMPEG_PIPELINE_GENERATOR_H_ 12 | #define _FFMPEG_PIPELINE_GENERATOR_H_ 13 | 14 | /** 15 | * @brief Generates an FFmpeg pipeline string based on the provided configuration. 16 | * 17 | * This function takes a configuration object and constructs an FFmpeg pipeline string 18 | * that can be used to execute FFmpeg commands. The configuration object contains various 19 | * settings and parameters that dictate how the pipeline should be constructed. 20 | * 21 | * @param config The configuration object containing settings for the FFmpeg pipeline. 22 | * @param pipeline_string The string where the generated FFmpeg pipeline will be stored. 23 | * @return int Returns 0 on success, or a non-zero error code on failure. 24 | */ 25 | int ffmpeg_generate_pipeline(Config &config, std::string &pipeline_string); 26 | 27 | #endif // _FFMPEG_PIPELINE_GENERATOR_H_ 28 | -------------------------------------------------------------------------------- /src/build_local.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 4 | # 5 | #SPDX-License-Identifier: BSD-3-Clause 6 | 7 | set -eo pipefail 8 | 9 | SCRIPT_DIR="$(readlink -f "$(dirname -- "${BASH_SOURCE[0]}")")" 10 | GREEN='\033[0;32m' 11 | NC='\033[0m' 12 | NMOS_CPP_VERSION=f54971298c47a633969e9e9adac824b56fc08da7 13 | MY_INSTALL_DIR=$HOME/.local 14 | num_proc=$(nproc) 15 | 16 | # Function to display help message 17 | show_help() { 18 | echo "Usage: $0 [-ut] [--build_type ] [-h|--help]" 19 | echo "" 20 | echo "Options:" 21 | echo " -ut Build with unit tests enabled" 22 | echo " --build_type Specify the build type (e.g., Debug, Release)" 23 | echo " -h, --help Show this help message and exit" 24 | } 25 | 26 | UT_OPTION=$1 27 | BUILD_TYPE="Release" 28 | 29 | # Parse input parameters 30 | while [[ "$#" -gt 0 ]]; do 31 | case $1 in 32 | -ut) UT_OPTION="$1"; shift ;; 33 | --build_type) BUILD_TYPE="$2"; shift 2 ;; 34 | -h|--help) show_help; exit 0 ;; 35 | *) echo "Unknown parameter passed: $1"; show_help; exit 1 ;; 36 | esac 37 | done 38 | 39 | # Function to handle errors 40 | handle_error() { 41 | echo "Error: $1" 42 | exit 1 43 | } 44 | 45 | function build_grpc() { 46 | if [ ! -d "grpc" ]; then 47 | mkdir -p $MY_INSTALL_DIR 48 | git clone --recurse-submodules -b v1.58.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc 49 | mkdir -p grpc/cmake/build 50 | fi 51 | 52 | export PATH="$MY_INSTALL_DIR/bin:$PATH" 53 | cd grpc 54 | 55 | pushd cmake/build 56 | cmake -DgRPC_INSTALL=ON \ 57 | -DgRPC_BUILD_TESTS=OFF \ 58 | -DCMAKE_CXX_STANDARD=17 \ 59 | -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \ 60 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 61 | ../.. 62 | make -j"$num_proc" 63 | make install 64 | popd 65 | } 66 | 67 | function build_grpc_based_ffmpeg_app() { 68 | cd "${SCRIPT_DIR}"/gRPC || handle_error "Failed to change directory to gRPC" 69 | if [ "$UT_OPTION" == "-ut" ]; then 70 | ./compile.sh --unit_testing --build_type $BUILD_TYPE 71 | else 72 | ./compile.sh --build_type $BUILD_TYPE 73 | fi 74 | } 75 | 76 | function build_nmos_cpp_library () { 77 | cd "${SCRIPT_DIR}"/nmos 78 | 79 | if [ ! -d "nmos-cpp" ]; then 80 | curl --output - -s -k https://codeload.github.com/sony/nmos-cpp/tar.gz/${NMOS_CPP_VERSION} | tar zxvf - -C . && \ 81 | mv ./nmos-cpp-${NMOS_CPP_VERSION} ./nmos-cpp 82 | mkdir -p nmos-cpp/Development/build 83 | fi 84 | 85 | cd nmos-cpp/Development/build 86 | 87 | cmake .. -DNMOS_CPP_USE_SUPPLIED_JSON_SCHEMA_VALIDATOR=ON \ 88 | -DNMOS_CPP_USE_SUPPLIED_JWT_CPP=ON \ 89 | -DNMOS_CPP_BUILD_EXAMPLES=OFF \ 90 | -DNMOS_CPP_BUILD_TESTS=OFF \ 91 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE && \ 92 | make -j"$num_proc" && \ 93 | make install 94 | } 95 | 96 | function build_nmos_node() { 97 | cd "${SCRIPT_DIR}"/nmos/nmos-node 98 | mkdir -p build && cd build 99 | if [ "$UT_OPTION" == "-ut" ]; then 100 | cmake .. -DENABLE_UNIT_TESTS=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE 101 | else 102 | cmake .. -DENABLE_UNIT_TESTS=OFF -DCMAKE_BUILD_TYPE=$BUILD_TYPE 103 | fi 104 | make -j"$num_proc" 105 | } 106 | 107 | build_grpc 108 | build_grpc_based_ffmpeg_app 109 | build_nmos_cpp_library 110 | build_nmos_node 111 | 112 | echo 113 | echo -e ${GREEN}Build finished sucessfuly ${NC} 114 | echo -------------------------------------------------------------------------------- /src/common/FFmpeg_wrapper_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _CMD_PASS_CLIENT_H_ 8 | #define _CMD_PASS_CLIENT_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "ffmpeg_cmd_wrap.pb.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "ffmpeg_cmd_wrap.grpc.pb.h" 27 | #include "config_params.hpp" 28 | 29 | using grpc::Channel; 30 | using grpc::ClientContext; 31 | using grpc::CompletionQueue; 32 | using grpc::Status; 33 | 34 | std::vector> commitConfigs(const Config& config); 35 | 36 | class CmdPassClient { 37 | public: 38 | CmdPassClient(std::string interface, std::string port); 39 | ~CmdPassClient(); 40 | 41 | void FFmpegCmdExec(std::vector>& cmd_pairs); 42 | void WaitForAllRequests(); 43 | 44 | private: 45 | void AsyncCompleteRpc(); 46 | 47 | // Create a new call object 48 | struct AsyncClientCall { 49 | FFmpegServiceRes response; 50 | ClientContext context; 51 | Status status; 52 | std::unique_ptr> response_reader; 53 | }; 54 | 55 | std::unique_ptr stub_; 56 | CompletionQueue cq_; 57 | std::thread cq_thread_; 58 | std::atomic pending_requests_{0}; 59 | std::atomic all_tasks_completed{false}; 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/common/config_params.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #ifndef CONFIG_PARAMS_H 11 | #define CONFIG_PARAMS_H 12 | 13 | struct FrameRate { 14 | int numerator; 15 | int denominator; 16 | }; 17 | 18 | struct Video { 19 | int frame_width; 20 | int frame_height; 21 | FrameRate frame_rate; 22 | std::string pixel_format; 23 | std::string video_type; 24 | std::string preset; //optional 25 | std::string profile; //optional 26 | // in case of rawvideo then ffmpeg param = "-f rawwideo" 27 | // otherwise -c:v e.g. -c:v x264 -preset veryfast -profile main 28 | 29 | }; 30 | 31 | // Audio struct is a placeholder for future implementation 32 | struct Audio { 33 | int channels; 34 | int sample_rate; 35 | std::string format; 36 | std::string packet_time; 37 | }; 38 | 39 | struct File { 40 | std::string path; 41 | std::string filename; 42 | }; 43 | 44 | struct ST2110 { 45 | std::string network_interface; //VFIO port address 0000:00:00.0; ffmpeg param name: -p_port 46 | std::string local_ip; // ffmpeg param name: -p_sip 47 | std::string remote_ip; // ffmpeg param name: -p_rx_ip / -p_tx_ip 48 | std::string transport; 49 | int remote_port; // ffmpeg param name: -udp_port 50 | int payload_type; 51 | int queues_cnt; // ffmpeg param name: -rx_queues / -tx_queues ; 0 mean use default ffmpeg plugin value 52 | }; 53 | 54 | struct MCM { 55 | std::string conn_type; 56 | std::string transport; 57 | std::string transport_pixel_format; 58 | std::string ip; 59 | int port; 60 | std::string urn; 61 | }; 62 | 63 | enum payload_type { 64 | video = 0, 65 | audio 66 | }; 67 | 68 | struct Payload { 69 | payload_type type; 70 | Video video; 71 | Audio audio; 72 | }; 73 | 74 | enum stream_type { 75 | file = 0, 76 | st2110, 77 | mcm 78 | }; 79 | 80 | struct StreamType { 81 | stream_type type; 82 | File file; 83 | ST2110 st2110; 84 | MCM mcm; 85 | }; 86 | 87 | struct Stream { 88 | Payload payload; 89 | StreamType stream_type; 90 | }; 91 | 92 | struct Config { 93 | std::vector senders; 94 | std::vector receivers; 95 | 96 | std::string function; //multiviewer, upscale, replay, recorder, jpegxs, rx, tx 97 | int multiviewer_columns; //number of streams in a row 98 | 99 | std::string gpu_hw_acceleration; //intel, nvidia, none 100 | std::string gpu_hw_acceleration_device; // /dev/dri/renderD128 101 | 102 | int stream_loop; // number of times to loop the input stream 103 | 104 | int logging_level; 105 | }; 106 | 107 | #endif // CONFIG_PARAMS_H 108 | -------------------------------------------------------------------------------- /src/gRPC/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 2 | # 3 | #SPDX-License-Identifier: BSD-3-Clause 4 | 5 | cmake_minimum_required(VERSION 3.8) 6 | 7 | project(ffmpeg_cmd_wrap C CXX) 8 | 9 | 10 | set(CMAKE_CXX_STANDARD 20) 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") 12 | 13 | set(protobuf_MODULE_COMPATIBLE TRUE) 14 | find_package(Protobuf CONFIG REQUIRED) 15 | message(STATUS "Using protobuf ${Protobuf_VERSION}") 16 | 17 | set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) 18 | set(_REFLECTION gRPC::grpc++_reflection) 19 | 20 | if(CMAKE_CROSSCOMPILING) 21 | find_program(_PROTOBUF_PROTOC protoc) 22 | else() 23 | set(_PROTOBUF_PROTOC $) 24 | endif() 25 | 26 | # Find gRPC installation 27 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 28 | find_package(gRPC CONFIG REQUIRED) 29 | message(STATUS "Using gRPC ${gRPC_VERSION}") 30 | 31 | set(_GRPC_GRPCPP gRPC::grpc++) 32 | if(CMAKE_CROSSCOMPILING) 33 | find_program(_GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin) 34 | else() 35 | set(_GRPC_CPP_PLUGIN_EXECUTABLE $) 36 | endif() 37 | 38 | # Proto file 39 | get_filename_component(hw_proto "./ffmpeg_cmd_wrap.proto" ABSOLUTE) 40 | get_filename_component(hw_proto_path "${hw_proto}" PATH) 41 | 42 | # Generated sources 43 | set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.pb.cc") 44 | set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.pb.h") 45 | set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.grpc.pb.cc") 46 | set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/ffmpeg_cmd_wrap.grpc.pb.h") 47 | add_custom_command( 48 | OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" 49 | COMMAND ${_PROTOBUF_PROTOC} 50 | ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" 51 | --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" 52 | -I "${hw_proto_path}" 53 | --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" 54 | "${hw_proto}" 55 | DEPENDS "${hw_proto}") 56 | 57 | # Include generated *.pb.h files 58 | include_directories("${CMAKE_CURRENT_BINARY_DIR}" 59 | ../common 60 | build 61 | ../app) 62 | 63 | include(FetchContent) 64 | FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) 65 | FetchContent_MakeAvailable(json) 66 | 67 | # hw_grpc_proto 68 | add_library(hw_grpc_proto 69 | ${hw_grpc_srcs} 70 | ${hw_grpc_hdrs} 71 | ${hw_proto_srcs} 72 | ${hw_proto_hdrs}) 73 | target_link_libraries(hw_grpc_proto 74 | absl::check 75 | ${_REFLECTION} 76 | ${_GRPC_GRPCPP} 77 | ${_PROTOBUF_LIBPROTOBUF}) 78 | 79 | add_library(FFmpeg_wrapper_client FFmpeg_wrapper_client.cc) 80 | target_link_libraries(FFmpeg_wrapper_client 81 | absl::check 82 | ${_REFLECTION} 83 | ${_GRPC_GRPCPP} 84 | ${_PROTOBUF_LIBPROTOBUF} 85 | nlohmann_json::nlohmann_json) 86 | 87 | add_executable(cmd_pass_client cmd_pass_client.cc) 88 | target_link_libraries(cmd_pass_client 89 | FFmpeg_wrapper_client 90 | hw_grpc_proto 91 | absl::check 92 | absl::flags 93 | absl::flags_parse 94 | absl::log 95 | ${_REFLECTION} 96 | ${_GRPC_GRPCPP} 97 | ${_PROTOBUF_LIBPROTOBUF}) 98 | 99 | add_executable(FFmpeg_wrapper_service FFmpeg_wrapper_service.cc CmdPassImpl.cc ../app/ffmpeg_pipeline_generator.cc) 100 | target_link_libraries(FFmpeg_wrapper_service 101 | hw_grpc_proto 102 | absl::check 103 | absl::flags 104 | absl::flags_parse 105 | absl::log 106 | ${_REFLECTION} 107 | ${_GRPC_GRPCPP} 108 | ${_PROTOBUF_LIBPROTOBUF} 109 | nlohmann_json::nlohmann_json) 110 | -------------------------------------------------------------------------------- /src/gRPC/CmdPassImpl.h: -------------------------------------------------------------------------------- 1 | #ifndef CMD_PASS_IMPL_H 2 | #define CMD_PASS_IMPL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "ffmpeg_cmd_wrap.grpc.pb.h" 12 | #include "ffmpeg_cmd_wrap.pb.h" 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using grpc::Server; 21 | using grpc::ServerAsyncResponseWriter; 22 | using grpc::ServerBuilder; 23 | using grpc::ServerCompletionQueue; 24 | using grpc::ServerContext; 25 | using grpc::Status; 26 | 27 | #define FFMPEG_INVALID_COMMAND_STATUS "1" 28 | #define FFMPEG_INVALID_COMMAND_MSG std::string("Failed to execute ffmpeg command : No commands provided") 29 | 30 | #define FFMPEG_APP_EXEC_FAIL_STATUS "-1" 31 | #define FFMPEG_APP_EXEC_FAIL_MSG std::string("Failed to execute ffmpeg pipeline (popen) : ") + std::strerror(errno) 32 | 33 | #define FFMPEG_COMMAND_FAIL_STATUS "2" 34 | #define FFMPEG_COMMAND_FAIL_MSG std::string("FFmpeg command failed : ") 35 | 36 | #define FFMPEG_EXEC_OK_STATUS "0" 37 | #define FFMPEG_EXEC_OK_MSG std::string("FFmpeg command : ") + std::strerror(errno) 38 | 39 | class CmdPassImpl final { 40 | public: 41 | std::atomic stop; 42 | 43 | void Run(std::string server_address); 44 | void Shutdown(); 45 | 46 | private: 47 | class CallData { 48 | public: 49 | CallData(CmdPass::AsyncService *service, grpc::ServerCompletionQueue *cq); 50 | void Proceed(); 51 | 52 | private: 53 | CmdPass::AsyncService *service_; 54 | grpc::ServerCompletionQueue *cq_; 55 | grpc::ServerContext ctx_; 56 | ReqCmds request_; 57 | FFmpegServiceRes response_; 58 | grpc::ServerAsyncResponseWriter responder_; 59 | enum CallStatus { CREATE, PROCESS, FINISH }; 60 | CallStatus status_; 61 | }; 62 | 63 | void HandleRpcs(); 64 | 65 | std::unique_ptr cq_; 66 | CmdPass::AsyncService service_; 67 | std::unique_ptr server_; 68 | }; 69 | 70 | #endif // CMD_PASS_IMPL_H 71 | -------------------------------------------------------------------------------- /src/gRPC/FFmpeg_wrapper_service.cc: -------------------------------------------------------------------------------- 1 | #include "CmdPassImpl.h" 2 | 3 | CmdPassImpl manager; 4 | 5 | void wrapperSignalHandler(int signal) { 6 | std::cout << "[*] wrapperSignalHandler called SIG : " << signal << std::endl; 7 | manager.Shutdown(); 8 | } 9 | 10 | int main(int argc, char *argv[]) { 11 | if (argc != 3) { 12 | std::cout 13 | << "[*] FFmpeg wrapper service takes 2 arguments: interface and port" 14 | << std::endl; 15 | return 1; 16 | } 17 | 18 | std::stringstream ss; 19 | ss << argv[1] << ":" << argv[2]; 20 | 21 | std::signal(SIGTERM, wrapperSignalHandler); 22 | std::signal(SIGINT, wrapperSignalHandler); 23 | 24 | manager.Run(ss.str()); 25 | 26 | std::cout << "[*] Service exited gracefully" << std::endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/gRPC/cmd_pass_client.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #include "FFmpeg_wrapper_client.h" 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char* argv[]) { 13 | 14 | if (argc != 5) { 15 | std::cout << "client sample app requires the following arguments: 1) interface, 2) port, 3) source_ip, 4) destination_port" << std::endl; 16 | return 1; 17 | } 18 | 19 | std::string interface = argv[1];//"localhost"; 20 | std::string port = argv[2];//"50051"; 21 | std::string source_ip = argv[3]; 22 | std::string destination_port = argv[4]; 23 | 24 | // Populate the connection_info vector with the provided values 25 | std::vector> connection_info = {{"ip_addr", source_ip}, {"port", destination_port}}; 26 | 27 | CmdPassClient obj(interface, port); 28 | 29 | // Send multiple asynchronous requests 30 | obj.FFmpegCmdExec(connection_info); 31 | 32 | // Wait for all asynchronous operations to complete 33 | obj.WaitForAllRequests(); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/gRPC/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 4 | # 5 | #SPDX-License-Identifier: BSD-3-Clause 6 | 7 | COMPILE_DIR="$(readlink -f "$(dirname -- "${BASH_SOURCE[0]}")")" 8 | num_proc=$(nproc) 9 | BUILD_TYPE="Release" 10 | UNIT_TESTING=false 11 | 12 | # Parse input parameters 13 | while [[ "$#" -gt 0 ]]; do 14 | case $1 in 15 | --build_type) BUILD_TYPE="$2"; shift 2 ;; 16 | --unit_testing) UNIT_TESTING=true; shift ;; 17 | *) echo "Unknown parameter passed: $1"; exit 1 ;; 18 | esac 19 | done 20 | 21 | cmake -S "${COMPILE_DIR}" -B "${COMPILE_DIR}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE && \ 22 | make -j"$num_proc" -C "${COMPILE_DIR}/build" 23 | 24 | if [[ "$UNIT_TESTING" == true ]]; then 25 | cmake -S "${COMPILE_DIR}/unit_test" -B "${COMPILE_DIR}/unit_test/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE && \ 26 | make -j"$num_proc" -C "${COMPILE_DIR}/unit_test/build" && ctest --test-dir "${COMPILE_DIR}/unit_test/build" 27 | fi -------------------------------------------------------------------------------- /src/gRPC/config_serialize_deserialize.hpp: -------------------------------------------------------------------------------- 1 | #include "nlohmann/json.hpp" 2 | #include "config_params.hpp" 3 | #include 4 | #include 5 | 6 | #ifndef CONFIG_SERIALIZE_DESERIALIZE_H 7 | #define CONFIG_SERIALIZE_DESERIALIZE_H 8 | 9 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(FrameRate, numerator, denominator) 10 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Video, frame_width, frame_height, frame_rate, pixel_format, video_type, preset, profile) 11 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Audio, channels, sample_rate, format, packet_time) 12 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(File, path, filename) 13 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ST2110, network_interface, local_ip, remote_ip, transport, remote_port, payload_type, queues_cnt) 14 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(MCM, conn_type, transport, transport_pixel_format, ip, port, urn) 15 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Payload, type, video, audio) 16 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(StreamType, type, file, st2110, mcm) 17 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Stream, payload, stream_type) 18 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Config, senders, receivers, function, multiviewer_columns, gpu_hw_acceleration, gpu_hw_acceleration_device, logging_level, stream_loop) 19 | 20 | //TODO: move serialize_config_json and deserialize_config_json to a separate file 21 | 22 | static int serialize_config_json(const Config &input_config, std::string &output_string){ 23 | try { 24 | nlohmann::json config_json = input_config; 25 | //Dump json to string 26 | std::cout << "Starting to dump json" << std::endl; 27 | output_string = config_json.dump(); 28 | std::cout << "JSON output string: " << std::endl << output_string << std::endl; 29 | } 30 | catch (const nlohmann::json::parse_error &e) { 31 | std::cout << "JSON parse error: " << e.what() << std::endl; 32 | return 1; 33 | } 34 | catch (const nlohmann::json::type_error &e) { 35 | std::cout << "JSON type error: " << e.what() << std::endl; 36 | return 1; 37 | } 38 | catch (const std::exception &e) { 39 | std::cout << "Exception: " << e.what() << std::endl; 40 | return 1; 41 | } 42 | return 0; 43 | } 44 | 45 | static int deserialize_config_json(Config &output_config, const std::string &input_string){ 46 | try { 47 | nlohmann::json config_json = nlohmann::json::parse(input_string); 48 | std::cout << "JSON input string: " << std::endl << input_string << std::endl; 49 | // Deserialize from json to Config 50 | output_config = config_json.get(); 51 | } 52 | catch (const nlohmann::json::parse_error &e) { 53 | std::cout << "JSON parse error: " << e.what() << std::endl; 54 | return 1; 55 | } 56 | catch (const nlohmann::json::type_error &e) { 57 | std::cout << "JSON type error: " << e.what() << std::endl; 58 | return 1; 59 | } 60 | catch (const std::exception &e) { 61 | std::cout << "Exception: " << e.what() << std::endl; 62 | return 1; 63 | } 64 | return 0; 65 | } 66 | 67 | #endif //CONFIG_SERIALIZE_DESERIALIZE_H 68 | -------------------------------------------------------------------------------- /src/gRPC/ffmpeg_cmd_wrap.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | syntax = "proto3"; 8 | 9 | message CmdMsg { 10 | string cmd_key = 1; 11 | string cmd_val = 2; 12 | } 13 | 14 | message ReqCmds { 15 | repeated CmdMsg objs = 1; 16 | } 17 | 18 | message FFmpegServiceRes { 19 | int32 status = 1; 20 | string message = 2; 21 | } 22 | 23 | service CmdPass { 24 | rpc FFmpegCmdExec(ReqCmds) returns (FFmpegServiceRes) {} 25 | } 26 | -------------------------------------------------------------------------------- /src/gRPC/unit_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | 3 | # Project name 4 | project(FFmpegWrapperServiceTests) 5 | 6 | # Set C++ standard 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_CXX_STANDARD_REQUIRED True) 9 | 10 | # Add gRPC and Protocol Buffers 11 | find_package(Protobuf CONFIG REQUIRED) 12 | find_package(gRPC CONFIG REQUIRED) 13 | 14 | # Include FetchContent module 15 | include(FetchContent) 16 | 17 | # Download and install Google Test 18 | FetchContent_Declare( 19 | googletest 20 | URL https://github.com/google/googletest/archive/refs/tags/v1.15.0.tar.gz 21 | ) 22 | # For Windows: Prevent overriding the parent project's compiler/linker settings 23 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 24 | FetchContent_MakeAvailable(googletest) 25 | 26 | FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) 27 | FetchContent_MakeAvailable(json) 28 | 29 | # Ensure GoogleTest is built with C++20 30 | set_target_properties(gtest PROPERTIES CXX_STANDARD 20) 31 | set_target_properties(gtest_main PROPERTIES CXX_STANDARD 20) 32 | 33 | # Include directories 34 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 35 | include_directories(${googletest_SOURCE_DIR}/googletest/include) 36 | include_directories(${googletest_SOURCE_DIR}/googlemock/include) 37 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../build) 38 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) 39 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../app) 40 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../common) 41 | 42 | # Source files 43 | set(SOURCE_FILES 44 | ${CMAKE_CURRENT_BINARY_DIR}/../../build/ffmpeg_cmd_wrap.grpc.pb.cc 45 | ${CMAKE_CURRENT_BINARY_DIR}/../../build/ffmpeg_cmd_wrap.pb.cc 46 | ${CMAKE_CURRENT_BINARY_DIR}/../../CmdPassImpl.cc 47 | ${CMAKE_CURRENT_BINARY_DIR}/../../FFmpeg_wrapper_client.cc 48 | ${CMAKE_CURRENT_BINARY_DIR}/../../../app/ffmpeg_pipeline_generator.cc 49 | ${CMAKE_CURRENT_BINARY_DIR}/../FFmpeg_wrapper_service_UT.cc 50 | ) 51 | 52 | set(SOURCE_FILES_PIPELINE_GENERATOR 53 | ${CMAKE_CURRENT_BINARY_DIR}/../../../app/ffmpeg_pipeline_generator.cc 54 | ${CMAKE_CURRENT_BINARY_DIR}/../ffmpeg_pipeline_generator_test.cc 55 | ) 56 | 57 | # Add the executable 58 | add_executable(FFmpegWrapperServiceTests ${SOURCE_FILES}) 59 | add_executable(FFmpegPipelineGeneratorTests ${SOURCE_FILES_PIPELINE_GENERATOR}) 60 | 61 | # Link libraries 62 | target_link_libraries(FFmpegWrapperServiceTests 63 | gRPC::grpc++ 64 | protobuf::libprotobuf 65 | absl::check 66 | absl::string_view 67 | absl::log 68 | absl::flags 69 | absl::flags_parse 70 | gtest 71 | gtest_main 72 | gmock 73 | gmock_main 74 | nlohmann_json::nlohmann_json 75 | ) 76 | 77 | target_link_libraries(FFmpegPipelineGeneratorTests 78 | gtest 79 | gtest_main 80 | nlohmann_json::nlohmann_json 81 | ) 82 | 83 | # Enable testing 84 | enable_testing() 85 | 86 | # Add test 87 | add_test(NAME RunTest COMMAND FFmpegWrapperServiceTests) 88 | add_test(NAME handleEmptyArgs COMMAND FFmpegWrapperServiceTests) 89 | add_test(NAME handleInvalidArgs COMMAND FFmpegWrapperServiceTests) 90 | add_test(NAME FFmpegPipelineGeneratorTest COMMAND FFmpegPipelineGeneratorTests) 91 | -------------------------------------------------------------------------------- /src/nmos/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2024 Intel 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | NOTICE: Files: docker-compose.yaml, node.json, registry.json and UserConfig.py 16 | are inspired by the implementation in https://github.com/rhastie/easy-nmos/tree/master, 17 | licensed under Apache License, Version 2.0 18 | -------------------------------------------------------------------------------- /src/nmos/RUN-SIMPLE-PIPELINE.md: -------------------------------------------------------------------------------- 1 | # Test pipeline on baremetal 2 | > In each terminal - remove http/https proxy before running app 3 | 4 | Open 5 terminal windows: 5 | 6 | - 1. terminal 7 | Run TX (NMOS node with sender) 8 | ```bash 9 | cd /nmos/nmos-cpp/Development/build 10 | ./nmos-cpp-node ../nmos-cpp-node/node1_baremetal.json 11 | ``` 12 | 13 | - 2. terminal 14 | Run RX (NMOS node with receiver) 15 | ```bash 16 | cd /nmos/nmos-cpp/Development/build 17 | ./nmos-cpp-node ../nmos-cpp-node/node2_baremetal.json 18 | ``` 19 | 20 | - 3. terminal 21 | Run ffmpeg for TX. Port 50051 is defined in `../nmos-cpp-node/node1_baremetal.json` as `ffmpeg_grpc_server_port` 22 | ```bash 23 | cd /gRPC/build/ 24 | ./FFmpeg_wrapper_service localhost 50051 25 | ``` 26 | 27 | - 4. terminal 28 | Run ffmpeg for RX. Port 50052 is defined in `../nmos-cpp-node/node2_baremetal.json` as `ffmpeg_grpc_server_port` 29 | ```bash 30 | cd /gRPC/build/ 31 | ./FFmpeg_wrapper_service localhost 50052 32 | ``` 33 | 34 | - 5. terminal 35 | Connect sender and receiver using NMOS IS-04 and IS-05. `--receiver_port 95 --sender_port 90` are defined in `../nmos-cpp-node/node2_baremetal.json` as `http_port`. On this port NMOS node is exposed. 36 | ```bash 37 | cd /nmos/nmos-is05-controller 38 | python3 threaded-nmos-controller05.py --receiver_ip localhost --sender_ip localhost --receiver_port 95 --sender_port 90 39 | ``` 40 | -------------------------------------------------------------------------------- /src/nmos/nmos-node/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.17 FATAL_ERROR) 8 | 9 | # project name 10 | project(bcs-nmos-node) 11 | 12 | set(CMAKE_CXX_STANDARD 20) 13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread ") 14 | 15 | # Find gRPC installation 16 | # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation. 17 | set(protobuf_MODULE_COMPATIBLE TRUE) 18 | find_package(Protobuf CONFIG REQUIRED) 19 | message(STATUS "Using protobuf ${Protobuf_VERSION}") 20 | set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf) 21 | set(_REFLECTION gRPC::grpc++_reflection) 22 | find_package(gRPC CONFIG REQUIRED) 23 | message(STATUS "Using gRPC ${gRPC_VERSION}") 24 | 25 | find_package(nmos-cpp REQUIRED) 26 | find_package(websocketpp REQUIRED) 27 | 28 | # nmos-cpp-node executable 29 | set(NMOS_CPP_NODE_SOURCES 30 | node_implementation.cpp 31 | intel_config_parser.cpp 32 | ) 33 | 34 | set(NMOS_CPP_NODE_HEADERS 35 | node_implementation.h 36 | intel_config_parser.h 37 | ) 38 | 39 | include_directories( 40 | ../../common 41 | ../../gRPC/build 42 | ) 43 | 44 | link_directories(../../gRPC/build) 45 | 46 | add_library(bcs-nmos-node-lib ${NMOS_CPP_NODE_SOURCES} ${NMOS_CPP_NODE_HEADERS}) 47 | 48 | target_link_libraries( 49 | bcs-nmos-node-lib 50 | nmos-cpp::nmos-cpp 51 | FFmpeg_wrapper_client 52 | protobuf::libprotobuf 53 | hw_grpc_proto 54 | gRPC::grpc++ 55 | ) 56 | 57 | add_executable( 58 | bcs-nmos-node 59 | main.cpp 60 | ) 61 | 62 | target_link_libraries( 63 | bcs-nmos-node 64 | bcs-nmos-node-lib 65 | ) 66 | 67 | # enable or disable the unit test suite 68 | set(BUILD_TESTING ON CACHE BOOL "Build test suite application") 69 | 70 | if(BUILD_TESTING) 71 | add_subdirectory(unit_tests) 72 | endif() 73 | -------------------------------------------------------------------------------- /src/nmos/nmos-node/intel_config_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef INTEL_CONFIG_PARSER_H 8 | #define INTEL_CONFIG_PARSER_H 9 | 10 | #include 11 | #include "config_params.hpp" 12 | 13 | class ConfigManager { 14 | public: 15 | ConfigManager() = default; 16 | int parse_json_file(const std::string& file_path); 17 | void print_config() const; 18 | const Config& get_config() const; 19 | std::pair get_framerate(const Stream& stream) const; 20 | 21 | protected: 22 | Config config; 23 | Video parse_video(const web::json::value& video_data) const; 24 | Audio parse_audio(const web::json::value& audio_data) const; 25 | StreamType parse_stream_type(const web::json::value& stream_type_data) const; 26 | Stream parse_stream(const web::json::value& stream_data) const; 27 | }; 28 | 29 | #endif // INTEL_CONFIG_PARSER_H -------------------------------------------------------------------------------- /src/nmos/nmos-node/node_implementation.h: -------------------------------------------------------------------------------- 1 | #ifndef NMOS_CPP_NODE_NODE_IMPLEMENTATION_H 2 | #define NMOS_CPP_NODE_NODE_IMPLEMENTATION_H 3 | #include "intel_config_parser.h" 4 | namespace slog 5 | { 6 | class base_gate; 7 | } 8 | 9 | namespace nmos 10 | { 11 | struct node_model; 12 | 13 | namespace experimental 14 | { 15 | struct node_implementation; 16 | struct control_protocol_state; 17 | } 18 | } 19 | 20 | struct AppConnectionResources 21 | { 22 | std::vector all_receivers; 23 | std::vector all_senders; 24 | std::vector threads; 25 | }; 26 | 27 | // This is an example of how to integrate the nmos-cpp library with a device-specific underlying implementation. 28 | // It constructs and inserts a node resource and some sub-resources into the model, based on the model settings, 29 | // starts background tasks to emit regular events from the temperature event source, and then waits for shutdown. 30 | 31 | void node_implementation_thread(nmos::node_model& model, nmos::experimental::control_protocol_state& control_protocol_state, ConfigManager& config_manager, slog::base_gate& gate); 32 | 33 | // This constructs all the callbacks used to integrate the example device-specific underlying implementation 34 | // into the server instance for the NMOS Node. 35 | nmos::experimental::node_implementation make_node_implementation(nmos::node_model& model, ConfigManager& config_manager, AppConnectionResources& app_resources, slog::base_gate& gate); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/nmos/nmos-node/unit_tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation 3 | # 4 | # SPDX-License-Identifier: BSD-3-Clause 5 | # 6 | 7 | cmake_minimum_required(VERSION 3.8) 8 | 9 | # Project name 10 | project(NmosNodeTests) 11 | 12 | # Set C++ standard 13 | set(CMAKE_CXX_STANDARD 20) 14 | set(CMAKE_CXX_STANDARD_REQUIRED True) 15 | 16 | # Add gRPC and Protocol Buffers 17 | find_package(Protobuf CONFIG REQUIRED) 18 | find_package(gRPC CONFIG REQUIRED) 19 | 20 | # Include FetchContent module 21 | include(FetchContent) 22 | 23 | # Download and install Google Test 24 | FetchContent_Declare( 25 | googletest 26 | URL https://github.com/google/googletest/archive/refs/tags/v1.15.0.tar.gz 27 | ) 28 | FetchContent_MakeAvailable(googletest) 29 | 30 | # Ensure GoogleTest is built with C++20 31 | set_target_properties(gtest PROPERTIES CXX_STANDARD 20) 32 | set_target_properties(gtest_main PROPERTIES CXX_STANDARD 20) 33 | 34 | # Include directories 35 | include_directories( 36 | ${CMAKE_CURRENT_SOURCE_DIR}/../../app 37 | ${CMAKE_CURRENT_SOURCE_DIR}/../../common 38 | ${CMAKE_CURRENT_SOURCE_DIR}/.. 39 | ) 40 | 41 | # Source files 42 | set(NMOS_NODE_SOURCES 43 | ${CMAKE_CURRENT_SOURCE_DIR}/config_parser_tests.cc 44 | ) 45 | 46 | # Add the executable 47 | add_executable(NmosNodeTests ${NMOS_NODE_SOURCES}) 48 | 49 | # Link libraries 50 | target_link_libraries(NmosNodeTests 51 | gtest 52 | gtest_main 53 | bcs-nmos-node-lib 54 | ) 55 | -------------------------------------------------------------------------------- /tests/gRPC-k8s/manifests.yaml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: Copyright (c) 2025 Intel Corporation 2 | # 3 | # SPDX-License-Identifier: BSD-3-Clause 4 | 5 | apiVersion: apps/v1 6 | kind: Deployment 7 | metadata: 8 | name: ffmpeg-pipeline 9 | labels: 10 | app: ffmpeg-pipeline 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: ffmpeg-pipeline 16 | template: 17 | metadata: 18 | labels: 19 | app: ffmpeg-pipeline 20 | spec: 21 | containers: 22 | - name: ffmpeg-pipeline 23 | image: video_production_image:latest 24 | imagePullPolicy: IfNotPresent 25 | command: ["/usr/bin/FFmpeg_wrapper_service"] 26 | args: ["localhost", "50051"] 27 | ports: 28 | - containerPort: 50051 29 | securityContext: 30 | readOnlyRootFilesystem: true 31 | 32 | --- 33 | 34 | apiVersion: v1 35 | kind: Service 36 | metadata: 37 | name: ffmpeg-pipeline 38 | spec: 39 | selector: 40 | app: ffmpeg-pipeline 41 | ports: 42 | - protocol: TCP 43 | port: 50051 44 | targetPort: 50051 45 | type: ClusterIP 46 | -------------------------------------------------------------------------------- /tests/intel-node-multiviewer-h264.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "multiviewer", 9 | "activate_senders": false, 10 | "multiviewer_columns": 3, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50056", 15 | "receiver_payload_type":112, 16 | "receiver": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }, 40 | { 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "st2110" : { 58 | "transport" : "st2110-20", 59 | "payloadType" : 112, 60 | "queues_cnt": 0 61 | } 62 | } 63 | }, 64 | { 65 | "stream_payload": { 66 | "video": { 67 | "frame_width": 1920, 68 | "frame_height": 1080, 69 | "frame_rate": { "numerator": 60, "denominator": 1 }, 70 | "pixel_format": "yuv422p10le", 71 | "video_type": "rawvideo" 72 | }, 73 | "audio": { 74 | "channels": 2, 75 | "sampleRate": 48000, 76 | "format": "pcm_s24be", 77 | "packetTime": "1ms" 78 | } 79 | }, 80 | "stream_type": { 81 | "st2110" : { 82 | "transport" : "st2110-20", 83 | "payloadType" : 112, 84 | "queues_cnt": 0 85 | } 86 | } 87 | }], 88 | "sender": [{ 89 | "stream_payload": { 90 | "video": { 91 | "frame_width": 1920, 92 | "frame_height": 1080, 93 | "frame_rate": { "numerator": 60, "denominator": 1 }, 94 | "pixel_format": "yuv420p", 95 | "video_type": "h264" 96 | }, 97 | "audio": { 98 | "channels": 2, 99 | "sampleRate": 48000, 100 | "format": "pcm_s24be", 101 | "packetTime": "1ms" 102 | } 103 | }, 104 | "stream_type": { 105 | "file": { 106 | "path": "/videos/recv", 107 | "filename": "multiviewer_3.h264" 108 | } 109 | } 110 | }] 111 | } -------------------------------------------------------------------------------- /tests/intel-node-multiviewer-h265.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "multiviewer", 9 | "activate_senders": false, 10 | "multiviewer_columns": 3, 11 | "gpu_hw_acceleration": "intel", 12 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "localhost", 15 | "ffmpeg_grpc_server_port": "50056", 16 | "receiver_payload_type":112, 17 | "receiver": [{ 18 | "stream_payload": { 19 | "video": { 20 | "frame_width": 1920, 21 | "frame_height": 1080, 22 | "frame_rate": { "numerator": 60, "denominator": 1 }, 23 | "pixel_format": "yuv422p10le", 24 | "video_type": "rawvideo" 25 | }, 26 | "audio": { 27 | "channels": 2, 28 | "sampleRate": 48000, 29 | "format": "pcm_s24be", 30 | "packetTime": "1ms" 31 | } 32 | }, 33 | "stream_type": { 34 | "st2110" : { 35 | "transport" : "st2110-20", 36 | "payloadType" : 112, 37 | "queues_cnt": 0 38 | } 39 | } 40 | }, 41 | { 42 | "stream_payload": { 43 | "video": { 44 | "frame_width": 1920, 45 | "frame_height": 1080, 46 | "frame_rate": { "numerator": 60, "denominator": 1 }, 47 | "pixel_format": "yuv422p10le", 48 | "video_type": "rawvideo" 49 | }, 50 | "audio": { 51 | "channels": 2, 52 | "sampleRate": 48000, 53 | "format": "pcm_s24be", 54 | "packetTime": "1ms" 55 | } 56 | }, 57 | "stream_type": { 58 | "st2110" : { 59 | "transport" : "st2110-20", 60 | "payloadType" : 112, 61 | "queues_cnt": 0 62 | } 63 | } 64 | }, 65 | { 66 | "stream_payload": { 67 | "video": { 68 | "frame_width": 1920, 69 | "frame_height": 1080, 70 | "frame_rate": { "numerator": 60, "denominator": 1 }, 71 | "pixel_format": "yuv422p10le", 72 | "video_type": "rawvideo" 73 | }, 74 | "audio": { 75 | "channels": 2, 76 | "sampleRate": 48000, 77 | "format": "pcm_s24be", 78 | "packetTime": "1ms" 79 | } 80 | }, 81 | "stream_type": { 82 | "st2110" : { 83 | "transport" : "st2110-20", 84 | "payloadType" : 112, 85 | "queues_cnt": 0 86 | } 87 | } 88 | }], 89 | "sender": [{ 90 | "stream_payload": { 91 | "video": { 92 | "frame_width": 1920, 93 | "frame_height": 1080, 94 | "frame_rate": { "numerator": 60, "denominator": 1 }, 95 | "pixel_format": "yuv422p10le", 96 | "video_type": "hevc_qsv" 97 | }, 98 | "audio": { 99 | "channels": 2, 100 | "sampleRate": 48000, 101 | "format": "pcm_s24be", 102 | "packetTime": "1ms" 103 | } 104 | }, 105 | "stream_type": { 106 | "file": { 107 | "path": "/videos/recv", 108 | "filename": "multiviewer_3.h265" 109 | } 110 | } 111 | }] 112 | } -------------------------------------------------------------------------------- /tests/intel-node-multiviewer.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": -10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "multiviewer", 9 | "activate_senders": false, 10 | "multiviewer_columns": 3, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50056", 15 | "receiver_payload_type":112, 16 | "receiver": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }, 40 | { 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "st2110" : { 58 | "transport" : "st2110-20", 59 | "payloadType" : 112, 60 | "queues_cnt": 0 61 | } 62 | } 63 | }, 64 | { 65 | "stream_payload": { 66 | "video": { 67 | "frame_width": 1920, 68 | "frame_height": 1080, 69 | "frame_rate": { "numerator": 60, "denominator": 1 }, 70 | "pixel_format": "yuv422p10le", 71 | "video_type": "rawvideo" 72 | }, 73 | "audio": { 74 | "channels": 2, 75 | "sampleRate": 48000, 76 | "format": "pcm_s24be", 77 | "packetTime": "1ms" 78 | } 79 | }, 80 | "stream_type": { 81 | "st2110" : { 82 | "transport" : "st2110-20", 83 | "payloadType" : 112, 84 | "queues_cnt": 0 85 | } 86 | } 87 | }, 88 | { 89 | "stream_payload": { 90 | "video": { 91 | "frame_width": 1920, 92 | "frame_height": 1080, 93 | "frame_rate": { "numerator": 60, "denominator": 1 }, 94 | "pixel_format": "yuv422p10le", 95 | "video_type": "rawvideo" 96 | }, 97 | "audio": { 98 | "channels": 2, 99 | "sampleRate": 48000, 100 | "format": "pcm_s24be", 101 | "packetTime": "1ms" 102 | } 103 | }, 104 | "stream_type": { 105 | "st2110" : { 106 | "transport" : "st2110-20", 107 | "payloadType" : 112, 108 | "queues_cnt": 0 109 | } 110 | } 111 | }], 112 | "sender": [{ 113 | "stream_payload": { 114 | "video": { 115 | "frame_width": 1920, 116 | "frame_height": 1080, 117 | "frame_rate": { "numerator": 60, "denominator": 1 }, 118 | "pixel_format": "yuv422p10le", 119 | "video_type": "rawvideo" 120 | }, 121 | "audio": { 122 | "channels": 2, 123 | "sampleRate": 48000, 124 | "format": "pcm_s24be", 125 | "packetTime": "1ms" 126 | } 127 | }, 128 | "stream_type": { 129 | "file": { 130 | "path": "/videos/recv", 131 | "filename": "4_input_multiviewer.yuv" 132 | } 133 | } 134 | }] 135 | } -------------------------------------------------------------------------------- /tests/intel-node-rx-h264.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "rx", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "none", 11 | "domain": "local", 12 | "ffmpeg_grpc_server_address": "localhost", 13 | "ffmpeg_grpc_server_port": "50056", 14 | "receiver_payload_type":112, 15 | "receiver": [{ 16 | "stream_payload": { 17 | "video": { 18 | "frame_width": 1920, 19 | "frame_height": 1080, 20 | "frame_rate": { "numerator": 60, "denominator": 1 }, 21 | "pixel_format": "yuv422p10le", 22 | "video_type": "rawvideo" 23 | }, 24 | "audio": { 25 | "channels": 2, 26 | "sampleRate": 48000, 27 | "format": "pcm_s24be", 28 | "packetTime": "1ms" 29 | } 30 | }, 31 | "stream_type": { 32 | "st2110" : { 33 | "transport" : "st2110-20", 34 | "payloadType" : 112 35 | } 36 | } 37 | }], 38 | "sender": [{ 39 | "stream_payload": { 40 | "video": { 41 | "frame_width": 1920, 42 | "frame_height": 1080, 43 | "frame_rate": { "numerator": 60, "denominator": 1 }, 44 | "pixel_format": "yuv420p", 45 | "video_type": "h264", 46 | "preset": "veryfast", 47 | "profile": "main" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos/recv", 59 | "filename": "output3.h264" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-rx-h265.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "rx", 9 | "stream_loop": 0, 10 | "activate_senders": false, 11 | "gpu_hw_acceleration": "intel", 12 | "gpu_hw_acceleration_device": "/dev/dri/renderD128", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "localhost", 15 | "ffmpeg_grpc_server_port": "50056", 16 | "receiver_payload_type":112, 17 | "receiver": [{ 18 | "stream_payload": { 19 | "video": { 20 | "frame_width": 1920, 21 | "frame_height": 1080, 22 | "frame_rate": { "numerator": 60, "denominator": 1 }, 23 | "pixel_format": "yuv422p10le", 24 | "video_type": "rawvideo" 25 | }, 26 | "audio": { 27 | "channels": 2, 28 | "sampleRate": 48000, 29 | "format": "pcm_s24be", 30 | "packetTime": "1ms" 31 | } 32 | }, 33 | "stream_type": { 34 | "st2110" : { 35 | "transport" : "st2110-20", 36 | "payloadType" : 112 37 | } 38 | } 39 | }], 40 | "sender": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "hevc_qsv", 48 | "preset": "veryfast", 49 | "profile": "main" 50 | }, 51 | "audio": { 52 | "channels": 2, 53 | "sampleRate": 48000, 54 | "format": "pcm_s24be", 55 | "packetTime": "1ms" 56 | } 57 | }, 58 | "stream_type": { 59 | "file": { 60 | "path": "/videos/recv", 61 | "filename": "1920x1080p10le.h265" 62 | } 63 | } 64 | }] 65 | } -------------------------------------------------------------------------------- /tests/intel-node-rx-mcm.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["rx"] 7 | }, 8 | "function": "rx", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "none", 11 | "domain": "local", 12 | "ffmpeg_grpc_server_address": "localhost", 13 | "ffmpeg_grpc_server_port": "50058", 14 | "receiver_payload_type":112, 15 | "receiver": [{ 16 | "stream_payload": { 17 | "video": { 18 | "frame_width": 1920, 19 | "frame_height": 1080, 20 | "frame_rate": { "numerator": 60, "denominator": 1 }, 21 | "pixel_format": "yuv422p10le", 22 | "video_type": "rawvideo" 23 | }, 24 | "audio": { 25 | "channels": 2, 26 | "sampleRate": 48000, 27 | "format": "pcm_s24be", 28 | "packetTime": "1ms" 29 | } 30 | }, 31 | "stream_type": { 32 | "mcm": { 33 | "conn_type": "st2110", 34 | "transport": "st2110-20", 35 | "urn": "NULL", 36 | "transportPixelFormat": "yuv422p10rfc4175" 37 | } 38 | } 39 | }], 40 | "sender": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos/recv", 59 | "filename": "1920x1080p10le_3.yuv" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-rx.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 95, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": [ 7 | "rx" 8 | ] 9 | }, 10 | "function": "rx", 11 | "activate_senders": false, 12 | "gpu_hw_acceleration": "none", 13 | "domain": "local", 14 | "ffmpeg_grpc_server_address": "192.168.2.6", 15 | "ffmpeg_grpc_server_port": "50053", 16 | "sender_payload_type": 0, 17 | "sender": [ 18 | { 19 | "stream_payload": { 20 | "video": { 21 | "frame_width": 1920, 22 | "frame_height": 1080, 23 | "frame_rate": { 24 | "numerator": 60, 25 | "denominator": 1 26 | }, 27 | "pixel_format": "yuv422p10le", 28 | "video_type": "rawvideo" 29 | }, 30 | "audio": { 31 | "channels": 2, 32 | "sampleRate": 48000, 33 | "format": "pcm_s24be", 34 | "packetTime": "1ms" 35 | } 36 | }, 37 | "stream_type": { 38 | "file": { 39 | "path": "/videos/recv", 40 | "filename": "1920x1080p10le_0.yuv" 41 | } 42 | } 43 | } 44 | ], 45 | "receiver": [ 46 | { 47 | "stream_payload": { 48 | "video": { 49 | "frame_width": 1920, 50 | "frame_height": 1080, 51 | "frame_rate": { 52 | "numerator": 60, 53 | "denominator": 1 54 | }, 55 | "pixel_format": "yuv422p10le", 56 | "video_type": "rawvideo" 57 | }, 58 | "audio": { 59 | "channels": 2, 60 | "sampleRate": 48000, 61 | "format": "pcm_s24be", 62 | "packetTime": "1ms" 63 | } 64 | }, 65 | "stream_type": { 66 | "st2110": { 67 | "transport": "st2110-20", 68 | "payloadType": 112, 69 | "queues_cnt": 0 70 | } 71 | } 72 | } 73 | ] 74 | } -------------------------------------------------------------------------------- /tests/intel-node-tx-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 100, 4 | "label": "intel-broadcast-suite-tx-1", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "stream_loop": -1, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50091", 15 | "sender_payload_type":112, 16 | "sender": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "1920x1080p10le_1.yuv" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-tx-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 105, 4 | "label": "intel-broadcast-suite-tx-2", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "stream_loop":-1, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50092", 15 | "sender_payload_type":112, 16 | "sender": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "1920x1080p10le_2.yuv" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-tx-h264.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 0, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "stream_loop": -1, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50055", 15 | "sender_payload_type":112, 16 | "sender": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422", 47 | "video_type": "h264" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "output.h264" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-tx-h265.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "stream_loop": 0, 11 | "gpu_hw_acceleration": "none", 12 | "domain": "local", 13 | "ffmpeg_grpc_server_address": "localhost", 14 | "ffmpeg_grpc_server_port": "50055", 15 | "sender_payload_type":112, 16 | "sender": [{ 17 | "stream_payload": { 18 | "video": { 19 | "frame_width": 1920, 20 | "frame_height": 1080, 21 | "frame_rate": { "numerator": 60, "denominator": 1 }, 22 | "pixel_format": "yuv422p10le", 23 | "video_type": "rawvideo" 24 | }, 25 | "audio": { 26 | "channels": 2, 27 | "sampleRate": 48000, 28 | "format": "pcm_s24be", 29 | "packetTime": "1ms" 30 | } 31 | }, 32 | "stream_type": { 33 | "st2110" : { 34 | "transport" : "st2110-20", 35 | "payloadType" : 112, 36 | "queues_cnt": 0 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "hevc_qsv" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "1920x1080p10le.h265" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-tx-mcm.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 90, 4 | "label": "intel-broadcast-suite", 5 | "device_tags": { 6 | "pipeline": ["tx"] 7 | }, 8 | "function": "tx", 9 | "activate_senders": false, 10 | "gpu_hw_acceleration": "none", 11 | "domain": "local", 12 | "ffmpeg_grpc_server_address": "localhost", 13 | "ffmpeg_grpc_server_port": "50057", 14 | "sender_payload_type":112, 15 | "sender": [{ 16 | "stream_payload": { 17 | "video": { 18 | "frame_width": 1920, 19 | "frame_height": 1080, 20 | "frame_rate": { "numerator": 60, "denominator": 1 }, 21 | "pixel_format": "yuv422p10le", 22 | "video_type": "rawvideo" 23 | }, 24 | "audio": { 25 | "channels": 2, 26 | "sampleRate": 48000, 27 | "format": "pcm_s24be", 28 | "packetTime": "1ms" 29 | } 30 | }, 31 | "stream_type": { 32 | "mcm": { 33 | "conn_type": "st2110", 34 | "transport": "st2110-20", 35 | "urn": "NULL", 36 | "transportPixelFormat": "yuv422p10rfc4175" 37 | } 38 | } 39 | }], 40 | "receiver": [{ 41 | "stream_payload": { 42 | "video": { 43 | "frame_width": 1920, 44 | "frame_height": 1080, 45 | "frame_rate": { "numerator": 60, "denominator": 1 }, 46 | "pixel_format": "yuv422p10le", 47 | "video_type": "rawvideo" 48 | }, 49 | "audio": { 50 | "channels": 2, 51 | "sampleRate": 48000, 52 | "format": "pcm_s24be", 53 | "packetTime": "1ms" 54 | } 55 | }, 56 | "stream_type": { 57 | "file": { 58 | "path": "/videos", 59 | "filename": "1920x1080p10le_1.yuv" 60 | } 61 | } 62 | }] 63 | } -------------------------------------------------------------------------------- /tests/intel-node-tx.json: -------------------------------------------------------------------------------- 1 | { 2 | "logging_level": 10, 3 | "http_port": 5004, 4 | "label": "intel-broadcast-suite-tx", 5 | "device_tags": { 6 | "pipeline": [ 7 | "tx" 8 | ] 9 | }, 10 | "function": "tx", 11 | "activate_senders": false, 12 | "stream_loop": -1, 13 | "gpu_hw_acceleration": "none", 14 | "domain": "local", 15 | "ffmpeg_grpc_server_address": "192.168.2.4", 16 | "ffmpeg_grpc_server_port": "50051", 17 | "sender_payload_type": 112, 18 | "sender": [ 19 | { 20 | "stream_payload": { 21 | "video": { 22 | "frame_width": 1920, 23 | "frame_height": 1080, 24 | "frame_rate": { 25 | "numerator": 60, 26 | "denominator": 1 27 | }, 28 | "pixel_format": "yuv422p10le", 29 | "video_type": "rawvideo" 30 | }, 31 | "audio": { 32 | "channels": 2, 33 | "sampleRate": 48000, 34 | "format": "pcm_s24be", 35 | "packetTime": "1ms" 36 | } 37 | }, 38 | "stream_type": { 39 | "st2110": { 40 | "transport": "st2110-20", 41 | "payloadType": 112, 42 | "queues_cnt": 0 43 | } 44 | } 45 | } 46 | ], 47 | "receiver": [ 48 | { 49 | "stream_payload": { 50 | "video": { 51 | "frame_width": 1920, 52 | "frame_height": 1080, 53 | "frame_rate": { 54 | "numerator": 60, 55 | "denominator": 1 56 | }, 57 | "pixel_format": "yuv422p10le", 58 | "video_type": "rawvideo" 59 | }, 60 | "audio": { 61 | "channels": 2, 62 | "sampleRate": 48000, 63 | "format": "pcm_s24be", 64 | "packetTime": "1ms" 65 | } 66 | }, 67 | "stream_type": { 68 | "file": { 69 | "path": "/videos", 70 | "filename": "1920x1080p10le_0.yuv" 71 | } 72 | } 73 | } 74 | ] 75 | } -------------------------------------------------------------------------------- /tests/nmos-is05-controller/receiver.json: -------------------------------------------------------------------------------- 1 | { 2 | "activation": { 3 | "mode": "activate_immediate" 4 | }, 5 | "master_enable": true, 6 | "sender_id": "", 7 | "transport_file": { 8 | "data": "", 9 | "type": "application/sdp" 10 | }, 11 | "transport_params": [ 12 | { 13 | "interface_ip": "127.0.0.6" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /tests/nmos-is05-controller/sender.json: -------------------------------------------------------------------------------- 1 | { 2 | "master_enable": true, 3 | "receiver_id": "", 4 | "activation": { 5 | "mode": "activate_immediate" 6 | }, 7 | "transport_params": [ 8 | { 9 | "destination_ip": "127.0.0.6", 10 | "destination_port": 5005, 11 | "rtp_enabled": true, 12 | "source_ip": "127.0.0.5", 13 | "source_port": 5008 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /tests/nmos-k8s/testing-dev/nmos-is-05-controller.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: nmos-is05-controller-job 5 | namespace: default 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: nmos-is05-controller 11 | image: nmos-is05-controller:latest 12 | env: 13 | - name: RECEIVER_IP 14 | value: "localhost" 15 | - name: RECEIVER_PORT 16 | value: "90" 17 | - name: SENDER_IP 18 | value: "localhost" 19 | - name: SENDER_PORT 20 | value: "95" 21 | ports: 22 | - containerPort: 90 23 | - containerPort: 95 24 | securityContext: 25 | readOnlyRootFilesystem: true 26 | runAsNonRoot: false 27 | allowPrivilegeEscalation: false 28 | seccompProfile: 29 | type: RuntimeDefault 30 | capabilities: 31 | drop: 32 | - ALL 33 | restartPolicy: Never 34 | backoffLimit: 10 35 | -------------------------------------------------------------------------------- /tests/nmos-k8s/testing-dev/nmos-sample-registry.yaml: -------------------------------------------------------------------------------- 1 | #SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 2 | # 3 | #SPDX-License-Identifier: BSD-3-Clause 4 | 5 | apiVersion: v1 6 | kind: ConfigMap 7 | metadata: 8 | name: registry-config 9 | data: 10 | registry.json: | 11 | { 12 | "pri": 99, 13 | "logging_level": -20, 14 | "http_trace": false, 15 | "label": "nmos-registry", 16 | "http_port": 1080, 17 | "query_ws_port": 1081, 18 | "registration_expiry_interval": 12 19 | } 20 | 21 | --- 22 | apiVersion: apps/v1 23 | kind: Deployment 24 | metadata: 25 | name: nmos-registry 26 | spec: 27 | replicas: 1 28 | selector: 29 | matchLabels: 30 | app: nmos-registry 31 | template: 32 | metadata: 33 | labels: 34 | app: nmos-registry 35 | spec: 36 | containers: 37 | - name: nmos-registry 38 | image: nmos-cpp:1.2A-f549712 39 | ports: 40 | - containerPort: 1080 41 | - containerPort: 1081 42 | - containerPort: 1883 43 | env: 44 | - name: RUN_NODE 45 | value: "FALSE" 46 | volumeMounts: 47 | - name: registry-config 48 | mountPath: /home/registry.json 49 | subPath: registry.json 50 | resources: 51 | requests: 52 | cpu: 1 53 | memory: 100Mi 54 | limits: 55 | cpu: 1 56 | memory: 100Mi 57 | securityContext: 58 | readOnlyRootFilesystem: true 59 | runAsNonRoot: false 60 | allowPrivilegeEscalation: false 61 | seccompProfile: 62 | type: RuntimeDefault 63 | capabilities: 64 | drop: 65 | - ALL 66 | volumes: 67 | - name: registry-config 68 | configMap: 69 | name: registry-config 70 | 71 | --- 72 | apiVersion: v1 73 | kind: Service 74 | metadata: 75 | name: nmos-registry 76 | spec: 77 | type: NodePort 78 | selector: 79 | app: nmos-registry 80 | ports: 81 | - protocol: TCP 82 | port: 1080 83 | targetPort: 1080 84 | name: nmos-registry-port-http 85 | nodePort: 30080 86 | - protocol: TCP 87 | port: 1081 88 | targetPort: 1081 89 | name: nmos-registry-port-ws 90 | nodePort: 30081 91 | - protocol: TCP 92 | port: 1883 93 | targetPort: 1883 94 | name: nmos-registry-port-mqtt 95 | nodePort: 31883 96 | -------------------------------------------------------------------------------- /tests/nmos-k8s/testing-dev/nmos-testing.yaml: -------------------------------------------------------------------------------- 1 | #SPDX-FileCopyrightText: Copyright (c) 2024 Intel Corporation 2 | # 3 | #SPDX-License-Identifier: BSD-3-Clause 4 | 5 | --- 6 | apiVersion: v1 7 | kind: ConfigMap 8 | metadata: 9 | name: testing-config 10 | data: 11 | UserConfig.py: | 12 | from . import Config as CONFIG 13 | 14 | --- 15 | apiVersion: apps/v1 16 | kind: Deployment 17 | metadata: 18 | name: nmos-testing 19 | spec: 20 | replicas: 1 21 | selector: 22 | matchLabels: 23 | app: nmos-testing 24 | template: 25 | metadata: 26 | labels: 27 | app: nmos-testing 28 | spec: 29 | containers: 30 | - name: nmos-testing 31 | image: amwa/nmos-testing:k8s 32 | imagePullPolicy: IfNotPresent 33 | command: ["/bin/bash", "-c"] 34 | args: 35 | - | 36 | /etc/init.d/dbus start; 37 | /etc/init.d/avahi-daemon start; 38 | python3 nmos-test.py 39 | ports: 40 | - containerPort: 5000 41 | volumeMounts: 42 | - name: testing-config 43 | mountPath: /config/UserConfig.py 44 | subPath: UserConfig.py 45 | resources: 46 | requests: 47 | cpu: 1 48 | memory: 100Mi 49 | limits: 50 | cpu: 1 51 | memory: 100Mi 52 | securityContext: 53 | readOnlyRootFilesystem: true 54 | runAsNonRoot: false 55 | allowPrivilegeEscalation: false 56 | seccompProfile: 57 | type: RuntimeDefault 58 | capabilities: 59 | drop: 60 | - ALL 61 | volumes: 62 | - name: testing-config 63 | configMap: 64 | name: testing-config 65 | 66 | --- 67 | apiVersion: v1 68 | kind: Service 69 | metadata: 70 | name: nmos-testing 71 | spec: 72 | type: NodePort 73 | selector: 74 | app: nmos-testing 75 | ports: 76 | - protocol: TCP 77 | name: nmos-testing-port 78 | nodePort: 30005 79 | port: 5000 80 | targetPort: 5000 -------------------------------------------------------------------------------- /tests/nmos-registry/registry.json: -------------------------------------------------------------------------------- 1 | { 2 | "pri": 99, 3 | "logging_level": -20, 4 | "http_trace": false, 5 | "label": "nmos-bcs-registry-controller", 6 | "http_port": 80, 7 | "query_ws_port": 81, 8 | "registration_expiry_interval": 12 9 | } 10 | -------------------------------------------------------------------------------- /tests/test_docker_launcher_rx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 2 ]; then 4 | echo "Usage: $0 e.g. $0 192.168.2.1 50057" 5 | exit 1 6 | fi 7 | 8 | HOSTNAME=$1 9 | PORT=$2 10 | 11 | docker run -it \ 12 | --user root \ 13 | --privileged \ 14 | --device=/dev/vfio:/dev/vfio \ 15 | --device=/dev/dri:/dev/dri \ 16 | --cap-add ALL \ 17 | -v "$(pwd)":/videos \ 18 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 19 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 20 | -v /dev/null:/dev/null \ 21 | -v /tmp/hugepages:/tmp/hugepages \ 22 | -v /hugepages:/hugepages \ 23 | -v /var/run/imtl:/var/run/imtl \ 24 | -e http_proxy="" \ 25 | -e https_proxy="" \ 26 | --network=host \ 27 | --ipc=host \ 28 | -v /dev/shm:/dev/shm \ 29 | tiber-broadcast-suite "$HOSTNAME" "$PORT" -------------------------------------------------------------------------------- /tests/test_docker_launcher_rx_mcm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run -it \ 4 | --user root\ 5 | --privileged \ 6 | --device=/dev/vfio:/dev/vfio \ 7 | --device=/dev/dri:/dev/dri \ 8 | --cap-add ALL \ 9 | -v "$(pwd)":/videos \ 10 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 11 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 12 | -v /dev/null:/dev/null \ 13 | -v /tmp/hugepages:/tmp/hugepages \ 14 | -v /hugepages:/hugepages \ 15 | -v /run/mcm:/var/run/mcm \ 16 | -v /var/run/imtl:/var/run/imtl \ 17 | -e http_proxy="" \ 18 | -e https_proxy="" \ 19 | -e HTTP_PROXY="" \ 20 | -e HTTPS_PROXY="" \ 21 | --expose=5000-20170 \ 22 | --ipc=host -v /dev/shm:/dev/shm \ 23 | --net=host \ 24 | -e MCM_MEDIA_PROXY_PORT=8003 \ 25 | tiber-broadcast-suite localhost 50058 -------------------------------------------------------------------------------- /tests/test_docker_launcher_tx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 2 ]; then 4 | echo "Usage: $0 e.g. $0 192.168.2.1 50057" 5 | exit 1 6 | fi 7 | 8 | HOSTNAME=$1 9 | PORT=$2 10 | 11 | docker run -it \ 12 | --user root \ 13 | --privileged \ 14 | --device=/dev/vfio:/dev/vfio \ 15 | --device=/dev/dri:/dev/dri \ 16 | --cap-add ALL \ 17 | -v "$(pwd)":/videos \ 18 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 19 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 20 | -v /dev/null:/dev/null \ 21 | -v /tmp/hugepages:/tmp/hugepages \ 22 | -v /hugepages:/hugepages \ 23 | -v /var/run/imtl:/var/run/imtl \ 24 | -e http_proxy="" \ 25 | -e https_proxy="" \ 26 | --network=host \ 27 | --ipc=host \ 28 | -v /dev/shm:/dev/shm \ 29 | tiber-broadcast-suite "$HOSTNAME" "$PORT" -------------------------------------------------------------------------------- /tests/test_docker_launcher_tx_mcm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run -it \ 4 | --user root\ 5 | --privileged \ 6 | --device=/dev/vfio:/dev/vfio \ 7 | --device=/dev/dri:/dev/dri \ 8 | --cap-add ALL \ 9 | -v "$(pwd)":/videos \ 10 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 11 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 12 | -v /dev/null:/dev/null \ 13 | -v /tmp/hugepages:/tmp/hugepages \ 14 | -v /hugepages:/hugepages \ 15 | -v /run/mcm:/var/run/mcm \ 16 | -v /var/run/imtl:/var/run/imtl \ 17 | -e http_proxy="" \ 18 | -e https_proxy="" \ 19 | -e HTTP_PROXY="" \ 20 | -e HTTPS_PROXY="" \ 21 | --expose=5000-20170 \ 22 | --ipc=host -v /dev/shm:/dev/shm \ 23 | --net=host \ 24 | -e MCM_MEDIA_PROXY_PORT=8002 \ 25 | tiber-broadcast-suite localhost 50057 -------------------------------------------------------------------------------- /tests/test_docker_nmos_multiviewer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: $0 " 5 | exit 1 6 | fi 7 | 8 | case $1 in 9 | "raw") 10 | format="" 11 | ;; 12 | "h264") 13 | format="-h264" 14 | ;; 15 | "h265") 16 | format="-h265" 17 | ;; 18 | *) 19 | echo "Invalid option: $2" 20 | echo "Valid options are: raw, h264, h265" 21 | exit 1 22 | ;; 23 | esac 24 | 25 | config_file="intel-node-multiviewer${format}.json" 26 | 27 | docker run -it \ 28 | --user root\ 29 | --privileged \ 30 | --device=/dev/vfio:/dev/vfio \ 31 | --device=/dev/dri:/dev/dri \ 32 | --cap-add ALL \ 33 | -v "$(pwd)":/home/config/ \ 34 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 35 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 36 | -v /dev/null:/dev/null \ 37 | -v /tmp/hugepages:/tmp/hugepages \ 38 | -v /hugepages:/hugepages \ 39 | -v /var/run/imtl:/var/run/imtl \ 40 | -e http_proxy="" \ 41 | -e https_proxy="" \ 42 | -e VFIO_PORT_RX=0000:31:01.1 \ 43 | --network=host \ 44 | --ipc=host \ 45 | -v /dev/shm:/dev/shm \ 46 | tiber-broadcast-suite-nmos-node config/$config_file 47 | -------------------------------------------------------------------------------- /tests/test_docker_nmos_rx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$1" ]; then 4 | echo "Usage: $0 " 5 | exit 1 6 | fi 7 | 8 | case $1 in 9 | "raw") 10 | format="" 11 | ;; 12 | "h264") 13 | format="-h264" 14 | ;; 15 | "h265") 16 | format="-h265" 17 | ;; 18 | *) 19 | echo "Invalid option: $2" 20 | echo "Valid options are: raw, h264, h265" 21 | exit 1 22 | ;; 23 | esac 24 | 25 | config_file="intel-node-rx${format}.json" 26 | 27 | docker run -it \ 28 | --user root\ 29 | --privileged \ 30 | --device=/dev/vfio:/dev/vfio \ 31 | --device=/dev/dri:/dev/dri \ 32 | --cap-add ALL \ 33 | -v "$(pwd)":/home/config/ \ 34 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 35 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 36 | -v /dev/null:/dev/null \ 37 | -v /tmp/hugepages:/tmp/hugepages \ 38 | -v /hugepages:/hugepages \ 39 | -v /var/run/imtl:/var/run/imtl \ 40 | -e http_proxy="" \ 41 | -e https_proxy="" \ 42 | -e VFIO_PORT_RX=0000:31:01.1 \ 43 | --network=host \ 44 | --ipc=host \ 45 | -v /dev/shm:/dev/shm \ 46 | tiber-broadcast-suite-nmos-node config/$config_file 47 | -------------------------------------------------------------------------------- /tests/test_docker_nmos_rx_mcm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run -it \ 4 | --user root\ 5 | --privileged \ 6 | --device=/dev/vfio:/dev/vfio \ 7 | --device=/dev/dri:/dev/dri \ 8 | --cap-add ALL \ 9 | -v "$(pwd)":/home/config/ \ 10 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 11 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 12 | -v /dev/null:/dev/null \ 13 | -v /tmp/hugepages:/tmp/hugepages \ 14 | -v /hugepages:/hugepages \ 15 | -v /var/run/imtl:/var/run/imtl \ 16 | -v /run/mcm:/run/mcm \ 17 | -e http_proxy="" \ 18 | -e https_proxy="" \ 19 | -e HTTP_PROXY="" \ 20 | -e HTTPS_PROXY="" \ 21 | -e MCM_MEDIA_PROXY_PORT=8003 \ 22 | -e VFIO_PORT_RX=0000:31:01.1 \ 23 | --network=host \ 24 | --ipc=host -v /dev/shm:/dev/shm \ 25 | tiber-broadcast-suite-nmos-node config/intel-node-rx-mcm.json -------------------------------------------------------------------------------- /tests/test_docker_nmos_tx_mcm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker run -it \ 4 | --user root\ 5 | --privileged \ 6 | --device=/dev/vfio:/dev/vfio \ 7 | --device=/dev/dri:/dev/dri \ 8 | --cap-add ALL \ 9 | -v "$(pwd)":/home/config/ \ 10 | -v /usr/lib/x86_64-linux-gnu/dri:/usr/local/lib/x86_64-linux-gnu/dri/ \ 11 | -v /tmp/kahawai_lcore.lock:/tmp/kahawai_lcore.lock \ 12 | -v /dev/null:/dev/null \ 13 | -v /tmp/hugepages:/tmp/hugepages \ 14 | -v /hugepages:/hugepages \ 15 | -v /var/run/imtl:/var/run/imtl \ 16 | -v /run/mcm:/run/mcm \ 17 | -e http_proxy="" \ 18 | -e https_proxy="" \ 19 | -e HTTP_PROXY="" \ 20 | -e HTTPS_PROXY="" \ 21 | -e MCM_MEDIA_PROXY_PORT=8002 \ 22 | -e VFIO_PORT_TX=0000:31:01.0 \ 23 | --network=host \ 24 | --ipc=host -v /dev/shm:/dev/shm \ 25 | tiber-broadcast-suite-nmos-node config/intel-node-tx-mcm.json -------------------------------------------------------------------------------- /versions.env: -------------------------------------------------------------------------------- 1 | LIBVMAF=2.3.1 2 | ONEVPL=25.2.1 3 | SVTAV1=1.7.0 4 | VULKANSDK=vulkan-sdk-1.3.280.0 5 | VSR=v23.11 6 | CARTWHEEL_COMMIT_ID=7.0 7 | FFMPEG_COMMIT_ID=n7.0.2 8 | XDP_VER=d7edea3590052581c5fda5f8cfa40ae7be94f05c 9 | BPF_VER=42065ea6627ff6e1ab4c65e51042a70fbf30ff7c 10 | MTL_VER=maint-25.02.1 11 | MCM_VER=25.03 12 | JPEG_XS_COMMIT_ID=e0940acc5cd0ec239233fe5a065cffcdb29b2db4 13 | DPDK_VER=23.11 14 | FFNVCODED_VER=1889e62e2d35ff7aa9baca2bceb14f053785e6f1 15 | FFMPEG_PLUGIN_VER=7.0 16 | ICE_VER=1.14.9 17 | ICE_DMID=822519 18 | IRDMA_VER=1.16.10 19 | IRDMA_DMID=843933 20 | GMMLIB=22.7.1 21 | IHD=25.1.4 22 | LIBVA=2.22.0 23 | LIBVPL=2.13.0 24 | 25 | GRPC=1.58.0 26 | NMOS_CPP_VERSION=f54971298c47a633969e9e9adac824b56fc08da7 27 | mDNSResponder=878.260.1 28 | 29 | DEBIAN_FRONTEND=noninteractive 30 | TZ=Europe/Warsaw 31 | 32 | IRDMA_REPO=https://downloadmirror.intel.com/${IRDMA_DMID}/irdma-${IRDMA_VER}.tgz 33 | ICE_REPO=https://downloadmirror.intel.com/${ICE_DMID}/ice-${ICE_VER}.tar.gz 34 | 35 | LINK_CUDA_REPO=https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb 36 | LINK_ICE_DRIVER=https://downloadmirror.intel.com/822519/ice-1.14.9.tar.gz 37 | LINK_ICE_FIRMWARE=https://downloadmirror.intel.com/832330/Release_29.3.1.zip 38 | 39 | LINK_DPDK_DEBIAN_v2404_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/dpdk_24_04.tar.gz 40 | 41 | LINK_FFMPEG_DEBIAN_v2204_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/ffmpeg_22_04.tar.gz 42 | LINK_FFMPEG_DEBIAN_v2404_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/ffmpeg_24_04.tar.gz 43 | 44 | LINK_JPEG_XS_DEBIAN_v2204_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/jpegxs_22_04.tar.gz 45 | LINK_JPEG_XS_DEBIAN_v2404_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/jpegxs_24_04.tar.gz 46 | 47 | LINK_MCM_DEBIAN_v2204_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/mcm_22_04.tar.gz 48 | LINK_MCM_DEBIAN_v2404_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/mcm_24_04.tar.gz 49 | 50 | LINK_MTL_DEBIAN_v2204_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/Media-Transport-Library_22_04.tar.gz 51 | LINK_MTL_DEBIAN_v2404_ZIP=https://github.com/OpenVisualCloud/Intel-Tiber-Broadcast-Suite/releases/download/24.11/Media-Transport-Library_24_04.tar.gz 52 | --------------------------------------------------------------------------------