├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── doxygen ├── include │ └── kl-logo-doxygen_200x55.png └── libklvanc.doxyconf ├── lgpl-2.1.txt ├── meson.build ├── samples ├── 1280x720-608-708B.raw.bz2 ├── 1920x1080i-AFD-708B.raw.bz2 ├── 1920x1080i-sharedline-AFD-708.raw.bz2 ├── 920x1080i-AFD-708B-large.raw.bz2 ├── obe-smpte2038-and-scte35.ts.bz2 ├── ross-vanc3_2038.niles.raw.tar.gz └── smpte2038-sample-pid-01e9.ts ├── src ├── Makefile.am ├── core-cache.c ├── core-checksum.c ├── core-did.c ├── core-lines.c ├── core-packet-afd.c ├── core-packet-eia_608.c ├── core-packet-eia_708b.c ├── core-packet-kl_u64le_counter.c ├── core-packet-scte_104.c ├── core-packet-sdp.c ├── core-packet-smpte_12_2.c ├── core-packet-smpte_2108_1.c ├── core-packets.c ├── core-pixels.c ├── core-private.h ├── core.c ├── klbitstream_readwriter.h ├── libklvanc.pc.in ├── libklvanc │ ├── cache.h │ ├── did.h │ ├── klrestricted_code_path.h │ ├── pixels.h │ ├── smpte2038.h │ ├── vanc-afd.h │ ├── vanc-checksum.h │ ├── vanc-eia_608.h │ ├── vanc-eia_708b.h │ ├── vanc-kl_u64le_counter.h │ ├── vanc-lines.h │ ├── vanc-packets.h │ ├── vanc-scte_104.h │ ├── vanc-sdp.h │ ├── vanc-smpte_12_2.h │ ├── vanc-smpte_2108_1.h │ └── vanc.h ├── meson.build ├── smpte2038.c └── xorg-list.h └── tools ├── .gitignore ├── Makefile.am ├── afd.c ├── demo.c ├── eia708.c ├── genscte104.c ├── gensmpte2038.c ├── hexdump.h ├── klringbuffer.c ├── klringbuffer.h ├── klvanc_util.c ├── meson.build ├── parse.c ├── pes_extractor.c ├── pes_extractor.h ├── scte104.c ├── smpte12_2.c ├── smpte2038.c ├── ts_packetizer.c ├── ts_packetizer.h ├── udp.c ├── udp.h ├── url.c ├── url.h └── version.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | .deps/ 3 | .libs/ 4 | Makefile.in 5 | Makefile 6 | aclocal.m4 7 | autom4te.cache/ 8 | compile 9 | config.guess 10 | config.log 11 | config.status 12 | config.sub 13 | configure 14 | depcomp 15 | install-sh 16 | libtool 17 | ltmain.sh 18 | m4/ 19 | missing 20 | libklvanc.la 21 | src/libklvanc_la-*.lo 22 | doxygen/html 23 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C++ Launch", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "program": "iso13818_util", 9 | "args": [], 10 | "stopAtEntry": false, 11 | "cwd": "${workspaceRoot}/tools", 12 | "environment": [], 13 | "externalConsole": true, 14 | "linux": { 15 | "MIMode": "gdb" 16 | }, 17 | "osx": { 18 | "MIMode": "lldb" 19 | }, 20 | "windows": { 21 | "MIMode": "gdb" 22 | } 23 | }, 24 | { 25 | "name": "C++ Attach", 26 | "type": "cppdbg", 27 | "request": "attach", 28 | "program": "iso13818_util", 29 | "processId": "${command.pickProcess}", 30 | "linux": { 31 | "MIMode": "gdb" 32 | }, 33 | "osx": { 34 | "MIMode": "lldb" 35 | }, 36 | "windows": { 37 | "MIMode": "gdb" 38 | } 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | 4 | // Configure glob patterns for excluding files and folders. 5 | "files.exclude": { 6 | "**/.git": true, 7 | "**/.svn": true, 8 | "**/.hg": true, 9 | "**/.DS_Store": true, 10 | "**/.lo": true, 11 | "**/*.lo": true, 12 | "**/*.Po": true, 13 | "**/*.la": true, 14 | "**/*.o": true, 15 | "**/Makefile": true, 16 | "**/Makefile.in": true, 17 | "**/.libs": true, 18 | "**/.deps": true, 19 | "**/m4": true, 20 | "**/autom4te.cache": true, 21 | "config.*": true, 22 | "configure": true, 23 | "install-sh": true, 24 | "aclocal.m4": true, 25 | "compile": true, 26 | "libtool": true, 27 | "ltmain.sh": true, 28 | "missing": true, 29 | "depcomp": true, 30 | // Binaries that we generate 31 | "tools/klvanc_util": true, 32 | "tools/klvanc_capture": true, 33 | "tools/klvanc_smpte2038": true, 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "bash", 4 | "isShellCommand": true, 5 | "args": ["-c"], 6 | "showOutput": "always", 7 | "echoCommand": true, 8 | "suppressTaskName": true, 9 | "tasks": [ 10 | { 11 | "isBuildCommand": true, 12 | "isShellCommand": true, 13 | "taskName": "make", 14 | "args": ["make"], 15 | "showOutput": "always", 16 | }, 17 | { 18 | "isBuildCommand": true, 19 | "taskName": "make clean (tools)", 20 | "args": ["make", "-C", "tools", "clean"], 21 | "showOutput": "always", 22 | }, 23 | { 24 | "isBuildCommand": true, 25 | "taskName": "make clean (src)", 26 | "args": ["make", "-C", "src", "clean"], 27 | "showOutput": "always", 28 | }, 29 | { 30 | "isBuildCommand": true, 31 | "taskName": "run util usage", 32 | "args": ["tools/iso13818_util", "-h"], 33 | "showOutput": "always", 34 | }, 35 | { 36 | "isBuildCommand": true, 37 | "taskName": "configure", 38 | "args": ["./configure --enable-shared=no"], 39 | "showOutput": "always", 40 | }, 41 | { 42 | "isBuildCommand": true, 43 | "taskName": "autogen.sh --build", 44 | "args": ["./autogen.sh --build"], 45 | "showOutput": "always", 46 | }, 47 | { 48 | "isBuildCommand": true, 49 | "taskName": "Doxygen - Create Docs", 50 | "args": ["make docs"], 51 | "showOutput": "always", 52 | } 53 | ] 54 | } 55 | 56 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | SUBDIRS = src tools 3 | EXTRA_DIST = doxygen/libklvanc.doxyconf doxygen/include 4 | 5 | docs: 6 | cd doxygen && doxygen libklvanc.doxyconf 7 | 8 | test: 9 | cd tools && make test 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Libklvanc is a library which can be used for parsing/generation of Vertical 4 | Ancillary Data (VANC) commonly found in the Serial Digital Interface (SDI) wire protocol. 5 | 6 | The library includes a general parser/decoder and an encoder for 7 | VANC lines, as well as the ability to both decode and generate protocols 8 | commonly found in SDI, including: 9 | - SMPTE ST 334 - CEA-708 closed captions in VANC 10 | - SMPTE ST 2016 Active Format Descriptor (AFD) and Bar Data 11 | - SCTE-104 Ad triggers 12 | - SMPTE ST 2038 arbitrary VANC encapsulation 13 | - SMPTE ST 12-2 Timecodes 14 | - SMPTE RDD 8 Subtitle Distribution packets 15 | - SMPTE ST 2108-1 HDR/WCG Metadata Packing and Signaling 16 | 17 | By providing both encoders and decoders, the library can be used for common 18 | use cases involving both capture of SDI (and subsequent decoding) as well as 19 | generation of VANC for inclusion in an SDI output interface. This includes 20 | computing/validating checksums at various levels and dealing with subtle edge 21 | cases related to VANC line formatting such as ensuring packets are contiguous. 22 | 23 | The library also provides utility functions for various colorspaces VANC 24 | may be represented in, including the V210 format typically used by 25 | BlackMagic Decklink SDI cards. 26 | 27 | Beyond this Readme.MD file, API level documentation can be generated via 28 | Doxygen (see "Making Documentation" section below). 29 | 30 | Users should refer to the "tools" subdirectory for some test code which 31 | which make use of the library. For a "real world" application, refer to 32 | the klvanc-tools package, which make use of libklvanc in conjunction with 33 | Blackmagic cards to capture real SDI signals. 34 | 35 | https://github.com/stoth68000/klvanc-tools 36 | 37 | # LICENSE 38 | 39 | LGPL-V2.1 40 | See the included lgpl-2.1.txt for the complete license agreement. 41 | 42 | ## Dependencies 43 | * Doxygen (if generation of API documentation is desired) 44 | 45 | ## Compilation 46 | 47 | ./autogen.sh --build 48 | ./configure --enable-shared=no 49 | make 50 | 51 | ## Making Documentation: 52 | To make doxygen documentation in the doxygen folder, run the following command: 53 | 54 | make docs 55 | 56 | To view the documentation, cd into the doxygen/html/ directory and open the index.html file in a browser window. 57 | ## Verifying the compilation: 58 | The library comes with a series of test cases which allow the user to confirm 59 | the library is working appropriately (as well as allowing us to watch for 60 | regressions). 61 | 62 | To run the tests after compilation, run the following command: 63 | 64 | make test 65 | 66 | ## Compilation with meson 67 | 68 | Meson can be used as an alternative to autotools: 69 | 70 | meson build 71 | ninja -C build 72 | 73 | The documentation will be built automatically if Doxygen is available 74 | 75 | ## Running tests with meson 76 | 77 | meson test -C build 78 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case "$1" in 4 | --clean) 5 | make distclean 6 | rm -rf autom4te.cache m4 7 | rm -f aclocal.m4 config.log config.status configure 8 | rm -f depcomp install-sh Makefile Makefile.in missing 9 | rm -f config.guess config.sub libtool ltmain.sh 10 | rm -f src/Makefile.in 11 | ;; 12 | --build) 13 | aclocal 14 | autoconf 15 | autoreconf -i 16 | automake --add-missing 17 | ;; 18 | *) 19 | echo "$0 --clean --build" 20 | exit 1 21 | ;; 22 | esac 23 | 24 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.68]) 5 | AC_INIT([libklvanc], [1.0], [stoth@kernellabs.com]) 6 | AM_INIT_AUTOMAKE 7 | AC_CONFIG_MACRO_DIR([m4]) 8 | AC_CANONICAL_HOST 9 | AM_SILENT_RULES([yes]) 10 | AC_CONFIG_FILES([src/libklvanc.pc:src/libklvanc.pc.in]) 11 | 12 | # Checks for programs. 13 | AC_PROG_CC 14 | AC_PROG_CC_C99 15 | if test `uname -s` = "Darwin" 16 | then 17 | CFLAGS+=" -I/usr/local/include " 18 | LDFLAGS+=" -L/usr/local/lib " 19 | fi 20 | 21 | # We always build with -fPIC in case our static libraries end up 22 | # being linked into a consumer's shared library 23 | AC_MSG_CHECKING(whether fPIC compiler option is accepted) 24 | SAVED_CFLAGS="$CFLAGS" 25 | CFLAGS="$CFLAGS -fPIC -Werror" 26 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [return 0;])], 27 | [AC_MSG_RESULT(yes) 28 | CFLAGS="$SAVED_CFLAGS -fPIC"], 29 | [AC_MSG_RESULT(no) 30 | CFLAGS="$SAVED_CFLAGS"]) 31 | 32 | AC_PROG_RANLIB 33 | AC_PROG_LIBTOOL 34 | 35 | # Checks for header files. 36 | AC_CHECK_HEADERS([arpa/inet.h fcntl.h netinet/in.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h]) 37 | 38 | # Checks for typedefs, structures, and compiler characteristics. 39 | AC_TYPE_UINT16_T 40 | AC_TYPE_UINT8_T 41 | 42 | # Checks for library functions. 43 | AC_CHECK_FUNCS([memset strrchr]) 44 | 45 | # Add debug support 46 | AC_ARG_ENABLE(debug, 47 | AS_HELP_STRING( 48 | [--enable-debug], 49 | [enable debugging, default: no]), 50 | [case "${enableval}" in 51 | yes) debug=true ;; 52 | no) debug=false ;; 53 | *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; 54 | esac], 55 | [debug=false]) 56 | AM_CONDITIONAL(DEBUG, test x"$debug" = x"true") 57 | AM_COND_IF(DEBUG, 58 | AC_DEFINE(DEBUG, 1, [Define to 0 if this is a release build]), 59 | AC_DEFINE(DEBUG, 0, [Define to 1 or higher if this is a debug build])) 60 | 61 | AC_CONFIG_FILES([Makefile src/Makefile tools/Makefile]) 62 | AC_OUTPUT 63 | 64 | -------------------------------------------------------------------------------- /doxygen/include/kl-logo-doxygen_200x55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/doxygen/include/kl-logo-doxygen_200x55.png -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('libklvanc', 'c', 2 | default_options : ['buildtype=debugoptimized']) 3 | 4 | subdir('src') 5 | subdir('tools') 6 | 7 | doxygen = find_program('doxygen', required : false) 8 | 9 | datadir = join_paths(get_option('datadir'), 'doc', 'libklvanc') 10 | doxyfile = files('doxygen/libklvanc.doxyconf') 11 | 12 | if doxygen.found() 13 | html_target = custom_target('libklvanc-docs', 14 | build_by_default: false, 15 | input: doxyfile, 16 | output: 'html', 17 | command: [doxygen, '@INPUT@'], 18 | install: true, 19 | install_dir: datadir) 20 | endif 21 | -------------------------------------------------------------------------------- /samples/1280x720-608-708B.raw.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/1280x720-608-708B.raw.bz2 -------------------------------------------------------------------------------- /samples/1920x1080i-AFD-708B.raw.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/1920x1080i-AFD-708B.raw.bz2 -------------------------------------------------------------------------------- /samples/1920x1080i-sharedline-AFD-708.raw.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/1920x1080i-sharedline-AFD-708.raw.bz2 -------------------------------------------------------------------------------- /samples/920x1080i-AFD-708B-large.raw.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/920x1080i-AFD-708B-large.raw.bz2 -------------------------------------------------------------------------------- /samples/obe-smpte2038-and-scte35.ts.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/obe-smpte2038-and-scte35.ts.bz2 -------------------------------------------------------------------------------- /samples/ross-vanc3_2038.niles.raw.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/ross-vanc3_2038.niles.raw.tar.gz -------------------------------------------------------------------------------- /samples/smpte2038-sample-pid-01e9.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stoth68000/libklvanc/b409fc2b0b8051c871f89367a3489f8aa2b6ed37/samples/smpte2038-sample-pid-01e9.ts -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | AUTOMAKE_OPTIONS = foreign 3 | 4 | pkgconfigdir = $(libdir)/pkgconfig 5 | pkgconfig_DATA = libklvanc.pc 6 | 7 | lib_LTLIBRARIES = libklvanc.la 8 | 9 | libklvanc_la_SOURCES = core.c 10 | libklvanc_la_SOURCES += core-packet-eia_708b.c 11 | libklvanc_la_SOURCES += core-packet-eia_608.c 12 | libklvanc_la_SOURCES += core-packet-scte_104.c 13 | libklvanc_la_SOURCES += core-packet-afd.c 14 | libklvanc_la_SOURCES += core-packet-sdp.c 15 | libklvanc_la_SOURCES += core-packet-smpte_12_2.c 16 | libklvanc_la_SOURCES += core-packet-smpte_2108_1.c 17 | libklvanc_la_SOURCES += core-packets.c 18 | libklvanc_la_SOURCES += core-lines.c 19 | libklvanc_la_SOURCES += core-did.c 20 | libklvanc_la_SOURCES += core-pixels.c 21 | libklvanc_la_SOURCES += core-checksum.c 22 | libklvanc_la_SOURCES += smpte2038.c 23 | libklvanc_la_SOURCES += core-cache.c 24 | libklvanc_la_SOURCES += core-packet-kl_u64le_counter.c 25 | libklvanc_la_SOURCES += core-private.h xorg-list.h 26 | libklvanc_la_SOURCES += klbitstream_readwriter.h 27 | 28 | libklvanc_la_CFLAGS = -Wall -DVERSION=\"$(VERSION)\" -DPROG="\"$(PACKAGE)\"" \ 29 | -D_FILE_OFFSET_BITS=64 -O3 -D_BSD_SOURCE -I$(top_srcdir)/include 30 | 31 | if DEBUG 32 | libklvanc_la_CFLAGS += -g 33 | endif 34 | 35 | libklvanc_includedir = $(includedir)/libklvanc 36 | 37 | libklvanc_include_HEADERS = libklvanc/vanc.h 38 | libklvanc_include_HEADERS += libklvanc/did.h 39 | libklvanc_include_HEADERS += libklvanc/pixels.h 40 | libklvanc_include_HEADERS += libklvanc/smpte2038.h 41 | libklvanc_include_HEADERS += libklvanc/vanc-eia_708b.h 42 | libklvanc_include_HEADERS += libklvanc/vanc-eia_608.h 43 | libklvanc_include_HEADERS += libklvanc/vanc-scte_104.h 44 | libklvanc_include_HEADERS += libklvanc/vanc-smpte_12_2.h 45 | libklvanc_include_HEADERS += libklvanc/vanc-smpte_2108_1.h 46 | libklvanc_include_HEADERS += libklvanc/vanc-packets.h 47 | libklvanc_include_HEADERS += libklvanc/vanc-lines.h 48 | libklvanc_include_HEADERS += libklvanc/vanc-afd.h 49 | libklvanc_include_HEADERS += libklvanc/vanc-sdp.h 50 | libklvanc_include_HEADERS += libklvanc/vanc-checksum.h 51 | libklvanc_include_HEADERS += libklvanc/klrestricted_code_path.h 52 | libklvanc_include_HEADERS += libklvanc/cache.h 53 | libklvanc_include_HEADERS += libklvanc/vanc-kl_u64le_counter.h 54 | 55 | -------------------------------------------------------------------------------- /src/core-cache.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | /* Maintain a static array of VANC messages, so that at any given time, 29 | * a user may ask "what message types have I seen on what lines?". 30 | */ 31 | 32 | int klvanc_cache_alloc(struct klvanc_context_s *ctx) 33 | { 34 | ctx->cacheLines = calloc(0x10000, sizeof(struct klvanc_cache_s)); 35 | if (!ctx->cacheLines) 36 | return -1; 37 | 38 | return 0; 39 | } 40 | 41 | void klvanc_cache_free(struct klvanc_context_s *ctx) 42 | { 43 | /* Free any cached lines otherwise we'll memory leak. */ 44 | klvanc_cache_reset(ctx); 45 | 46 | if (ctx->cacheLines) { 47 | free(ctx->cacheLines); 48 | ctx->cacheLines = 0; 49 | } 50 | } 51 | 52 | struct klvanc_cache_s * klvanc_cache_lookup(struct klvanc_context_s *ctx, uint8_t didnr, uint8_t sdidnr) 53 | { 54 | if (!ctx) 55 | return NULL; 56 | if (!ctx->cacheLines) 57 | return NULL; 58 | 59 | return &ctx->cacheLines[ (((didnr) << 8) | (sdidnr)) ]; 60 | }; 61 | 62 | int klvanc_cache_update(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *pkt) 63 | { 64 | if (!ctx) 65 | return -1; 66 | if (!ctx->cacheLines) 67 | return -1; 68 | if (pkt->did > 0xff) 69 | return -1; 70 | if (pkt->dbnsdid > 0xff) 71 | return -1; 72 | if (pkt->lineNr >= 2048) 73 | return -1; 74 | 75 | struct klvanc_cache_s *s = klvanc_cache_lookup(ctx, pkt->did, pkt->dbnsdid); 76 | if (s->activeCount == 0) { 77 | s->did = pkt->did; 78 | s->sdid = pkt->dbnsdid; 79 | s->desc = klvanc_didLookupDescription(pkt->did, pkt->dbnsdid); 80 | s->spec = klvanc_didLookupSpecification(pkt->did, pkt->dbnsdid); 81 | } 82 | gettimeofday(&s->lastUpdated, NULL); 83 | 84 | struct klvanc_cache_line_s *line = &s->lines[ pkt->lineNr ]; 85 | line->active = 1; 86 | s->activeCount++; 87 | 88 | pthread_mutex_lock(&line->mutex); 89 | if (line->pkt) { 90 | klvanc_packet_free(line->pkt); 91 | line->pkt = 0; 92 | } 93 | klvanc_packet_copy(&line->pkt, pkt); 94 | pthread_mutex_unlock(&line->mutex); 95 | 96 | line->count++; 97 | 98 | return 0; 99 | } 100 | 101 | void klvanc_cache_reset(struct klvanc_context_s *ctx) 102 | { 103 | if (!ctx) 104 | return; 105 | if (!ctx->cacheLines) 106 | return; 107 | 108 | for (int d = 0; d <= 0xff; d++) { 109 | for (int s = 0; s <= 0xff; s++) { 110 | struct klvanc_cache_s *e = klvanc_cache_lookup(ctx, d, s); 111 | 112 | if (e->activeCount == 0) 113 | continue; 114 | e->activeCount = 0; 115 | 116 | for (int l = 0; l < 2048; l++) { 117 | struct klvanc_cache_line_s *line = &e->lines[ l ]; 118 | if (!line->active) 119 | continue; 120 | 121 | line->active = 0; 122 | line->count = 0; 123 | 124 | pthread_mutex_lock(&line->mutex); 125 | if (line->pkt) { 126 | klvanc_packet_free(line->pkt); 127 | line->pkt = 0; 128 | } 129 | pthread_mutex_unlock(&line->mutex); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/core-checksum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include "core-private.h" 24 | 25 | #include 26 | #include 27 | 28 | /* Wikipedia: 29 | * The last word in an ANC packet is the Checksum word. It is computed 30 | * by computing the sum (modulo 512) of bits 0-8 (not bit 9), of all the other 31 | * words in the ANC packet, excluding the packet start sequence. 32 | * Bit 9 of the checksum word is then defined as the inverse of bit 8. 33 | * Note that the checksum word does not contain a parity bit; instead, the 34 | * parity bits of other words are included in the checksum calculations. 35 | * Checksumming begins after the AFD and should conclude on the last word 36 | * of the message, sans the checksum byte itself. 37 | * 38 | * To be clear, on the words 111, 222 and 333 should be passed to this routine. 39 | * 000 03FF 03FF 111 222 333 CHKSUM 40 | * So pass the address of 111 with a wordCount of 3. 41 | */ 42 | uint16_t klvanc_checksum_calculate(const uint16_t *words, int wordCount) 43 | { 44 | uint16_t s = 0; 45 | for (uint16_t i = 0; i < wordCount; i++) { 46 | s += *(words + i); 47 | s &= 0x01ff; 48 | } 49 | s |= ((~s & 0x0100) << 1); 50 | 51 | return s; 52 | } 53 | 54 | /* For a given list of words, excludint the ADF, ending in a checksum, 55 | * calculate the checksum and verify the last word in the array is a correct 56 | * calculation of all the prior words in the array. 57 | * 58 | * To be clear, on the words 111, 222, 333 and CHECKSUM should be passed to this routine. 59 | * 000 03FF 03FF 111 222 333 CHECKSUM 60 | * So pass the address of 111 with a wordCount of 3. 61 | * 62 | * Returns: Boolean true or false. 63 | */ 64 | int klvanc_checksum_is_valid(const uint16_t *words, int wordCount) 65 | { 66 | #define LOCAL_DEBUG 0 67 | #if 0 68 | printf("%s(%p, %d): ", __func__, words, wordCount); 69 | for (int i = 0; i < wordCount; i++) 70 | printf("%04x ", *(words + i)); 71 | printf("\n"); 72 | #endif 73 | uint16_t sum = klvanc_checksum_calculate(words, wordCount - 1); 74 | if (sum != *(words + (wordCount - 1))) { 75 | #if LOCAL_DEBUG 76 | fprintf(stderr, "Checksum calculated as %04x, but passed as %04x\n", sum, *(words + (wordCount - 1))); 77 | #endif 78 | return 0; 79 | } 80 | 81 | return 1; 82 | } 83 | -------------------------------------------------------------------------------- /src/core-did.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "core-private.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* The content in this list comes from the SMPTE Registration Authority 33 | https://smpte-ra.org/smpte-ancillary-data-smpte-st-291 */ 34 | static struct did_s { 35 | uint16_t did; 36 | uint16_t sdid; 37 | const char *spec; 38 | const char *desc; 39 | } dids[] = { 40 | { 0x00, 0x00, "S291", "Undefined Data"}, 41 | { 0x08, 0x08, "S353", "MPEG recoding data, VANC space"}, 42 | { 0x08, 0x0C, "S353", "MPEG recoding data, HANC space"}, 43 | { 0x40, 0x01, "S305", "SDTI transport in active frame space"}, 44 | { 0x40, 0x02, "S348", "HD-SDTI transport in active frame space"}, 45 | { 0x40, 0x04, "S427", "Link Encryption Message 1"}, 46 | { 0x40, 0x05, "S427", "Link Encryption Message 2"}, 47 | { 0x40, 0x06, "S427", "Link Encryption Metadata"}, 48 | { 0x40, 0xfe, "KLABS","UINT64_T little endian frame counter"}, 49 | { 0x41, 0x01, "S352", "Payload Identification, HANC space"}, 50 | { 0x41, 0x05,"S2016-3", "Active Format Description and Bar Data"}, 51 | { 0x41, 0x06,"S2016-4", "Pan-Scan Data"}, 52 | { 0x41, 0x07, "S2010", "ANSI/SCTE 104 messages"}, 53 | { 0x41, 0x08, "S2031", "DVB/SCTE VBI data"}, 54 | { 0x41, 0x09, "S2056", "MPEG TS packets in VANC"}, 55 | { 0x41, 0x0A, "S2068", "Stereoscopic 3D Frame Compatible Packing and Signaling"}, 56 | { 0x41, 0x0B,"S2064-2", "Lip Sync data as specified by ST 2064-1"}, 57 | { 0x41, 0x0C,"S2108-1", "Extended HDR/WCG for SDI"}, 58 | { 0x41, 0x0D,"S2108-2", "Vertical Ancillary Data Mapping of KLV Formatted HDR/WCG Metadata"}, 59 | { 0x43, 0x01,"ITU-R BT.1685", "Structure of inter-station control data"}, 60 | { 0x43, 0x02, "RDD8", "Subtitling Distribution packet (SDP)"}, 61 | { 0x43, 0x03, "RDD8", "Transport of ANC packet in an ANC Multipacket"}, 62 | { 0x43, 0x04,"ARIB RT-B29", "Monitoring Metadata for ARIB Broadcasting chain"}, 63 | { 0x43, 0x05, "RDD18", "Acquisition Metadata Sets for Video Camera Parameters"}, 64 | { 0x44, 0x04, "RP214", "KLV Metadata transport in VANC space"}, 65 | { 0x44, 0x14, "RP214", "KLV Metadata transport in HANC space"}, 66 | { 0x44, 0x44, "RP223", "UMID and Program Identification Label Data"}, 67 | { 0x45, 0x01,"S2020-1", "Compressed Audio Metadata"}, 68 | { 0x45, 0x02,"S2020-1", "Compressed Audio Metadata"}, 69 | { 0x45, 0x03,"S2020-1", "Compressed Audio Metadata"}, 70 | { 0x45, 0x04,"S2020-1", "Compressed Audio Metadata"}, 71 | { 0x45, 0x05,"S2020-1", "Compressed Audio Metadata"}, 72 | { 0x45, 0x06,"S2020-1", "Compressed Audio Metadata"}, 73 | { 0x45, 0x07,"S2020-1", "Compressed Audio Metadata"}, 74 | { 0x45, 0x08,"S2020-1", "Compressed Audio Metadata"}, 75 | { 0x45, 0x09,"S2020-1", "Compressed Audio Metadata"}, 76 | { 0x46, 0x01, "S2051", "Two Frame Marker in HANC"}, 77 | { 0x50, 0x01, "RDD8", "WSS Data"}, 78 | 79 | /* Note: Not registered with SMPTE-RA (taken from ARIB STD-B37 Version 2.4-E1) */ 80 | { 0x5F, 0xDC,"ARIB STD-B37", "ARIB Captioning - Mobile"}, 81 | { 0x5F, 0xDD,"ARIB STD-B37", "ARIB Captioning - Analog"}, 82 | { 0x5F, 0xDE,"ARIB STD-B37", "ARIB Captioning - SD"}, 83 | { 0x5F, 0xDF,"ARIB STD-B37", "ARIB Captioning - HD"}, 84 | 85 | { 0x51, 0x01, "RP215", "Film Codes in VANC space"}, 86 | { 0x60, 0x60, "S12M-2", "Ancillary Time Code"}, 87 | { 0x60, 0x61, "S12M-3", "Time Code for High Frame Rate Signals"}, 88 | { 0x60, 0x62, "S2103", "Generic Time Label"}, 89 | { 0x61, 0x01, "S334-1", "EIA 708B Data mapping into HDTV VBI, VANC space"}, 90 | { 0x61, 0x02, "S334-1", "EIA 608 Data mapping into HDTV VBI, VANC space"}, 91 | 92 | /* Note: Not registered with SMPTE-RA (origin/validity unclear) */ 93 | { 0x61, 0x03, "S334", "World System Teletext Description Packet"}, 94 | { 0x61, 0x04, "S334", "Subtitling Data Essence (SDE)"}, 95 | { 0x61, 0x05, "S334", "ARIB Captioning - HD"}, 96 | { 0x61, 0x06, "S334", "ARIB Captioning - SD"}, 97 | { 0x61, 0x07, "S334", "ARIB Captioning - Analog"}, 98 | 99 | { 0x62, 0x01, "RP207", "Program Description in VANC space"}, 100 | { 0x62, 0x02, "S334-1", "Data broadcast (DTV) in VANC space"}, 101 | { 0x62, 0x03, "RP208", "VBI Data in VANC space"}, 102 | { 0x64, 0x64, "RP196", "Time Code in HANC space (Deprecated)"}, 103 | { 0x64, 0x7F, "RP196", "VITC in HANC space (Deprecated)"}, 104 | }; 105 | 106 | static struct did_s dids_t1[] = { 107 | { 0x00, 0x00, "S291", "Undefined Data (Deprecated)"}, 108 | { 0x80, 0x00, "S291", "Packet marked for deletion"}, 109 | { 0x84, 0x00, "S291", "End packet deleted (Deprecated)"}, 110 | { 0x88, 0x00, "S291", "Start packet deleted (Deprecated)"}, 111 | { 0xA0, 0x00,"S299-2", "Audio data in HANC space (3G) G8 Control"}, 112 | { 0xA1, 0x00,"S299-2", "Audio data in HANC space (3G) G7 Control"}, 113 | { 0xA2, 0x00,"S299-2", "Audio data in HANC space (3G) G6 Control"}, 114 | { 0xA3, 0x00,"S299-2", "Audio data in HANC space (3G) G5 Control"}, 115 | { 0xA4, 0x00,"S299-2", "Audio data in HANC space (3G) G8"}, 116 | { 0xA5, 0x00,"S299-2", "Audio data in HANC space (3G) G7"}, 117 | { 0xA6, 0x00,"S299-2", "Audio data in HANC space (3G) G6"}, 118 | { 0xA7, 0x00,"S299-2", "Audio data in HANC space (3G) G5"}, 119 | { 0xE0, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 120 | { 0xE1, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 121 | { 0xE2, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 122 | { 0xE3, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 123 | { 0xE4, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 124 | { 0xE5, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 125 | { 0xE6, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 126 | { 0xE7, 0x00,"S299-1", "Audio data in HANC space (HDTV)"}, 127 | { 0xEC, 0x00, "S272", "Audio data in HANC space (SDTV)"}, 128 | { 0xED, 0x00, "S272", "Audio data in HANC space (SDTV)"}, 129 | { 0xEE, 0x00, "S272", "Audio data in HANC space (SDTV)"}, 130 | { 0xEF, 0x00, "S272", "Audio data in HANC space (SDTV)"}, 131 | { 0xF0, 0x00, "S315", "Camera Position (HANC or VANC space)"}, 132 | { 0xF4, 0x00, "RP165", "Error Detection and Handling, HANC space"}, 133 | { 0xF8, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 134 | { 0xF9, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 135 | { 0xFA, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 136 | { 0xFB, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 137 | { 0xFC, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 138 | { 0xFD, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 139 | { 0xFE, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 140 | { 0xFF, 0x00, "S272", "Audio Data in HANC space (SDTV)"}, 141 | }; 142 | 143 | const char *klvanc_didLookupDescription(uint16_t did, uint16_t sdid) 144 | { 145 | for (unsigned int i = 0; i < (sizeof(dids) / sizeof(struct did_s)); i++) { 146 | if ((did == dids[i].did) && (sdid == dids[i].sdid)) 147 | return dids[i].desc; 148 | } 149 | 150 | /* No match for Type 2, check type 1 */ 151 | for (unsigned int i = 0; i < (sizeof(dids_t1) / sizeof(struct did_s)); i++) { 152 | if (did == dids_t1[i].did) 153 | return dids_t1[i].desc; 154 | } 155 | 156 | return "Undefined"; 157 | } 158 | 159 | const char *klvanc_didLookupSpecification(uint16_t did, uint16_t sdid) 160 | { 161 | for (unsigned int i = 0; i < (sizeof(dids) / sizeof(struct did_s)); i++) { 162 | if ((did == dids[i].did) && (sdid == dids[i].sdid)) 163 | return dids[i].spec; 164 | } 165 | 166 | /* No match for Type 2, check type 1 */ 167 | for (unsigned int i = 0; i < (sizeof(dids_t1) / sizeof(struct did_s)); i++) { 168 | if (did == dids_t1[i].did) 169 | return dids_t1[i].spec; 170 | } 171 | 172 | return "Undefined"; 173 | } 174 | -------------------------------------------------------------------------------- /src/core-lines.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "core-private.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | struct klvanc_line_s *klvanc_line_create(int line_number) 32 | { 33 | struct klvanc_line_s *new_line = NULL; 34 | new_line = (struct klvanc_line_s *)malloc(sizeof(struct klvanc_line_s)); 35 | if (new_line == NULL) 36 | return NULL; 37 | memset(new_line, 0, sizeof(struct klvanc_line_s)); 38 | new_line->line_number = line_number; 39 | return new_line; 40 | } 41 | 42 | void klvanc_line_free(struct klvanc_line_s *line) 43 | { 44 | for (int i = 0; i < KLVANC_MAX_VANC_ENTRIES; i++) { 45 | if (line->p_entries[i] != NULL) { 46 | free(line->p_entries[i]->payload); 47 | free(line->p_entries[i]); 48 | } 49 | } 50 | free(line); 51 | } 52 | 53 | int klvanc_line_insert(struct klvanc_context_s *ctx, struct klvanc_line_set_s *vanc_lines, 54 | uint16_t * pixels, int pixel_width, int line_number, int horizontal_offset) 55 | { 56 | int i; 57 | struct klvanc_line_s *line = vanc_lines->lines[0]; 58 | struct klvanc_entry_s *new_entry = 59 | (struct klvanc_entry_s *)malloc(sizeof(struct klvanc_entry_s)); 60 | if (new_entry == NULL) 61 | return -ENOMEM; 62 | 63 | new_entry->payload = 64 | (uint16_t *) malloc(pixel_width * sizeof(uint16_t)); 65 | if (new_entry->payload == NULL) { 66 | free(new_entry); 67 | return -ENOMEM; 68 | } 69 | memcpy(new_entry->payload, pixels, pixel_width * sizeof(uint16_t)); 70 | new_entry->h_offset = horizontal_offset; 71 | new_entry->pixel_width = pixel_width; 72 | 73 | /* See if there is already a line allocated for the target line, if not, create one */ 74 | for (i = 0; i < KLVANC_MAX_VANC_LINES; i++) { 75 | if (vanc_lines->lines[i] == NULL) { 76 | line = klvanc_line_create(line_number); 77 | vanc_lines->lines[i] = line; 78 | vanc_lines->num_lines++; 79 | break; 80 | } 81 | if (vanc_lines->lines[i]->line_number == line_number) { 82 | line = vanc_lines->lines[i]; 83 | break; 84 | } 85 | } 86 | 87 | if (i == KLVANC_MAX_VANC_LINES) { 88 | /* Array is full */ 89 | PRINT_DEBUG("array of lines is full!\n"); 90 | free(new_entry->payload); 91 | free(new_entry); 92 | return -ENOMEM; 93 | } 94 | 95 | /* Now insert the VANC entry into the line */ 96 | if (line->num_entries == KLVANC_MAX_VANC_ENTRIES) { 97 | /* Array is full */ 98 | PRINT_DEBUG("line is full!\n"); 99 | free(new_entry->payload); 100 | free(new_entry); 101 | return -ENOMEM; 102 | } 103 | 104 | line->p_entries[line->num_entries++] = new_entry; 105 | return 0; 106 | } 107 | 108 | static int vanc_ent_comp(const void *a, const void *b) 109 | { 110 | const struct klvanc_entry_s *vala = *(struct klvanc_entry_s **) a; 111 | const struct klvanc_entry_s *valb = *(struct klvanc_entry_s **) b; 112 | 113 | if (vala->h_offset < valb->h_offset) 114 | return -1; 115 | 116 | if (vala->h_offset == valb->h_offset) 117 | return 0; 118 | return 1; 119 | } 120 | 121 | int klvanc_generate_vanc_line(struct klvanc_context_s *ctx, struct klvanc_line_s *line, 122 | uint16_t ** outbuf, int *out_len, int line_pixel_width) 123 | { 124 | int pixels_used = 0; 125 | int i; 126 | 127 | /* Sort the VANC entries on the line prior to processing */ 128 | qsort(line->p_entries, line->num_entries, sizeof(struct klvanc_entry_s *), 129 | vanc_ent_comp); 130 | 131 | /* Now iterate through and adjust any offsets to prevent overlap. Also calculate 132 | how big a buffer we need for the final array of pixels */ 133 | for (i = 0; i < line->num_entries; i++) { 134 | struct klvanc_entry_s *entry = line->p_entries[i]; 135 | if (entry->h_offset < pixels_used) { 136 | /* New entry would overwrite earlier entry, so push it out */ 137 | entry->h_offset = pixels_used; 138 | } else if (entry->h_offset > pixels_used) { 139 | /* Don't let there be a gap between the latest entry and the 140 | previous entry. VANC entries must be contiguous 141 | (see SMPTE ST291-1-2011 Sec 7.3) */ 142 | entry->h_offset = pixels_used; 143 | } 144 | 145 | /* Check all bytes after VANC start words for illegal values */ 146 | for (int j = 3; j < entry->pixel_width; j++) { 147 | if (entry->payload[j] <= 0x0003 148 | || entry->payload[j] >= 0x03FC) { 149 | PRINT_DEBUG( 150 | "VANC line %d has entry with illegal payload at offset %d. Skipping. offset=%d len=%d", 151 | line->line_number, j, entry->h_offset, 152 | entry->pixel_width); 153 | for (int k = 0; k < entry->pixel_width; k++) { 154 | PRINT_DEBUG("%04x ", entry->payload[k]); 155 | } 156 | PRINT_DEBUG("\n"); 157 | entry->pixel_width = 0; 158 | break; 159 | } 160 | } 161 | 162 | /* Don't let sum of all VANC entries overflow end of line */ 163 | if ((entry->h_offset + entry->pixel_width) > line_pixel_width) { 164 | /* Set the length to zero so this entry gets skipped */ 165 | PRINT_DEBUG( 166 | "VANC line %d would overflow thus skipping. offset=%d len=%d", 167 | line->line_number, entry->h_offset, 168 | entry->pixel_width); 169 | entry->pixel_width = 0; 170 | continue; 171 | } 172 | 173 | pixels_used += entry->pixel_width; 174 | } 175 | 176 | /* Caller probably provided no line entries, return success as this isn't a failure of sorts. */ 177 | if (pixels_used == 0) 178 | return 0; 179 | 180 | *outbuf = (uint16_t *) malloc(pixels_used * sizeof(uint16_t)); 181 | if (*outbuf == NULL) { 182 | return -ENOMEM; 183 | } 184 | *out_len = pixels_used; 185 | 186 | /* Assemble the final line ensuring there are no discontinuities between 187 | the VANC entries */ 188 | for (i = 0; i < line->num_entries; i++) { 189 | struct klvanc_entry_s *entry = line->p_entries[i]; 190 | memcpy((*outbuf) + entry->h_offset, entry->payload, 191 | entry->pixel_width * (sizeof(uint16_t))); 192 | } 193 | return 0; 194 | } 195 | 196 | int klvanc_generate_vanc_line_v210(struct klvanc_context_s *ctx, 197 | struct klvanc_line_s *line, 198 | uint8_t *out_buf, int line_pixel_width) 199 | { 200 | uint16_t *out_line; 201 | int out_len; 202 | int result; 203 | 204 | /* Generate the full line taking into account all VANC packets on that line */ 205 | result = klvanc_generate_vanc_line(ctx, line, &out_line, &out_len, 206 | line_pixel_width); 207 | if (result != 0) { 208 | return -ENOMEM; 209 | } 210 | 211 | /* Repack the 16-bit ints into 10-bit, and push into final buffer */ 212 | if (line_pixel_width > 720) 213 | klvanc_y10_to_v210(out_line, out_buf, out_len); 214 | else 215 | klvanc_uyvy_to_v210(out_line, out_buf, out_len); 216 | 217 | free(out_line); 218 | return 0; 219 | } 220 | -------------------------------------------------------------------------------- /src/core-packet-afd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include "core-private.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | const char *klvanc_afd_to_string(enum klvanc_payload_afd_e afd) 31 | { 32 | switch(afd) { 33 | case AFD_UNDEFINED: 34 | return "AFD_UNDEFINED"; 35 | case AFD_BOX_16x9_TOP: 36 | return "AFD_BOX_16x9_TOP"; 37 | case AFD_BOX_14x9_TOP: 38 | return "AFD_BOX_14x9_TOP"; 39 | case AFD_BOX_16x9_CENTER: 40 | return "AFD_16x9_CENTER"; 41 | case AFD_FULL_FRAME: 42 | return "AFD_FULL_FRAME"; 43 | case AFD_FULL_FRAME_ALT: 44 | return "AFD_FULL_FRAME_ALT"; 45 | case AFD_16x9_CENTER: 46 | return "AFD_16x9_CENTER"; 47 | case AFD_14x9_CENTER: 48 | return "AFD_14x9_CENTER"; 49 | case AFD_4x3_WITH_ALTERNATIVE_14x9_CENTER: 50 | return "AFD_4x3_WITH_ALTERNATIVE_14x9_CENTER"; 51 | case AFD_16x9_WITH_ALTERNATIVE_14x9_CENTER: 52 | return "AFD_16x9_WITH_ALTERNATIVE_14x9_CENTER"; 53 | case AFD_16x9_WITH_ALTERNATIVE_4x3_CENTER: 54 | return "AFD_16x9_WITH_ALTERNATIVE_4x3_CENTER"; 55 | default: 56 | return "AFD_UNKNOWN"; 57 | } 58 | } 59 | 60 | const char *klvanc_aspectRatio_to_string(enum klvanc_payload_aspect_ratio_e ar) 61 | { 62 | switch(ar) { 63 | case ASPECT_4x3: 64 | return "ASPECT_4x3"; 65 | case ASPECT_16x9: 66 | return "ASPECT_16x9"; 67 | default: 68 | return "ASPECT_UNDEFINED"; 69 | } 70 | } 71 | 72 | const char *klvanc_barFlags_to_string(enum klvanc_payload_afd_barflags flags) 73 | { 74 | switch(flags) { 75 | case BARS_NONE: 76 | return "NONE"; 77 | case BARS_TOPBOTTOM: 78 | return "Top/Bottom"; 79 | case BARS_LEFTRIGHT: 80 | return "Left/Right"; 81 | default: 82 | return "INVALID"; 83 | } 84 | } 85 | 86 | int klvanc_dump_AFD(struct klvanc_context_s *ctx, void *p) 87 | { 88 | if (ctx->verbose) 89 | PRINT_DEBUG("%s()\n", __func__); 90 | 91 | struct klvanc_packet_afd_s *pkt = p; 92 | 93 | PRINT_DEBUG("%s() AFD: %s (%d) Aspect Ratio: %s Bar Flags: %s (0x%x)\n", __func__, 94 | klvanc_afd_to_string(pkt->afd), 95 | pkt->afd, 96 | klvanc_aspectRatio_to_string(pkt->aspectRatio), 97 | klvanc_barFlags_to_string(pkt->barDataFlags), 98 | pkt->barDataFlags); 99 | 100 | /* Sec 6.1 - For the two pairs of top/bottom and left/right, either both have 101 | - to be set or neither */ 102 | if ((pkt->barDataFlags & 0x0c) == 0x08 || (pkt->barDataFlags & 0x0c) == 0x04) 103 | PRINT_DEBUG(" INVALID top/bottom pairing"); 104 | 105 | if ((pkt->barDataFlags & 0x03) == 0x02 || (pkt->barDataFlags & 0x03) == 0x01) 106 | PRINT_DEBUG(" INVALID left right pairing"); 107 | 108 | /* Make sure there isn't some illegal combination of horizontal/vertical 109 | bits enabled (either top/bottom have to be enabled or left/right, but 110 | it can't be both) */ 111 | if ((pkt->barDataFlags & 0x0c) && (pkt->barDataFlags & 0x03)) 112 | PRINT_DEBUG(" INVALID both horizontal/vertical bar flags set"); 113 | 114 | /* Depending on which flags are set dictate which of the two values 115 | contains a given value */ 116 | if (pkt->barDataFlags == BARS_TOPBOTTOM) { 117 | PRINT_DEBUG(" Top bar = %d\n", pkt->top); 118 | PRINT_DEBUG(" Bottom bar = %d\n", pkt->bottom); 119 | } 120 | if (pkt->barDataFlags == BARS_LEFTRIGHT) { 121 | PRINT_DEBUG(" Left bar = %d\n", pkt->left); 122 | PRINT_DEBUG(" Right bar = %d\n", pkt->right); 123 | } 124 | 125 | return KLAPI_OK; 126 | } 127 | 128 | int parse_AFD(struct klvanc_context_s *ctx, 129 | struct klvanc_packet_header_s *hdr, void **pp) 130 | { 131 | if (ctx->callbacks == NULL || ctx->callbacks->afd == NULL) 132 | return KLAPI_OK; 133 | 134 | if (ctx->verbose) 135 | PRINT_DEBUG("%s()\n", __func__); 136 | 137 | struct klvanc_packet_afd_s *pkt = calloc(1, sizeof(*pkt)); 138 | if (!pkt) 139 | return -ENOMEM; 140 | 141 | memcpy(&pkt->hdr, hdr, sizeof(*hdr)); 142 | unsigned char afd = (sanitizeWord(hdr->payload[0]) >> 3) & 0x0f; 143 | 144 | pkt->afd = afd; 145 | 146 | if (sanitizeWord(hdr->payload[0]) & 0x04) 147 | pkt->aspectRatio = ASPECT_16x9; 148 | else 149 | pkt->aspectRatio = ASPECT_4x3; 150 | 151 | pkt->barDataFlags = sanitizeWord(hdr->payload[3]) >> 4; 152 | if (pkt->barDataFlags == BARS_TOPBOTTOM) { 153 | pkt->top = sanitizeWord(hdr->payload[4]) << 8; 154 | pkt->top |= sanitizeWord(hdr->payload[5]); 155 | pkt->bottom = sanitizeWord(hdr->payload[6]) << 8; 156 | pkt->bottom |= sanitizeWord(hdr->payload[7]); 157 | } else if (pkt->barDataFlags == BARS_LEFTRIGHT) { 158 | pkt->left = sanitizeWord(hdr->payload[4]) << 8; 159 | pkt->left |= sanitizeWord(hdr->payload[5]); 160 | pkt->right = sanitizeWord(hdr->payload[6]) << 8; 161 | pkt->right |= sanitizeWord(hdr->payload[7]); 162 | } 163 | 164 | ctx->callbacks->afd(ctx->callback_context, ctx, pkt); 165 | 166 | *pp = pkt; 167 | return KLAPI_OK; 168 | } 169 | 170 | int klvanc_create_AFD(struct klvanc_packet_afd_s **pkt) 171 | { 172 | struct klvanc_packet_afd_s *p = calloc(1, sizeof(*p)); 173 | if (p == NULL) 174 | return -ENOMEM; 175 | 176 | *pkt = p; 177 | return 0; 178 | } 179 | 180 | void klvanc_destroy_AFD(struct klvanc_packet_afd_s *pkt) 181 | { 182 | free(pkt); 183 | } 184 | 185 | static int klvanc_verify_afd_value(enum klvanc_payload_afd_e afd) 186 | { 187 | switch(afd) { 188 | case AFD_UNDEFINED: 189 | case AFD_BOX_16x9_TOP: 190 | case AFD_BOX_14x9_TOP: 191 | case AFD_BOX_16x9_CENTER: 192 | case AFD_FULL_FRAME: 193 | case AFD_FULL_FRAME_ALT: 194 | case AFD_16x9_CENTER: 195 | case AFD_14x9_CENTER: 196 | case AFD_4x3_WITH_ALTERNATIVE_14x9_CENTER: 197 | case AFD_16x9_WITH_ALTERNATIVE_14x9_CENTER: 198 | case AFD_16x9_WITH_ALTERNATIVE_4x3_CENTER: 199 | return 1; 200 | default: 201 | return 0; 202 | } 203 | } 204 | 205 | int klvanc_set_AFD_val(struct klvanc_packet_afd_s *pkt, unsigned char val) 206 | { 207 | if (!klvanc_verify_afd_value(val)) 208 | return -1; 209 | 210 | pkt->afd = val; 211 | return 0; 212 | } 213 | 214 | int klvanc_convert_AFD_to_packetBytes(struct klvanc_packet_afd_s *pkt, uint8_t **bytes, uint16_t *byteCount) 215 | { 216 | unsigned char afd; 217 | 218 | if (!pkt || !bytes) { 219 | return -1; 220 | } 221 | 222 | struct klbs_context_s *bs = klbs_alloc(); 223 | if (bs == NULL) 224 | return -ENOMEM; 225 | 226 | *bytes = malloc(255); 227 | if (*bytes == NULL) { 228 | klbs_free(bs); 229 | return -ENOMEM; 230 | } 231 | 232 | /* Serialize the AFD struct into a binary blob */ 233 | klbs_write_set_buffer(bs, *bytes, 255); 234 | 235 | afd = pkt->afd << 3; 236 | if (pkt->aspectRatio == ASPECT_16x9) 237 | afd |= 0x04; 238 | 239 | klbs_write_bits(bs, afd, 8); 240 | klbs_write_bits(bs, 0x00, 8); /* Reserved */ 241 | klbs_write_bits(bs, 0x00, 8); /* Reserved */ 242 | klbs_write_bits(bs, pkt->barDataFlags << 4, 8); 243 | if (pkt->barDataFlags == BARS_TOPBOTTOM) { 244 | klbs_write_bits(bs, pkt->top, 16); 245 | klbs_write_bits(bs, pkt->bottom, 16); 246 | } else if (pkt->barDataFlags == BARS_LEFTRIGHT) { 247 | klbs_write_bits(bs, pkt->left, 16); 248 | klbs_write_bits(bs, pkt->right, 16); 249 | } else { 250 | klbs_write_bits(bs, 0x00, 32); 251 | } 252 | 253 | klbs_write_buffer_complete(bs); 254 | 255 | *byteCount = klbs_get_byte_count(bs); 256 | klbs_free(bs); 257 | 258 | return 0; 259 | } 260 | 261 | int klvanc_convert_AFD_to_words(struct klvanc_packet_afd_s *pkt, uint16_t **words, uint16_t *wordCount) 262 | { 263 | uint8_t *buf; 264 | uint16_t byteCount; 265 | int ret; 266 | 267 | ret = klvanc_convert_AFD_to_packetBytes(pkt, &buf, &byteCount); 268 | if (ret != 0) 269 | return ret; 270 | 271 | /* Create the final array of VANC bytes (with correct DID/SDID, 272 | checksum, etc) */ 273 | klvanc_sdi_create_payload(0x05, 0x41, buf, byteCount, words, wordCount, 10); 274 | 275 | free(buf); 276 | 277 | return 0; 278 | } 279 | -------------------------------------------------------------------------------- /src/core-packet-eia_608.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include "core-private.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | int klvanc_dump_EIA_608(struct klvanc_context_s *ctx, void *p) 31 | { 32 | struct klvanc_packet_eia_608_s *pkt = p; 33 | 34 | if (ctx->verbose) 35 | PRINT_DEBUG("%s() %p\n", __func__, (void *)pkt); 36 | 37 | PRINT_DEBUG("%s() EIA608: %02x %02x %02x : field %d line_offset %d cc_data_1 %02x cc_data_2 %02x\n", 38 | __func__, 39 | pkt->payload[0], 40 | pkt->payload[1], 41 | pkt->payload[2], 42 | pkt->field, 43 | pkt->line_offset, 44 | pkt->cc_data_1, 45 | pkt->cc_data_2); 46 | 47 | return KLAPI_OK; 48 | } 49 | 50 | int parse_EIA_608(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, void **pp) 51 | { 52 | 53 | if (ctx->callbacks == NULL || ctx->callbacks->eia_608 == NULL) 54 | return KLAPI_OK; 55 | 56 | if (ctx->verbose) 57 | PRINT_DEBUG("%s()\n", __func__); 58 | 59 | struct klvanc_packet_eia_608_s *pkt = calloc(1, sizeof(*pkt)); 60 | if (!pkt) 61 | return -ENOMEM; 62 | 63 | memcpy(&pkt->hdr, hdr, sizeof(*hdr)); 64 | 65 | /* Parsed */ 66 | pkt->payload[0] = hdr->payload[0]; 67 | pkt->payload[1] = hdr->payload[1]; 68 | pkt->payload[2] = hdr->payload[2]; 69 | 70 | /* See SMPTE ST 334-1:2015 Annex B */ 71 | if (pkt->payload[0] & 0x80) 72 | pkt->field = 0; 73 | else 74 | pkt->field = 1; 75 | pkt->line_offset = pkt->payload[0] & 0x1f; 76 | pkt->cc_data_1 = pkt->payload[1]; 77 | pkt->cc_data_2 = pkt->payload[2]; 78 | 79 | ctx->callbacks->eia_608(ctx->callback_context, ctx, pkt); 80 | 81 | *pp = pkt; 82 | return KLAPI_OK; 83 | } 84 | 85 | int klvanc_create_EIA_608(struct klvanc_packet_eia_608_s **pkt) 86 | { 87 | struct klvanc_packet_eia_608_s *p = calloc(1, sizeof(*p)); 88 | if (p == NULL) 89 | return -ENOMEM; 90 | 91 | *pkt = p; 92 | return 0; 93 | } 94 | 95 | void klvanc_destroy_EIA_608(struct klvanc_packet_eia_608_s *pkt) 96 | { 97 | free(pkt); 98 | } 99 | 100 | int klvanc_convert_EIA_608_to_packetBytes(struct klvanc_packet_eia_608_s *pkt, uint8_t **bytes, uint16_t *byteCount) 101 | { 102 | if (!pkt || !bytes) { 103 | return -1; 104 | } 105 | 106 | struct klbs_context_s *bs = klbs_alloc(); 107 | if (bs == NULL) 108 | return -ENOMEM; 109 | 110 | *bytes = malloc(255); 111 | if (*bytes == NULL) { 112 | klbs_free(bs); 113 | return -ENOMEM; 114 | } 115 | 116 | /* Serialize the struct into a binary blob */ 117 | klbs_write_set_buffer(bs, *bytes, 255); 118 | 119 | if (pkt->field == 0) 120 | klbs_write_bits(bs, 1, 1); 121 | else 122 | klbs_write_bits(bs, 0, 1); 123 | 124 | /* Reserved */ 125 | klbs_write_bits(bs, 0, 2); 126 | klbs_write_bits(bs, pkt->line_offset, 5); 127 | 128 | /* CC Payload */ 129 | klbs_write_bits(bs, pkt->cc_data_1, 8); 130 | klbs_write_bits(bs, pkt->cc_data_2, 8); 131 | 132 | klbs_write_buffer_complete(bs); 133 | 134 | *byteCount = klbs_get_byte_count(bs); 135 | klbs_free(bs); 136 | 137 | return 0; 138 | } 139 | 140 | int klvanc_convert_EIA_608_to_words(struct klvanc_packet_eia_608_s *pkt, uint16_t **words, uint16_t *wordCount) 141 | { 142 | uint8_t *buf; 143 | uint16_t byteCount; 144 | int ret; 145 | 146 | ret = klvanc_convert_EIA_608_to_packetBytes(pkt, &buf, &byteCount); 147 | if (ret != 0) 148 | return ret; 149 | 150 | /* Create the final array of VANC bytes (with correct DID/SDID, 151 | checksum, etc) */ 152 | klvanc_sdi_create_payload(0x02, 0x61, buf, byteCount, words, wordCount, 10); 153 | 154 | free(buf); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /src/core-packet-kl_u64le_counter.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include "core-private.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | int klvanc_create_KL_U64LE_COUNTER(struct klvanc_packet_kl_u64le_counter_s **pkt) 32 | { 33 | struct klvanc_packet_kl_u64le_counter_s *p = calloc(1, sizeof(*p)); 34 | if (p == NULL) 35 | return -ENOMEM; 36 | 37 | *pkt = p; 38 | return 0; 39 | } 40 | 41 | int klvanc_dump_KL_U64LE_COUNTER(struct klvanc_context_s *ctx, void *p) 42 | { 43 | if (ctx->verbose) 44 | PRINT_DEBUG("%s()\n", __func__); 45 | 46 | struct klvanc_packet_kl_u64le_counter_s *pkt = p; 47 | 48 | PRINT_DEBUG("%s() KL_U64LE_COUNTER: %" PRIu64 " [%" PRIx64 "]\n", __func__, pkt->counter, pkt->counter); 49 | 50 | return KLAPI_OK; 51 | } 52 | 53 | int parse_KL_U64LE_COUNTER(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, void **pp) 54 | { 55 | if (ctx->callbacks == NULL || ctx->callbacks->kl_i64le_counter == NULL) 56 | return KLAPI_OK; 57 | 58 | if (ctx->verbose) 59 | PRINT_DEBUG("%s()\n", __func__); 60 | 61 | struct klvanc_packet_kl_u64le_counter_s *pkt = calloc(1, sizeof(*pkt)); 62 | if (!pkt) 63 | return -ENOMEM; 64 | 65 | memcpy(&pkt->hdr, hdr, sizeof(*hdr)); 66 | 67 | pkt->counter = 0; 68 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[0]) << 56; 69 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[1]) << 48; 70 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[2]) << 40; 71 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[3]) << 32; 72 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[4]) << 24; 73 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[5]) << 16; 74 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[6]) << 8; 75 | pkt->counter |= (uint64_t)sanitizeWord(hdr->payload[7]); 76 | 77 | ctx->callbacks->kl_i64le_counter(ctx->callback_context, ctx, pkt); 78 | 79 | *pp = pkt; 80 | return KLAPI_OK; 81 | } 82 | 83 | int klvanc_convert_KL_U64LE_COUNTER_to_words(struct klvanc_packet_kl_u64le_counter_s *pkt, 84 | uint16_t **words, uint16_t *wordCount) 85 | { 86 | uint8_t buf[8]; 87 | buf[0] = pkt->counter >> 56; 88 | buf[1] = pkt->counter >> 48; 89 | buf[2] = pkt->counter >> 40; 90 | buf[3] = pkt->counter >> 32; 91 | buf[4] = pkt->counter >> 24; 92 | buf[5] = pkt->counter >> 16; 93 | buf[6] = pkt->counter >> 8; 94 | buf[7] = pkt->counter; 95 | 96 | /* Create the final array of VANC bytes (with correct DID/SDID, 97 | checksum, etc) */ 98 | klvanc_sdi_create_payload(0xfe, 0x40, buf, sizeof(buf), words, wordCount, 10); 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /src/core-packet-sdp.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "core-private.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // Find spec at 11 | 12 | int klvanc_dump_SDP(struct klvanc_context_s *ctx, void *p) 13 | { 14 | if (ctx->verbose) 15 | PRINT_DEBUG("%s()\n", __func__); 16 | 17 | struct klvanc_packet_sdp_s *pkt = p; 18 | PRINT_DEBUG("Subtitle Description Packet struct\n"); 19 | PRINT_DEBUG_MEMBER_INT(pkt->identifier) 20 | PRINT_DEBUG_MEMBER_INT(pkt->format_code); 21 | 22 | for (int i = 0; i < 5; ++i) { 23 | PRINT_DEBUG_MEMBER_INT(pkt->descriptors[i].line); 24 | PRINT_DEBUG_MEMBER_INT(pkt->descriptors[i].field); 25 | for (int j = 0; j < 45; ++j) { 26 | PRINT_DEBUG(" %02x", pkt->descriptors[i].data[j]); 27 | } 28 | PRINT_DEBUG("\n"); 29 | } 30 | 31 | PRINT_DEBUG_MEMBER_INT(pkt->sequence_counter); 32 | PRINT_DEBUG("\n"); 33 | 34 | return KLAPI_OK; 35 | } 36 | 37 | int parse_SDP(struct klvanc_context_s *ctx, 38 | struct klvanc_packet_header_s *hdr, void **pp) 39 | { 40 | int i; 41 | int payloadBIndex = 0; 42 | 43 | if (ctx->callbacks == NULL || ctx->callbacks->sdp == NULL) 44 | return KLAPI_OK; 45 | 46 | if (ctx->verbose) 47 | PRINT_DEBUG("%s()\n", __func__); 48 | 49 | if (((hdr->payload[0] & 0x0ff) != 0x51) 50 | || ((hdr->payload[1] & 0x0ff) != 0x15)) { 51 | // if (ctx->verbose) 52 | PRINT_ERR 53 | ("Identifiers for Subtitling Description Packet don't match: %x %x\n", 54 | hdr->payload[0], hdr->payload[1]); 55 | return -EINVAL; 56 | } 57 | 58 | struct klvanc_packet_sdp_s *pkt = calloc(1, sizeof(*pkt)); 59 | if (!pkt) 60 | return -ENOMEM; 61 | 62 | memcpy(&pkt->hdr, hdr, sizeof(*hdr)); 63 | uint8_t length = hdr->payload[2] & 0x00ff; 64 | 65 | pkt->identifier = 66 | ((uint16_t) (hdr->payload[0] & 0xff)) << 8 | (hdr-> 67 | payload[1] & 0xff); 68 | 69 | pkt->format_code = hdr->payload[3] & 0xff; 70 | for (i = 0; (i < length - 4 - 4) && (i < 5); ++i) { 71 | pkt->descriptors[i].line = hdr->payload[4 + i] & 0x1f; 72 | pkt->descriptors[i].field = (hdr->payload[4 + i] & 0x80) >> 7; 73 | if ((hdr->payload[4 + i] & 0xff) != 0x00) { 74 | for (int j = 0; j < 45; ++j) 75 | pkt->descriptors[i].data[j] = 76 | hdr->payload[9 + (45 * payloadBIndex) + j]; 77 | payloadBIndex++; 78 | } 79 | } 80 | 81 | pkt->sequence_counter = 82 | ((uint16_t) (hdr->payload[9 + (45 * payloadBIndex) + 1] & 0xff) << 83 | 8) | (hdr->payload[9 + (45 * payloadBIndex) + 2] & 0xff); 84 | 85 | ctx->callbacks->sdp(ctx->callback_context, ctx, pkt); 86 | 87 | *pp = pkt; 88 | return KLAPI_OK; 89 | } 90 | 91 | int klvanc_create_SDP(struct klvanc_packet_sdp_s **pkt) 92 | { 93 | struct klvanc_packet_sdp_s *p = calloc(1, sizeof(*p)); 94 | if (p == NULL) 95 | return -ENOMEM; 96 | 97 | *pkt = p; 98 | return 0; 99 | } 100 | 101 | void klvanc_destroy_SDP(struct klvanc_packet_sdp_s *pkt) 102 | { 103 | free(pkt); 104 | } 105 | -------------------------------------------------------------------------------- /src/core-packet-smpte_2108_1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include "core-private.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | static const char *lookupFrameType(unsigned char frame_type) 32 | { 33 | switch (frame_type) { 34 | case 0x00: return "Static Metadata Type 1 (Mastering display color volume)"; 35 | case 0x01: return "Static Metadata Type 2 (Content light level information)"; 36 | case 0x02: return "Dynamic Metadata Type 1 (ATSC A/341 ST 2094-10_data)"; 37 | case 0x06: return "Dynamic Metadata Type 5 (SL-HDR information)"; 38 | default: return "Reserved"; 39 | } 40 | } 41 | 42 | int klvanc_dump_SMPTE_2108_1(struct klvanc_context_s *ctx, void *p) 43 | { 44 | struct klvanc_packet_smpte_2108_1_s *pkt = p; 45 | char *colorchan = "GBR"; 46 | 47 | if (ctx->verbose) 48 | PRINT_DEBUG("%s() %p\n", __func__, (void *)pkt); 49 | 50 | for (int n = 0; n < pkt->num_frames; n++) { 51 | struct klvanc_s2108_1_frame *frame = &pkt->frames[n]; 52 | PRINT_DEBUG(" frame_type = 0x%02x - %s\n", frame->frame_type, lookupFrameType(frame->frame_type)); 53 | PRINT_DEBUG(" frame_length = 0x%02x\n", frame->frame_length); 54 | 55 | if (frame->frame_type == KLVANC_HDR_STATIC1) { 56 | for (int i = 0; i < 3; i++) { 57 | uint16_t val = frame->static1.display_primaries_x[i]; 58 | PRINT_DEBUG(" display_primaries_x[%d] = %d (%c: %f)\n", i, val, colorchan[i], (float)val * 0.00002); 59 | val = frame->static1.display_primaries_y[i]; 60 | PRINT_DEBUG(" display_primaries_y[%d] = %d (%c: %f)\n", i, val, colorchan[i], (float)val * 0.00002); 61 | } 62 | 63 | PRINT_DEBUG(" white_point_x = %d (%f)\n", frame->static1.white_point_x, 64 | (float)frame->static1.white_point_x * 0.00002); 65 | PRINT_DEBUG(" white_point_y = %d (%f)\n", frame->static1.white_point_y, 66 | (float)frame->static1.white_point_y * 0.00002); 67 | PRINT_DEBUG(" max_display_mastering_luminance = %d (%f)\n", frame->static1.max_display_mastering_luminance, 68 | (float)frame->static1.max_display_mastering_luminance * 0.0001); 69 | PRINT_DEBUG(" min_display_mastering_luminance = %d (%f)\n", frame->static1.min_display_mastering_luminance, 70 | (float)frame->static1.min_display_mastering_luminance * 0.0001); 71 | } else if (frame->frame_type == KLVANC_HDR_STATIC2) { 72 | PRINT_DEBUG(" max_content_light_level = %d\n", frame->static2.max_content_light_level); 73 | PRINT_DEBUG(" max_pic_average_light_level = %d\n", frame->static2.max_pic_average_light_level); 74 | } else { 75 | PRINT_DEBUG(" Decoding of frame type 0x%02x not supported\n", frame->frame_type); 76 | } 77 | } 78 | 79 | return KLAPI_OK; 80 | } 81 | 82 | int parse_SMPTE_2108_1(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, void **pp) 83 | { 84 | struct klbs_context_s *bs; 85 | 86 | if (ctx->callbacks == NULL || ctx->callbacks->smpte_2108_1 == NULL) 87 | return KLAPI_OK; 88 | 89 | bs = klbs_alloc(); 90 | if (bs == NULL) 91 | return -ENOMEM; 92 | 93 | if (ctx->verbose) 94 | PRINT_DEBUG("%s()\n", __func__); 95 | 96 | struct klvanc_packet_smpte_2108_1_s *pkt = calloc(1, sizeof(*pkt)); 97 | if (!pkt) { 98 | klbs_free(bs); 99 | return -ENOMEM; 100 | } 101 | 102 | memcpy(&pkt->hdr, hdr, sizeof(*hdr)); 103 | 104 | /* Extract the 8-bit bitstream from the 10-bit payload */ 105 | for (int i = 0; i < hdr->payloadLengthWords; i++) { 106 | pkt->payload[i] = hdr->payload[i]; 107 | } 108 | pkt->payloadLengthBytes = hdr->payloadLengthWords; 109 | 110 | /* Parse the bitstream */ 111 | klbs_read_set_buffer(bs, pkt->payload, pkt->payloadLengthBytes); 112 | 113 | while (klbs_get_byte_count_free(bs) > 0) { 114 | struct klvanc_s2108_1_frame *frame = &pkt->frames[pkt->num_frames]; 115 | if (klbs_get_byte_count_free(bs) < 2) { 116 | /* Not enough to read type and length? malformed */ 117 | break; 118 | } 119 | 120 | frame->frame_type = klbs_read_bits(bs, 8); 121 | frame->frame_length = klbs_read_bits(bs, 8); 122 | 123 | if (klbs_get_byte_count_free(bs) < frame->frame_length) { 124 | /* Not enough to read payload? malformed */ 125 | break; 126 | } 127 | 128 | /* Skip SEI payload type and SEI payload length */ 129 | klbs_read_bits(bs, 16); 130 | 131 | if (frame->frame_type == KLVANC_HDR_STATIC1) { 132 | for (int i = 0; i < 3; i++) { 133 | frame->static1.display_primaries_x[i] = klbs_read_bits(bs, 16); 134 | frame->static1.display_primaries_y[i] = klbs_read_bits(bs, 16); 135 | } 136 | frame->static1.white_point_x = klbs_read_bits(bs, 16); 137 | frame->static1.white_point_y = klbs_read_bits(bs, 16); 138 | frame->static1.max_display_mastering_luminance = klbs_read_bits(bs, 32); 139 | frame->static1.min_display_mastering_luminance = klbs_read_bits(bs, 32); 140 | } else if (frame->frame_type == KLVANC_HDR_STATIC2) { 141 | frame->static2.max_content_light_level = klbs_read_bits(bs, 16); 142 | frame->static2.max_pic_average_light_level = klbs_read_bits(bs, 16); 143 | } else { 144 | klbs_read_bits(bs, 8 * (frame->frame_length - 2)); 145 | } 146 | pkt->num_frames++; 147 | } 148 | 149 | ctx->callbacks->smpte_2108_1(ctx->callback_context, ctx, pkt); 150 | 151 | klbs_free(bs); 152 | 153 | *pp = pkt; 154 | return KLAPI_OK; 155 | } 156 | -------------------------------------------------------------------------------- /src/core-pixels.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | #include "core-private.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #define av_le2ne32(x) (x) 32 | 33 | #define READ_PIXELS(a, b, c) \ 34 | do { \ 35 | val = av_le2ne32( *src++ ); \ 36 | *a++ = val & 0x3ff; \ 37 | *b++ = (val >> 10) & 0x3ff; \ 38 | *c++ = (val >> 20) & 0x3ff; \ 39 | } while (0) 40 | 41 | void klvanc_v210_planar_unpack_c(const uint32_t * src, uint16_t * y, uint16_t * u, uint16_t * v, int width) 42 | { 43 | uint32_t val; 44 | 45 | for (int i = 0; i < width - 5; i += 6) { 46 | READ_PIXELS(u, y, v); 47 | READ_PIXELS(y, u, y); 48 | READ_PIXELS(v, y, u); 49 | READ_PIXELS(y, v, y); 50 | } 51 | } 52 | 53 | /* Convert v210 to the native HD-SDI pixel format. 54 | * bmdFormat10BitYUV :‘v210’4:2:2Representation 55 | * Twelve 10-bit unsigned components are packed into four 32-bit little-endian words. 56 | * See BlackMagic SDK page 280 for a detailed description. 57 | */ 58 | int klvanc_v210_line_to_nv20_c(const uint32_t * src, uint16_t * dst, int dstSizeBytes, int width) 59 | { 60 | if (!src || !dst || !width) 61 | return -1; 62 | 63 | if (dstSizeBytes < (width * 6)) 64 | return -1; 65 | 66 | int w; 67 | uint32_t val = 0; 68 | uint16_t *uv = dst + width; 69 | for (w = 0; w < (width - 5); w += 6) { 70 | READ_PIXELS(uv, dst, uv); 71 | READ_PIXELS(dst, uv, dst); 72 | READ_PIXELS(uv, dst, uv); 73 | READ_PIXELS(dst, uv, dst); 74 | } 75 | 76 | if (w < width - 1) { 77 | READ_PIXELS(uv, dst, uv); 78 | 79 | val = av_le2ne32(*src++); 80 | *dst++ = val & 0x3ff; 81 | } 82 | 83 | if (w < width - 3) { 84 | *uv++ = (val >> 10) & 0x3ff; 85 | *dst++ = (val >> 20) & 0x3ff; 86 | 87 | val = av_le2ne32(*src++); 88 | *uv++ = val & 0x3ff; 89 | *dst++ = (val >> 10) & 0x3ff; 90 | } 91 | 92 | return 0; 93 | } 94 | 95 | /* Downscale 10-bit lines to 8-bit lines for processing by libzvbi. 96 | * Width is always 720*2 samples */ 97 | void klvanc_v210_downscale_line_c(uint16_t * src, uint8_t * dst, int lines) 98 | { 99 | for (int i = 0; i < 720 * 2 * lines; i++) 100 | dst[i] = src[i] >> 2; 101 | } 102 | 103 | /* Convert v210 to the native SD-SDI pixel format. 104 | * Width is always 720 samples */ 105 | 106 | /* 107 | https://msdn.microsoft.com/en-us/library/windows/desktop/bb970578(v=vs.85).aspx#_420formats 108 | https://developer.apple.com/library/mac/technotes/tn2162/_index.html#//apple_ref/doc/uid/DTS40013070-CH1-TNTAG8-V210__4_2_2_COMPRESSION_TYPE 109 | y0-5 = Y 110 | cb0-2 = U 111 | cr0-2 = V 112 | XXnn nnnn nnnn bbbb bbbb bbaa aaaa aaaa 113 | */ 114 | void klvanc_v210_line_to_uyvy_c(const uint32_t * src, uint16_t * dst, int width) 115 | { 116 | uint32_t val; 117 | for (int i = 0; i < width; i += 6) { 118 | READ_PIXELS(dst, dst, dst); 119 | READ_PIXELS(dst, dst, dst); 120 | READ_PIXELS(dst, dst, dst); 121 | READ_PIXELS(dst, dst, dst); 122 | } 123 | } 124 | 125 | static inline void put_le32(uint8_t **p, uint32_t d) 126 | { 127 | uint32_t **x = (uint32_t **) p; 128 | **x = av_le2ne32(d); 129 | (*p) += 4; 130 | } 131 | 132 | void klvanc_y10_to_v210(uint16_t *src, uint8_t *dst, int width) 133 | { 134 | size_t len = width / 6; 135 | size_t w; 136 | 137 | for (w = 0; w < len; w++) { 138 | put_le32(&dst, 0x200 | (src[w * 6 + 0] << 10) | (0x200 << 20)); 139 | put_le32(&dst, src[w * 6 + 1] | (0x200 << 10) | (src[w * 6 + 2] << 20)); 140 | put_le32(&dst, 0x200 | (src[w * 6 + 3] << 10) | (0x200 << 20)); 141 | put_le32(&dst, src[w * 6 + 4] | (0x200 << 10) | (src[w * 6 + 5] << 20)); 142 | } 143 | 144 | /* Handle remaining 0-5 bytes if any */ 145 | if (width % 6 > 0) 146 | put_le32(&dst, 0x200 | (src[w * 6 + 0] << 10) | (0x200 << 20)); 147 | if (width % 6 > 2) 148 | put_le32(&dst, src[w * 6 + 1] | (0x200 << 10) | (src[w * 6 + 2] << 20)); 149 | else if (width % 6 > 1) 150 | put_le32(&dst, src[w * 6 + 1] | (0x200 << 10) | (0x040 << 20)); 151 | if (width % 6 > 3) 152 | put_le32(&dst, 0x200 | (src[w * 6 + 3] << 10) | (0x200 << 20)); 153 | if (width % 6 > 4) 154 | put_le32(&dst, src[w * 6 + 4] | (0x200 << 10) | (0x040 << 20)); 155 | } 156 | 157 | void klvanc_uyvy_to_v210(uint16_t *src, uint8_t *dst, int width) 158 | { 159 | size_t len = width / 12; 160 | size_t w; 161 | 162 | for (w = 0; w < len; w++) { 163 | put_le32(&dst, (src[w * 12 + 0]) | 164 | (src[w * 12 + 1] << 10) | 165 | (src[w * 12 + 2] << 20)); 166 | put_le32(&dst, (src[w * 12 + 3]) | 167 | (src[w * 12 + 4] << 10) | 168 | (src[w * 12 + 5] << 20)); 169 | put_le32(&dst, (src[w * 12 + 6]) | 170 | (src[w * 12 + 7] << 10) | 171 | (src[w * 12 + 8] << 20)); 172 | put_le32(&dst, (src[w * 12 + 9]) | 173 | (src[w * 12 + 10] << 10) | 174 | (src[w * 12 + 11] << 20)); 175 | } 176 | 177 | /* Handle remaining 0-11 bytes if any */ 178 | if (width % 12 > 2) 179 | put_le32(&dst, (src[w * 12 + 0]) | 180 | (src[w * 12 + 1] << 10) | 181 | (src[w * 12 + 2] << 20)); 182 | else if (width % 12 > 1) 183 | put_le32(&dst, (src[w * 12 + 0]) | 184 | (src[w * 12 + 1] << 10) | 185 | (0x200 << 20)); 186 | else if (width % 12 > 0) 187 | put_le32(&dst, (src[w * 12 + 0]) | 188 | (0x040 << 10) | 189 | (0x200 << 20)); 190 | 191 | if (width % 12 > 5) 192 | put_le32(&dst, (src[w * 12 + 3]) | 193 | (src[w * 12 + 4] << 10) | 194 | (src[w * 12 + 5] << 20)); 195 | else if (width % 12 > 4) 196 | put_le32(&dst, (src[w * 12 + 3]) | 197 | (src[w * 12 + 4] << 10) | 198 | (0x040 << 20)); 199 | else if (width % 12 > 3) 200 | put_le32(&dst, (src[w * 12 + 3]) | 201 | (0x200 << 10) | 202 | (0x040 << 20)); 203 | 204 | 205 | if (width % 12 > 8) 206 | put_le32(&dst, (src[w * 12 + 6]) | 207 | (src[w * 12 + 7] << 10) | 208 | (src[w * 12 + 8] << 20)); 209 | else if (width % 12 > 7) 210 | put_le32(&dst, (src[w * 12 + 6]) | 211 | (src[w * 12 + 7] << 10) | 212 | (0x200 << 20)); 213 | else if (width % 12 > 6) 214 | put_le32(&dst, (src[w * 12 + 6]) | 215 | (0x040 << 10) | 216 | (0x200 << 20)); 217 | 218 | if (width % 12 > 10) 219 | put_le32(&dst, (src[w * 12 + 9]) | 220 | (src[w * 12 + 10] << 10) | 221 | (0x040 << 20)); 222 | else if (width % 12 > 9) 223 | put_le32(&dst, (src[w * 12 + 9]) | 224 | (0x200 << 10) | 225 | (0x040 << 20)); 226 | } 227 | -------------------------------------------------------------------------------- /src/core-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /* Not for inclusion by user applications */ 23 | 24 | #ifndef vanc_PRIVATE_H 25 | #define vanc_PRIVATE_H 26 | 27 | #include 28 | #include 29 | 30 | /* We'll have a mutex and a list of items */ 31 | #include 32 | #include "xorg-list.h" 33 | #include "klbitstream_readwriter.h" 34 | 35 | #define getPrivate(ctx) ((struct vanc_context_private_s *)ctx->priv) 36 | #define sanitizeWord(word) ((word) & 0xff) 37 | 38 | #define KLAPI_OK 0 39 | 40 | #define VALIDATE(ctx) \ 41 | if (!ctx) return -EINVAL; 42 | 43 | /* core-packet-afd.c */ 44 | int dump_AFD(struct klvanc_context_s *ctx, void *p); 45 | int parse_AFD(struct klvanc_context_s *ctx, 46 | struct klvanc_packet_header_s *hdr, void **pp); 47 | 48 | /* core-packet-eia_708b.c */ 49 | int dump_EIA_708B(struct klvanc_context_s *ctx, void *p); 50 | int parse_EIA_708B(struct klvanc_context_s *ctx, 51 | struct klvanc_packet_header_s *hdr, void **pp); 52 | 53 | /* core-packet-eia_608.c */ 54 | int dump_EIA_608(struct klvanc_context_s *ctx, void *p); 55 | int parse_EIA_608(struct klvanc_context_s *ctx, 56 | struct klvanc_packet_header_s *hdr, void **pp); 57 | 58 | /* core-packet-scte_104.c */ 59 | int dump_SCTE_104(struct klvanc_context_s *ctx, void *p); 60 | int parse_SCTE_104(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, 61 | void **pp); 62 | void cleanup_SCTE_104(struct klvanc_context_s *ctx); 63 | 64 | /* core-packet-kl_u64le_counter.c */ 65 | int dump_KL_U64LE_COUNTER(struct klvanc_context_s *ctx, void *p); 66 | int parse_KL_U64LE_COUNTER(struct klvanc_context_s *ctx, 67 | struct klvanc_packet_header_s *hdr, void **pp); 68 | 69 | void klvanc_dump_packet_console(struct klvanc_context_s *ctx, 70 | struct klvanc_packet_header_s *hdr); 71 | 72 | /* core-packet-sdp.c */ 73 | int dump_SDP(struct klvanc_context_s *ctx, void *p); 74 | int parse_SDP(struct klvanc_context_s *ctx, 75 | struct klvanc_packet_header_s *hdr, void **pp); 76 | 77 | /* core-packet-smpte_12_2.c */ 78 | int dump_SMPTE_12_2(struct klvanc_context_s *ctx, void *p); 79 | int parse_SMPTE_12_2(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, 80 | void **pp); 81 | 82 | /* core-packet-smpte_2108_1.c */ 83 | int dump_SMPTE_2108_1(struct klvanc_context_s *ctx, void *p); 84 | int parse_SMPTE_2108_1(struct klvanc_context_s *ctx, struct klvanc_packet_header_s *hdr, 85 | void **pp); 86 | 87 | 88 | /* We don't expect anything outside of the VANC framework to need toascii 89 | * call these, so we'll keep them private / internal calls. 90 | */ 91 | extern int klvanc_cache_alloc(struct klvanc_context_s *ctx); 92 | extern void klvanc_cache_free(struct klvanc_context_s *ctx); 93 | extern int klvanc_cache_update(struct klvanc_context_s *ctx, 94 | struct klvanc_packet_header_s *pkt); 95 | 96 | /* Logging Macros */ 97 | #define PRINT_ERR(...) if (ctx->log_cb) ctx->log_cb(NULL, LIBKLVANC_LOGLEVEL_ERR, __VA_ARGS__); 98 | #define PRINT_DEBUG(...) if (ctx->log_cb) ctx->log_cb(NULL, LIBKLVANC_LOGLEVEL_DEBUG, __VA_ARGS__); 99 | #define PRINT_DEBUG_MEMBER_INT(m) if (ctx->log_cb) ctx->log_cb(NULL, LIBKLVANC_LOGLEVEL_DEBUG, " %s = 0x%x\n", #m, m); 100 | #define PRINT_DEBUG_MEMBER_INTI(m, n) if (ctx->log_cb) ctx->log_cb(NULL, LIBKLVANC_LOGLEVEL_DEBUG, "%*c%s = 0x%x\n", n, ' ', #m, m); 101 | #define PRINT_DEBUG_MEMBER_INT64(m) if (ctx->log_cb) ctx->log_cb(NULL, LIBKLVANC_LOGLEVEL_DEBUG, " %s = 0x%" PRIx64 "\n", #m, m); 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /src/core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | 24 | #include "core-private.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /* Default logging implementation just writes to stderr */ 31 | static void vanc_default_logger(void *ctx, int level, const char *format, ...) 32 | { 33 | va_list args; 34 | va_start(args, format); 35 | vfprintf(stderr, format, args); 36 | va_end(args); 37 | } 38 | 39 | int klvanc_context_dump(struct klvanc_context_s *ctx) 40 | { 41 | VALIDATE(ctx); 42 | 43 | printf("ctx %p\n", (void *)ctx); 44 | 45 | return KLAPI_OK; 46 | } 47 | 48 | int klvanc_context_create(struct klvanc_context_s **ctx) 49 | { 50 | int ret = KLAPI_OK; 51 | 52 | struct klvanc_context_s *p = calloc(1, sizeof(struct klvanc_context_s)); 53 | if (!p) 54 | return -ENOMEM; 55 | 56 | /* If we fail to parse a vanc message, don't report more than one of those per second. */ 57 | klrestricted_code_path_block_initialize(&p->rcp_failedToDecode, 1, 1, 60 * 1000); 58 | 59 | if (ret == KLAPI_OK) 60 | *ctx = p; 61 | 62 | /* Set the default logger */ 63 | (*ctx)->log_cb = vanc_default_logger; 64 | 65 | return ret; 66 | } 67 | 68 | int klvanc_context_destroy(struct klvanc_context_s *ctx) 69 | { 70 | VALIDATE(ctx); 71 | 72 | klvanc_cache_free(ctx); 73 | 74 | cleanup_SCTE_104(ctx); 75 | 76 | memset(ctx, 0, sizeof(*ctx)); 77 | free(ctx); 78 | 79 | return KLAPI_OK; 80 | } 81 | 82 | int klvanc_context_enable_cache(struct klvanc_context_s *ctx) 83 | { 84 | if (klvanc_cache_alloc(ctx) < 0) { 85 | fprintf(stderr, "Unable to allocate vanc cache, enough free ram? Will continue.\n"); 86 | return -1; 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/libklvanc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libklvanc 7 | Description: Kernel Labs Library for processing Vertical Ancillary Data (VANC) 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -lklvanc 10 | Libs.private: -lpthread -lstdc++ -lm -lc 11 | Cflags: -I${includedir} -I${includedir}/libklvanc 12 | URL: https://github.com/stoth68000/libklvanc.git 13 | -------------------------------------------------------------------------------- /src/libklvanc/cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file cache.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved. 26 | * @brief VANC Caching functionality 27 | */ 28 | 29 | #ifndef _VANC_CACHE_H 30 | #define _VANC_CACHE_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | struct klvanc_cache_line_s 39 | { 40 | int active; 41 | uint64_t count; 42 | pthread_mutex_t mutex; 43 | struct klvanc_packet_header_s *pkt; 44 | }; 45 | 46 | struct klvanc_cache_s 47 | { 48 | uint32_t did, sdid; 49 | const char *desc, *spec; 50 | struct timeval lastUpdated; 51 | int hasCursor; 52 | int expandUI; 53 | int save; 54 | uint32_t activeCount; 55 | struct klvanc_cache_line_s lines[2048]; 56 | }; 57 | 58 | /** 59 | * @brief Begin caching and summarizing VANC payload, useful when you want to 60 | * query what VANC messages, and how many you seen on what lines. 61 | * @param[in] struct klvanc_context_s *ctx - Context. 62 | * @return 0 - Success 63 | * @return < 0 - Error 64 | */ 65 | int klvanc_context_enable_cache(struct klvanc_context_s *ctx); 66 | 67 | /** 68 | * @brief When caching and summarizing VANC payload is enabled, use this to reset any 69 | * internal counters, line counts and restart the stats collection process. 70 | * @param[in] struct klvanc_context_s *ctx - Context. 71 | * @return 0 - Success 72 | * @return < 0 - Error 73 | */ 74 | void klvanc_cache_reset(struct klvanc_context_s *ctx); 75 | 76 | /** 77 | * @brief When caching and summarizing VANC payload is enabled, lookup any statistics 78 | * related to didnr and sdidnr. 79 | * @param[in] struct klvanc_context_s *ctx - Context. 80 | * @return 0 - Success 81 | * @return < 0 - Error 82 | */ 83 | struct klvanc_cache_s * klvanc_cache_lookup(struct klvanc_context_s *ctx, uint8_t didnr, uint8_t sdidnr); 84 | 85 | #ifdef __cplusplus 86 | }; 87 | #endif 88 | 89 | #endif /* _VANC_CACHE_H */ 90 | -------------------------------------------------------------------------------- /src/libklvanc/did.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file did.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief Lookup functions that translate did/sdid into printable strings. 27 | */ 28 | 29 | #include 30 | 31 | /** 32 | * @brief For a given did, sdid, lookup a printable user description. 33 | * @param[in] uint16_t did - Brief description goes here. 34 | * @param[in] uint16_t sdid - Brief description goes here. 35 | * @return Success - User facing printable string. 36 | * @return Error - NULL 37 | */ 38 | const char * klvanc_didLookupDescription(uint16_t did, uint16_t sdid); 39 | 40 | /** 41 | * @brief For a given did, sdid, lookup the printable specification name. 42 | * @param[in] uint16_t did - Brief description goes here. 43 | * @param[in] uint16_t sdid - Brief description goes here. 44 | * @return Success - User facing printable string. 45 | * @return Error - NULL 46 | */ 47 | const char * klvanc_didLookupSpecification(uint16_t did, uint16_t sdid); 48 | -------------------------------------------------------------------------------- /src/libklvanc/klrestricted_code_path.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file klrestricted_code_path.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved. 26 | * @brief Generic code to limit the running of certain code to N times per second. 27 | * Primary use case is to prevent errors from spamming system logs. 28 | * User allocates a small context, context contains max latency.__msfr_align 29 | * Users asks whether its permitted to execute the code block, function determines answer. 30 | * First occurence is always allowed to execute. 31 | * 32 | * USAGE during initialization, allow messages only every 1000ms 33 | * struct klrestricted_code_path_block_s global_mypathXYZ; 34 | * klrestricted_code_path_block_initialize(&global_mypathXYZ, , 1, 1000); 35 | * 36 | * USAGE during runtime: 37 | * if (klrestricted_code_path_block_execute(&global_mypathXYZ)) 38 | * { 39 | * fprintf(stderr, "I logged a high volume message, but only once per second!\n"); 40 | * } 41 | */ 42 | 43 | #ifndef _KLRESTRICTED_CODE_PATH_H 44 | #define _KLRESTRICTED_CODE_PATH_H 45 | 46 | #include 47 | #include 48 | #include 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | struct klrestricted_code_path_block_s 55 | { 56 | int enableChecking; 57 | int id; 58 | uint64_t minimumIntervalMs; 59 | 60 | struct timeval lastExecuteTime; 61 | uint64_t countBlockEntered; 62 | uint64_t countBlockAvoided; 63 | }; 64 | 65 | static __inline__ int klrcp_timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) 66 | { 67 | /* Perform the carry for the later subtraction by updating y. */ 68 | if (x->tv_usec < y->tv_usec) 69 | { 70 | int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; 71 | y->tv_usec -= 1000000 * nsec; 72 | y->tv_sec += nsec; 73 | } 74 | if (x->tv_usec - y->tv_usec > 1000000) 75 | { 76 | int nsec = (x->tv_usec - y->tv_usec) / 1000000; 77 | y->tv_usec += 1000000 * nsec; 78 | y->tv_sec -= nsec; 79 | } 80 | 81 | /* Compute the time remaining to wait. tv_usec is certainly positive. */ 82 | result->tv_sec = x->tv_sec - y->tv_sec; 83 | result->tv_usec = x->tv_usec - y->tv_usec; 84 | 85 | /* Return 1 if result is negative. */ 86 | return x->tv_sec < y->tv_sec; 87 | } 88 | 89 | static __inline uint64_t klrcp_timediff_to_msecs(struct timeval *tv) 90 | { 91 | return (tv->tv_sec * 1000) + (tv->tv_usec / 1000); 92 | } 93 | 94 | static __inline__ void klrestricted_code_path_block_initialize(struct klrestricted_code_path_block_s *blk, int id, 95 | int enableChecking, uint64_t minimumIntervalMs) 96 | { 97 | memset(blk, 0, sizeof(*blk)); 98 | blk->id = id; 99 | blk->enableChecking = enableChecking; 100 | blk->minimumIntervalMs = minimumIntervalMs; 101 | }; 102 | 103 | static __inline__ int klrestricted_code_path_block_execute(struct klrestricted_code_path_block_s *blk) 104 | { 105 | if (blk->enableChecking == 0) { 106 | blk->countBlockEntered++; 107 | return 1; 108 | } 109 | 110 | struct timeval now, diff; 111 | gettimeofday(&now, 0); 112 | klrcp_timeval_subtract(&diff, &now, &blk->lastExecuteTime); 113 | if (klrcp_timediff_to_msecs(&diff) < blk->minimumIntervalMs) { 114 | blk->countBlockAvoided++; 115 | return 0; 116 | } 117 | 118 | blk->lastExecuteTime = now; 119 | blk->countBlockEntered++; 120 | return 1; 121 | } 122 | 123 | #ifdef __cplusplus 124 | }; 125 | #endif 126 | 127 | #endif /* _KLRESTRICTED_CODE_PATH_H */ 128 | -------------------------------------------------------------------------------- /src/libklvanc/pixels.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file pixels.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief Common colorspace conversion functions for VANC 27 | */ 28 | 29 | #ifndef _PIXELS_H 30 | #define _PIXELS_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @brief TODO - Brief description goes here. 40 | * @param[in] const uint32_t * src - Brief description goes here. 41 | * @param[in] uint16_t * y - Brief description goes here. 42 | * @param[in] uint16_t * u - Brief description goes here. 43 | * @param[in] uint16_t * v - Brief description goes here. 44 | * @param[in] int width - Brief description goes here. 45 | */ 46 | void klvanc_v210_planar_unpack_c(const uint32_t * src, uint16_t * y, uint16_t * u, uint16_t * v, int width); 47 | 48 | /** 49 | * @brief TODO - Brief description goes here. 50 | * @param[in] const uint32_t * src - Brief description goes here. 51 | * @param[in] uint16_t * dst - Brief description goes here. 52 | * @param[in] int dstSizeBytes - Size of the dst buffer allocation. 53 | * @param[in] int width - Brief description goes here. 54 | * @result 0 - Success 55 | * @result < 0 - Error 56 | */ 57 | int klvanc_v210_line_to_nv20_c(const uint32_t * src, uint16_t * dst, int dstSizeBytes, int width); 58 | 59 | /** 60 | * @brief TODO - Brief description goes here. 61 | * @param[in] uint16_t * src - Brief description goes here. 62 | * @param[in] uint8_t * dst - Brief description goes here. 63 | * @param[in] int lines - Brief description goes here. 64 | */ 65 | void klvanc_v210_downscale_line_c(uint16_t * src, uint8_t * dst, int lines); 66 | 67 | /** 68 | * @brief TODO - Brief description goes here. 69 | * @param[in] const uint32_t * src - Brief description goes here. 70 | * @param[in] uint16_t * dst - Brief description goes here. 71 | * @param[in] int width - Brief description goes here. 72 | */ 73 | void klvanc_v210_line_to_uyvy_c(const uint32_t * src, uint16_t * dst, int width); 74 | 75 | /** 76 | * @brief Convert Y10 buffer to V210 77 | * @param[in] uint16_t * src - Array of 16-bit fields containing 10-bit Y values 78 | * @param[out] uint8_t * dst - Destination containing resulting V210 video 79 | * @param[in] int width - Number of Y pixels in src 80 | */ 81 | void klvanc_y10_to_v210(uint16_t *src, uint8_t *dst, int width); 82 | 83 | /** 84 | * @brief Convert UYVY buffer to V210 85 | * @param[in] uint16_t * src - Array of 16-bit fields containing 10-bit YUV values 86 | * @param[out] uint8_t * dst - Destination containing resulting V210 video 87 | * @param[in] int width - Number of Y pixels in src 88 | */ 89 | void klvanc_uyvy_to_v210(uint16_t *src, uint8_t *dst, int width); 90 | 91 | #ifdef __cplusplus 92 | }; 93 | #endif 94 | 95 | #endif /* _PIXELS_H */ 96 | -------------------------------------------------------------------------------- /src/libklvanc/smpte2038.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file smpte2038.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief Functions to parse, create and inspect SMPTE2038 formatted packets. 27 | */ 28 | 29 | #ifndef SMPTE2038_H 30 | #define SMPTE2038_H 31 | 32 | #include 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** 40 | * @brief TODO - Brief description goes here. 41 | */ 42 | struct klvanc_smpte2038_anc_data_line_s 43 | { 44 | /* Based on data taken from the ADTEC EN-100 encodeer, 45 | * DID, SDID, DATA_COUNT, WORDS and CHECKSUM are 46 | * all marked with parity, don't forget to strip 47 | * bits 9:8 before you trust these values, esp. data_count. 48 | */ 49 | uint8_t reserved_000000; 50 | uint8_t c_not_y_channel_flag; 51 | uint16_t line_number; 52 | uint16_t horizontal_offset; 53 | uint16_t DID; 54 | uint16_t SDID; 55 | uint16_t data_count; 56 | uint16_t *user_data_words; 57 | uint16_t checksum_word; 58 | }; 59 | 60 | /** 61 | * @brief TODO - Brief description goes here. 62 | */ 63 | struct klvanc_smpte2038_anc_data_packet_s 64 | { 65 | uint32_t packet_start_code_prefix; 66 | uint8_t stream_id; 67 | uint16_t PES_packet_length; 68 | uint8_t reserved_10; 69 | uint8_t PES_scrambling_control; 70 | uint8_t PES_priority; 71 | uint8_t data_alignment_indicator; 72 | uint8_t copyright; 73 | uint8_t original_or_copy; 74 | uint8_t PTS_DTS_flags; 75 | uint8_t ESCR_flag; 76 | uint8_t ES_rate_flag; 77 | uint8_t DSM_trick_mode_flag; 78 | uint8_t additional_copy_info_flag; 79 | uint8_t PES_CRC_flag; 80 | uint8_t PES_extension_flag; 81 | uint8_t PES_header_data_length; 82 | uint8_t reserved_0010; 83 | uint64_t PTS; 84 | 85 | int lineCount; 86 | struct klvanc_smpte2038_anc_data_line_s *lines; 87 | }; 88 | 89 | /** 90 | * @brief Inspect a section, if its deemed valid, create a VANC packet and return it to the caller.\n 91 | * Typically this is a line of SDI data, 10bit video. We parse the content in this function,\n 92 | * if we find a VANC header signiture we'll create an ancillary packet to represet it,\n 93 | * we'll attempt to parse the structure and return a user representation of it.\n\n 94 | * Callers must release the returned struct using klvanc_smpte2038_anc_data_packet_free(). 95 | * @param[in] uint8_t *section - An array of memory that likely contains a valic (or invalid) VANC message. 96 | * @param[in] unsigned int byteCount - Length of section. 97 | * @param[out] struct klvanc_smpte2038_anc_data_packet_s **result - Packet 98 | * @result 0 - Success, **result is valid for future use. 99 | * @result < 0 - Error 100 | */ 101 | int klvanc_smpte2038_parse_pes_packet(uint8_t *section, unsigned int byteCount, struct klvanc_smpte2038_anc_data_packet_s **result); 102 | 103 | /** 104 | * @brief Inspect a section payload. This function is identical to klvanc_smpte2038_parse_pes_packet(),\n 105 | * except it takes just the payload section of a section, rather than the full section which\n 106 | * would include the section headers (e.g. start code prefix, stream id, etc). This routine\n 107 | * is for use in cases where the calling application is responsible for parsing the PES and\n 108 | * only hands off the payload section to decoders (such as the mpegts demux in libavformat).\n\n 109 | * Callers must release the returned struct using klvanc_smpte2038_anc_data_packet_free(). 110 | * @param[in] uint8_t *section - An array of memory that likely contains a valic (or invalid) VANC message. 111 | * @param[in] unsigned int byteCount - Length of section. 112 | * @param[out] struct klvanc_smpte2038_anc_data_packet_s **result - Packet 113 | * @result 0 - Success, **result is valid for future use. 114 | * @result < 0 - Error 115 | */ 116 | int klvanc_smpte2038_parse_pes_payload(uint8_t *payload, unsigned int byteCount, struct klvanc_smpte2038_anc_data_packet_s **result); 117 | 118 | /** 119 | * @brief Inspect structure and output textual information to console. 120 | * @param[in] struct klvanc_smpte2038_anc_data_packet_s *pkt - Packet 121 | */ 122 | void klvanc_smpte2038_anc_data_packet_dump(struct klvanc_smpte2038_anc_data_packet_s *h); 123 | 124 | /** 125 | * @brief Deallocate and release a previously allocated pkt, see klvanc_smpte2038_parse_section(). 126 | * @param[in] struct klvanc_smpte2038_anc_data_packet_s *pkt - Packet 127 | */ 128 | void klvanc_smpte2038_anc_data_packet_free(struct klvanc_smpte2038_anc_data_packet_s *pkt); 129 | 130 | /** 131 | * @brief TODO - Brief description goes here. 132 | */ 133 | struct klvanc_smpte2038_packetizer_s 134 | { 135 | uint8_t *buf; 136 | uint32_t buflen; 137 | uint32_t bufused; 138 | uint32_t buffree; 139 | struct klbs_context_s *bs; 140 | }; 141 | 142 | /** 143 | * @brief Allocate a context so we can use this with the rest of the library. 144 | * @param[out] struct klvanc_smpte2038_packetizer_s **ctx - Context 145 | * @return 0 - Success 146 | * @return < 0 - Error 147 | */ 148 | int klvanc_smpte2038_packetizer_alloc(struct klvanc_smpte2038_packetizer_s **ctx); 149 | 150 | /** 151 | * @brief Deallocate and release a previously allocated context, see klvanc_smpte2038_packetizer_alloc(). 152 | * @param[in] struct klvanc_smpte2038_packetizer_s **ctx - Context 153 | */ 154 | void klvanc_smpte2038_packetizer_free(struct klvanc_smpte2038_packetizer_s **ctx); 155 | 156 | /** 157 | * @brief Initialize state, typically done at the beginning of each incoming SDI frame\n 158 | * must be done before attempting to append decoded VANC packets. 159 | * @param[in] struct klvanc_smpte2038_packetizer_s **ctx - Context 160 | * @return 0 - Success 161 | * @return < 0 - Error 162 | */ 163 | int klvanc_smpte2038_packetizer_begin(struct klvanc_smpte2038_packetizer_s *ctx); 164 | 165 | /** 166 | * @brief TODO - Brief description goes here. 167 | * @param[in] struct klvanc_smpte2038_packetizer_s *ctx 168 | * @param[in] struct klvanc_packet_header_s *pkt 169 | * @return TODO. 170 | */ 171 | int klvanc_smpte2038_packetizer_append(struct klvanc_smpte2038_packetizer_s *ctx, 172 | struct klvanc_packet_header_s *pkt); 173 | 174 | /** 175 | * @brief Finalize VANC collection state. Typically done when the last VANC line in a frame\n 176 | * has been passed to klvanc_smpte2038_packetizer_append().\n 177 | * Don't attempt to append without first calling klvanc_smpte2038_packetizer_begin(). 178 | * @param[in] struct klvanc_smpte2038_packetizer_s **ctx - Context 179 | * @param[in] struct packet_header_s *pkt - A fully decoded VANC packet, from the vanc_*() callbacks. 180 | * @return 0 - Success 181 | * @return < 0 - Error 182 | */ 183 | int klvanc_smpte2038_packetizer_end(struct klvanc_smpte2038_packetizer_s *ctx, uint64_t pts); 184 | 185 | /** 186 | * @brief Convert type struct klvanc_smpte2038_anc_data_line_s into a more traditional line of\n 187 | * vanc words, so that we may push it into the vanc parser. 188 | * On success, caller MUST free the resulting *words array. 189 | * @param[in] struct klvanc_smpte2038_anc_data_line_s *line - A line of decomposed vanc, received from the SMPTE2038 parser. 190 | * @param[out] uint16_t **words - An array of words reppresenting a fully formed vanc line. 191 | * @param[out] uint16_t *wordCount - Number of words in the array. 192 | * @return 0 - Success 193 | * @return < 0 - Error 194 | * @return -ENOMEM - Not enough memory to satisfy request 195 | */ 196 | int klvanc_smpte2038_convert_line_to_words(struct klvanc_smpte2038_anc_data_line_s *l, uint16_t **words, uint16_t *wordCount); 197 | 198 | #ifdef __cplusplus 199 | }; 200 | #endif 201 | 202 | #endif /* SMPTE2038_H */ 203 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-afd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-afd.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief SMPTE 2016-3 Vertical Ancillary Data Mapping of Active Format Description and Bar Data 27 | */ 28 | 29 | #ifndef _VANC_AFD_H 30 | #define _VANC_AFD_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @brief TODO - Brief description goes here. 40 | */ 41 | enum klvanc_payload_aspect_ratio_e 42 | { 43 | ASPECT_UNDEFINED = 0, 44 | ASPECT_4x3, 45 | ASPECT_16x9, 46 | }; 47 | 48 | /** 49 | * @brief TODO - Brief description goes here. 50 | */ 51 | enum klvanc_payload_afd_e 52 | { 53 | AFD_UNDEFINED = 0x00, 54 | AFD_BOX_16x9_TOP = 0x02, 55 | AFD_BOX_14x9_TOP = 0x03, 56 | AFD_BOX_16x9_CENTER = 0x04, 57 | AFD_FULL_FRAME = 0x08, 58 | AFD_FULL_FRAME_ALT = 0x09, 59 | AFD_16x9_CENTER = 0x0a, 60 | AFD_14x9_CENTER = 0x0b, 61 | AFD_4x3_WITH_ALTERNATIVE_14x9_CENTER = 0x0d, 62 | AFD_16x9_WITH_ALTERNATIVE_14x9_CENTER = 0x0e, 63 | AFD_16x9_WITH_ALTERNATIVE_4x3_CENTER = 0x0f, 64 | }; 65 | 66 | enum klvanc_payload_afd_barflags { 67 | BARS_NONE = 0x00, 68 | BARS_LEFTRIGHT = 0x03, 69 | BARS_TOPBOTTOM = 0x0c, 70 | }; 71 | 72 | /** 73 | * @brief TODO - Brief description goes here. 74 | */ 75 | struct klvanc_packet_afd_s 76 | { 77 | struct klvanc_packet_header_s hdr; 78 | enum klvanc_payload_aspect_ratio_e aspectRatio; 79 | enum klvanc_payload_afd_e afd; 80 | enum klvanc_payload_afd_barflags barDataFlags; 81 | unsigned short top; 82 | unsigned short bottom; 83 | unsigned short left; 84 | unsigned short right; 85 | }; 86 | 87 | /** 88 | * @brief TODO - Brief description goes here. 89 | * @param[in] enum payload_afd_e afd - Brief description goes here. 90 | * @return Success - User facing printable string. 91 | * @return Error - NULL 92 | */ 93 | const char *klvanc_afd_to_string(enum klvanc_payload_afd_e afd); 94 | 95 | /** 96 | * @brief TODO - Brief description goes here. 97 | * @param[in] enum payload_aspect_ratio_e ar - Brief description goes here. 98 | * @return Success - User facing printable string. 99 | * @return Error - NULL 100 | */ 101 | const char *klvanc_aspectRatio_to_string(enum klvanc_payload_aspect_ratio_e ar); 102 | 103 | /** 104 | * @brief Return a string representing the bar flags field 105 | * @param[in] enum klvanc_payload_afd_barflags flags - Value of flags field 106 | * @return Success - User facing printable string. 107 | * @return Error - NULL 108 | */ 109 | const char *klvanc_barFlags_to_string(enum klvanc_payload_afd_barflags flags); 110 | 111 | /** 112 | * @brief TODO - Brief description goes here. 113 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 114 | * @return 0 - Success 115 | * @return < 0 - Error 116 | */ 117 | int klvanc_dump_AFD(struct klvanc_context_s *ctx, void *p); 118 | 119 | /** 120 | * @brief Create an AFD VANC packet 121 | * @param[out] struct klvanc_packet_afd_s **pkt - Pointer to newly created packet 122 | * @return 0 - Success 123 | * @return < 0 - Error 124 | */ 125 | int klvanc_create_AFD(struct klvanc_packet_afd_s **pkt); 126 | 127 | /** 128 | * @brief Destroy an AFD VANC packet 129 | * @param[in] struct klvanc_packet_afd_s *pkt - Packet to be destroyed 130 | */ 131 | void klvanc_destroy_AFD(struct klvanc_packet_afd_s *pkt); 132 | 133 | /** 134 | * @brief Set the AFD value on an AFD packet 135 | * @param[in] struct klvanc_packet_afd_s *pkt - Packet to be modified 136 | * @param[in] unsigned char val - Value to set the AFD field to 137 | * @return 0 - Success 138 | * @return < 0 - Unknown framerate specified 139 | */ 140 | int klvanc_set_AFD_val(struct klvanc_packet_afd_s *pkt, unsigned char val); 141 | 142 | /** 143 | * @brief Convert type struct klvanc_packet_afd_s into a more traditional line of\n 144 | * vanc words, so that we may push out as VANC data. 145 | * On success, caller MUST free the resulting *words array. 146 | * @param[in] struct klvanc_packet_afd_s *pkt - A AFD VANC entry 147 | * @param[out] uint16_t **words - An array of words representing a fully formed vanc line. 148 | * @param[out] uint16_t *wordCount - Number of words in the array. 149 | * @return 0 - Success 150 | * @return < 0 - Error 151 | * @return -ENOMEM - Not enough memory to satisfy request 152 | */ 153 | int klvanc_convert_AFD_to_words(struct klvanc_packet_afd_s *pkt, uint16_t **words, uint16_t *wordCount); 154 | 155 | /** 156 | * @brief Convert type struct klvanc_packet_afd_s into a block of bytes which represents\n 157 | * an AFD packet 158 | * On success, caller MUST free the resulting *bytes array. 159 | * @param[in] struct klvanc_packet_afd_s *pkt - A AFD VANC entry, received from the AFD parser 160 | * @param[out] uint8_t **bytes - An array of bytes representing the serialized AFD packet 161 | * @param[out] uint16_t *byteCount - Number of bytes in the array. 162 | * @return 0 - Success 163 | * @return < 0 - Error 164 | * @return -ENOMEM - Not enough memory to satisfy request 165 | */ 166 | int klvanc_convert_AFD_to_packetBytes(struct klvanc_packet_afd_s *pkt, uint8_t **bytes, uint16_t *byteCount); 167 | 168 | #ifdef __cplusplus 169 | }; 170 | #endif 171 | 172 | #endif /* _VANC_AFD_H */ 173 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-checksum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-checksum.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief VANC checksum routines 27 | */ 28 | 29 | /** 30 | * @brief TODO - Brief description goes here. 31 | * @param[in] uint16_t *words - Brief description goes here. 32 | * @param[in] int wordCount - Brief description goes here. 33 | */ 34 | uint16_t klvanc_checksum_calculate(const uint16_t *words, int wordCount); 35 | 36 | /** 37 | * @brief TODO - Brief description goes here. 38 | * @param[in] uint16_t *words - Brief description goes here. 39 | * @param[in] int wordCount - Brief description goes here. 40 | * @return 0 - Success 41 | * @return < 0 - Error 42 | */ 43 | int klvanc_checksum_is_valid(const uint16_t *words, int wordCount); 44 | 45 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-eia_608.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-eia_608.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief EIA/CEA-608 Closed Captions 27 | */ 28 | 29 | #ifndef _VANC_EIA_608_H 30 | #define _VANC_EIA_608_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @brief TODO - Brief description goes here. 40 | */ 41 | struct klvanc_packet_eia_608_s 42 | { 43 | struct klvanc_packet_header_s hdr; 44 | int nr; 45 | unsigned char payload[3]; 46 | 47 | /* Parsed */ 48 | int field; 49 | int line_offset; 50 | unsigned char cc_data_1; 51 | unsigned char cc_data_2; 52 | }; 53 | 54 | /** 55 | * @brief TODO - Brief description goes here. 56 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 57 | * @return 0 - Success 58 | * @return < 0 - Error 59 | */ 60 | int klvanc_dump_EIA_608(struct klvanc_context_s *ctx, void *p); 61 | 62 | /** 63 | * @brief Create an EIA-608 VANC packet 64 | * @param[out] struct klvanc_packet_eia_608_s **pkt - Pointer to newly created packet 65 | * @return 0 - Success 66 | * @return < 0 - Error 67 | */ 68 | int klvanc_create_EIA_608(struct klvanc_packet_eia_608_s **pkt); 69 | 70 | /** 71 | * @brief Destroy an EIA-608 VANC packet 72 | * @param[in] struct klvanc_packet_eia_608_s *pkt - Packet to be destroyed 73 | */ 74 | void klvanc_destroy_EIA_608(struct klvanc_packet_eia_608_s *pkt); 75 | 76 | /** 77 | * @brief Convert type struct klvanc_packet_eia_608_s into a block of bytes which represents\n 78 | * an EIA-608 packet (without DID/SDID/DC/checksum) 79 | * On success, caller MUST free the resulting *bytes array. 80 | * @param[in] struct klvanc_packet_eia_608_s *pkt - An EIA-608 VANC entry, received from the EIA-608 parser 81 | * @param[out] uint8_t **bytes - An array of bytes representing the serialized EIA-608 packet 82 | * @param[out] uint16_t *byteCount - Number of bytes in the array. 83 | * @return 0 - Success 84 | * @return < 0 - Error 85 | * @return -ENOMEM - Not enough memory to satisfy request 86 | */ 87 | int klvanc_convert_EIA_608_to_packetBytes(struct klvanc_packet_eia_608_s *pkt, uint8_t **bytes, uint16_t *byteCount); 88 | 89 | /** 90 | * @brief Convert type struct klvanc_packet_eia_608_s into a more traditional line of\n 91 | * vanc words, so that we may push out as VANC data. 92 | * On success, caller MUST free the resulting *words array. 93 | * @param[in] struct klvanc_packet_eia_608_s *pkt - A EIA-608 VANC entry 94 | * @param[out] uint16_t **words - An array of words representing a fully formed vanc line. 95 | * @param[out] uint16_t *wordCount - Number of words in the array. 96 | * @return 0 - Success 97 | * @return < 0 - Error 98 | * @return -ENOMEM - Not enough memory to satisfy request 99 | */ 100 | int klvanc_convert_EIA_608_to_words(struct klvanc_packet_eia_608_s *pkt, uint16_t **words, uint16_t *wordCount); 101 | 102 | #ifdef __cplusplus 103 | }; 104 | #endif 105 | 106 | #endif /* _VANC_EIA_608_H */ 107 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-eia_708b.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-eia_708b.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief CEA-708 Closed Captions 27 | */ 28 | 29 | #ifndef _VANC_EIA_708B_H 30 | #define _VANC_EIA_708B_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | 39 | struct klvanc_packet_eia_708b_cdp_header 40 | { 41 | uint16_t cdp_identifier; 42 | uint8_t cdp_length; 43 | uint8_t cdp_frame_rate; 44 | uint8_t time_code_present; 45 | uint8_t ccdata_present; 46 | uint8_t svcinfo_present; 47 | uint8_t svc_info_start; 48 | uint8_t svc_info_change; 49 | uint8_t svc_info_complete; 50 | uint8_t caption_service_active; 51 | uint16_t cdp_hdr_sequence_cntr;; 52 | }; 53 | 54 | struct klvanc_packet_eia_708b_time_code_section 55 | { 56 | uint8_t time_code_section_id; 57 | uint8_t tc_10hrs; 58 | uint8_t tc_1hrs; 59 | uint8_t tc_10min; 60 | uint8_t tc_1min; 61 | uint8_t tc_field_flag; 62 | uint8_t tc_10sec; 63 | uint8_t tc_1sec; 64 | uint8_t drop_frame_flag; 65 | uint8_t tc_10fr; 66 | uint8_t tc_1fr; 67 | }; 68 | 69 | struct klvanc_packet_eia_708b_ccdata_entry 70 | { 71 | uint8_t cc_valid; 72 | uint8_t cc_type; 73 | uint8_t cc_data[2]; 74 | }; 75 | 76 | #define KLVANC_MAX_CC_COUNT 30 77 | struct klvanc_packet_eia_708b_ccdata_section 78 | { 79 | uint8_t ccdata_id; 80 | uint8_t cc_count; 81 | struct klvanc_packet_eia_708b_ccdata_entry cc[KLVANC_MAX_CC_COUNT]; 82 | }; 83 | 84 | 85 | struct klvanc_packet_eia_708b_ccsvcinfo_entry 86 | { 87 | uint8_t caption_service_number; 88 | uint8_t svc_data_byte[6]; /* Raw bytes */ 89 | /* Decoding of svc_data_bytes defined in ATSC A/65 Sec 6.9.2 */ 90 | uint8_t language[4]; /* includes NULL termination for easy printing */ 91 | uint8_t digital_cc; 92 | uint8_t csn; 93 | uint8_t line21_field; 94 | uint8_t easy_reader; 95 | uint8_t wide_aspect_ratio; 96 | 97 | }; 98 | 99 | #define KLVANC_MAX_CCSVC_COUNT 16 100 | struct klvanc_packet_eia_708b_ccsvcinfo_section 101 | { 102 | uint8_t ccsvcinfo_id; 103 | uint8_t svc_info_start; 104 | uint8_t svc_info_change; 105 | uint8_t svc_info_complete; 106 | uint8_t svc_count; 107 | struct klvanc_packet_eia_708b_ccsvcinfo_entry svc[KLVANC_MAX_CCSVC_COUNT]; 108 | }; 109 | 110 | struct klvanc_packet_eia_708b_cdp_footer 111 | { 112 | uint8_t cdp_footer_id; 113 | uint16_t cdp_ftr_sequence_cntr; 114 | uint8_t packet_checksum; 115 | }; 116 | 117 | /** 118 | * @brief TODO - Brief description goes here. 119 | */ 120 | struct klvanc_packet_eia_708b_s 121 | { 122 | struct klvanc_packet_header_s hdr; 123 | uint8_t payload[256]; 124 | unsigned int payloadLengthBytes; 125 | int checksum_valid; 126 | struct klvanc_packet_eia_708b_cdp_header header; 127 | struct klvanc_packet_eia_708b_time_code_section tc; 128 | struct klvanc_packet_eia_708b_ccdata_section ccdata; 129 | struct klvanc_packet_eia_708b_ccsvcinfo_section ccsvc; 130 | struct klvanc_packet_eia_708b_cdp_footer footer; 131 | }; 132 | 133 | /** 134 | * @brief TODO - Brief description goes here. 135 | * @param[in] struct klvanc_context_s *ctx, void *p - Brief description goes here. 136 | * @return 0 - Success 137 | * @return < 0 - Error 138 | */ 139 | int klvanc_dump_EIA_708B(struct klvanc_context_s *ctx, void *p); 140 | 141 | /** 142 | * @brief Create an EIA-708 VANC packet 143 | * @param[out] struct klvanc_packet_eia_708b_s **pkt - Pointer to newly created packet 144 | * @return 0 - Success 145 | * @return < 0 - Error 146 | */ 147 | int klvanc_create_eia708_cdp(struct klvanc_packet_eia_708b_s **pkt); 148 | 149 | /** 150 | * @brief Destroy an EIA-708 VANC packet 151 | * @param[in] struct klvanc_packet_eia_708b_s *pkt - Packet to be destroyed 152 | */ 153 | void klvanc_destroy_eia708_cdp(struct klvanc_packet_eia_708b_s *pkt); 154 | 155 | /** 156 | * @brief Set the framerate on an EIA-708 packet 157 | * @param[in] struct klvanc_packet_eia_708b_s *pkt - Packet to be modified 158 | * @param[in] int num - numerator (e.g. 1001) 159 | * @param[in] int denominator - numerator (e.g. 30000) 160 | * @return 0 - Success 161 | * @return < 0 - Unknown framerate specified 162 | */ 163 | int klvanc_set_framerate_EIA_708B(struct klvanc_packet_eia_708b_s *pkt, int num, int den); 164 | 165 | /** 166 | * @brief Finalize a packet and prepare to serialize to output 167 | * @param[in] struct klvanc_packet_eia_708b_s *pkt - A EIA-608 VANC entry, received from the EIA-708 parser 168 | * @param[in] uint16_t seqNum - Sequence Number. This value should increment with each packet output over the final SDI link. 169 | */ 170 | void klvanc_finalize_EIA_708B(struct klvanc_packet_eia_708b_s *pkt, uint16_t seqNum); 171 | 172 | /** 173 | * @brief Convert type struct klvanc_packet_eia_708b_s into a more traditional line of\n 174 | * vanc words, so that we may push out as VANC data. 175 | * On success, caller MUST free the resulting *words array. 176 | * @param[in] struct klvanc_packet_eia_708bs *pkt - A EIA-708 VANC entry, received from the EIA-708 parser 177 | * @param[out] uint16_t **words - An array of words representing a fully formed vanc line. 178 | * @param[out] uint16_t *wordCount - Number of words in the array. 179 | * @return 0 - Success 180 | * @return < 0 - Error 181 | * @return -ENOMEM - Not enough memory to satisfy request 182 | */ 183 | int klvanc_convert_EIA_708B_to_words(struct klvanc_packet_eia_708b_s *pkt, uint16_t **words, uint16_t *wordCount); 184 | 185 | /** 186 | * @brief Convert type struct klvanc_packet_eia_708b_s into a block of bytes which represents\n 187 | * an EIA-708 packet 188 | * On success, caller MUST free the resulting *bytes array. 189 | * @param[in] struct klvanc_packet_eia_708b_s *pkt - A EIA-608 VANC entry, received from the EIA-708 parser 190 | * @param[out] uint8_t **bytes - An array of bytes representing the serialized CDP packet 191 | * @param[out] uint16_t *byteCount - Number of bytes in the array. 192 | * @return 0 - Success 193 | * @return < 0 - Error 194 | * @return -ENOMEM - Not enough memory to satisfy request 195 | */ 196 | int klvanc_convert_EIA_708B_to_packetBytes(struct klvanc_packet_eia_708b_s *pkt, uint8_t **bytes, uint16_t *byteCount); 197 | 198 | 199 | #ifdef __cplusplus 200 | }; 201 | #endif 202 | 203 | #endif /* _VANC_EIA_708B_H */ 204 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-kl_u64le_counter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-kl_u64le_counter.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2017 Kernel Labs Inc. All Rights Reserved. 26 | * @brief VANC counter library used for diagnostics/debugging 27 | */ 28 | 29 | #ifndef _VANC_KL_U64LE_COUNTER_H 30 | #define _VANC_KL_U64LE_COUNTER_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @brief TODO - Brief description goes here. 40 | */ 41 | struct klvanc_packet_kl_u64le_counter_s 42 | { 43 | struct klvanc_packet_header_s hdr; 44 | uint64_t counter; 45 | }; 46 | 47 | /** 48 | * @brief Create a KL counter packet 49 | * @param[out] struct klvanc_packet_kl_u64le_counter_s **pkt - Pointer to newly created packet 50 | * @return 0 - Success 51 | * @return < 0 - Error 52 | */ 53 | int klvanc_create_KL_U64LE_COUNTER(struct klvanc_packet_kl_u64le_counter_s **pkt); 54 | 55 | /** 56 | * @brief TODO - Brief description goes here. 57 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 58 | * @return 0 - Success 59 | * @return < 0 - Error 60 | */ 61 | int klvanc_dump_KL_U64LE_COUNTER(struct klvanc_context_s *ctx, void *p); 62 | 63 | /** 64 | * @brief Convert type struct klvanc_packet_kl_u64le_counter_s into a more traditional line of\n 65 | * vanc words, so that we may push out as VANC data. 66 | * On success, caller MUST free the resulting *words array. 67 | * @param[in] struct klvanc_packet_kl_u64le_counter_s *pkt - A KL counter VANC entry 68 | * @param[out] uint16_t **words - An array of words representing a fully formed vanc line. 69 | * @param[out] uint16_t *wordCount - Number of words in the array. 70 | * @return 0 - Success 71 | * @return < 0 - Error 72 | * @return -ENOMEM - Not enough memory to satisfy request 73 | */ 74 | int klvanc_convert_KL_U64LE_COUNTER_to_words(struct klvanc_packet_kl_u64le_counter_s *pkt, 75 | uint16_t **words, uint16_t *wordCount); 76 | 77 | #ifdef __cplusplus 78 | }; 79 | #endif 80 | 81 | #endif /* _VANC_KL_U64LE_COUNTER_H */ 82 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-lines.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-lines.h 24 | * @author Devin Heitmueller 25 | * @copyright Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved. 26 | * @brief Routines for managing VANC lines containing one or more VANC packets. 27 | * 28 | * These routines allow a caller to take VANC packets and assemble a frame 29 | * composed of a group of VANC lines. This includes: 30 | * 1. Ensuring no VANC packets with a given line/offset will overlap (moving VANC packets if necessary) 31 | * 2. Ensuring there are no gaps between VANC packets 32 | * 3. Ensuring the sum of all VANC packets does not overflow the line length 33 | * 4. Ensuring there are no illegal values in the VANC payload at a physical level 34 | */ 35 | 36 | #ifndef _KLVANC_LINE_H 37 | #define _KLVANC_LINE_H 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | #define KLVANC_MAX_VANC_LINES 64 48 | #define KLVANC_MAX_VANC_ENTRIES 16 49 | 50 | struct klvanc_entry_s 51 | { 52 | int h_offset; 53 | uint16_t *payload; 54 | int pixel_width; 55 | }; 56 | 57 | /** 58 | * @brief Represents a VANC line prior to serialization 59 | */ 60 | struct klvanc_line_s 61 | { 62 | int line_number; 63 | struct klvanc_entry_s *p_entries[KLVANC_MAX_VANC_ENTRIES]; 64 | int num_entries; 65 | }; 66 | 67 | /** 68 | * @brief Represents a group of VANC lines (e.g. perhaps corresponding to a video frame) 69 | */ 70 | 71 | struct klvanc_line_set_s 72 | { 73 | int num_lines; 74 | struct klvanc_line_s *lines[KLVANC_MAX_VANC_LINES]; 75 | }; 76 | 77 | /** 78 | * @brief Create a VANC line 79 | * 80 | * @param[in] int line_number - line number corresponding to where the line 81 | * placed within the field 82 | * @return struct klvanc_line_s containing the line or NULL on error 83 | */ 84 | struct klvanc_line_s *klvanc_line_create(int line_number); 85 | 86 | /** 87 | * @brief Free a previously created klvanc_line_s structure 88 | * @param[in] struct klvanc_line_s *line - pointer to the line to be deleted. 89 | * This will also deallocate any VANC packets previously inserted into the line 90 | */ 91 | void klvanc_line_free(struct klvanc_line_s *line); 92 | 93 | /** 94 | * @brief Insert a VANC packet into a VANC frame 95 | * 96 | * @param[in] struct klvanc_line_set_s *klvanc_lines - pointer to set of VANC lines to insert into 97 | * @param[in] uint16_t *pixels - Pointer to array of pixels to insert. For 10-bit pixels, these 98 | * should be 10-bit values inserted into 16-bit padded fields. 99 | * @param[in] int pixel_width - width of [pixels] argument, measured in number of samples 100 | * @param[in] int line_number - line number this VANC packet should appear on in the 101 | * resulting VANC frame 102 | * @param[in] int horizontal_offset - offset into active video area the packet should ideally 103 | * be inserted, measured in pixels 104 | * 105 | * @return 0 - Success 106 | * @return -ENOMEM - insufficient memory to store the VANC packet 107 | */ 108 | int klvanc_line_insert(struct klvanc_context_s *ctx, struct klvanc_line_set_s *vanc_lines, 109 | uint16_t *pixels, int pixel_width, int line_number, int horizontal_offset); 110 | 111 | /** 112 | * @brief Generate pixel array representing a fully formed VANC line. This 113 | * function will take in a klvanc_line_s, format the VANC entries to ensure there 114 | * are no gaps or overlapping packets, and create a final pixel array which 115 | * can be colorspace converted and output over SDI. 116 | * 117 | * @param[in] struct klvanc_context_s *ctx - Context. 118 | * @param[in] struct klvanc_line_s *line - the VANC line to operate on 119 | * @param[out] uint16_t **out_buf - a pointer to the buffer the function will output into. The 120 | * memory for the buffer will be allocated by the function, and the caller will need 121 | * to call free() to deallocate the resulting buffer. For 10-bit video, the array 122 | * will contain 10-bit samples in 16-bit values. Bit packing or Colorspace conversion 123 | * to other formats (such as V210) is the responsibility of the caller. 124 | * @param[out] int *out_len - the size of the resulting out_buf buffer. This parameter allows 125 | * the caller to know how large out_buf is to avoid buffer overflows. This value may 126 | * be shorter than the pixel width of the overall line. Measured in number of 16-bit 127 | * samples (i.e. not bytes). 128 | * @param[in] int line_pixel_width - Size of the line the VANC will ultimately be inserted into, 129 | * measured in number of samples. The function will not create an out_buf buffer which 130 | * is larger than this value, nor will it insert VANC packets which exceed the line 131 | * width specified. 132 | * @return 0 - Success 133 | * @return -ENOMEM - insufficient memory to store the VANC packet 134 | */ 135 | int klvanc_generate_vanc_line(struct klvanc_context_s *ctx, struct klvanc_line_s *line, 136 | uint16_t **out_buf, int *out_len, int line_pixel_width); 137 | 138 | /** 139 | * @brief Generate byte array representing a fully formed VANC line. This 140 | * function will take in a klvanc_line_s, format the VANC entries to ensure there 141 | * are no gaps or overlapping packets, and create a final byte array which 142 | * can be directly output over SDI in packed v210 format. 143 | * 144 | * @param[in] struct klvanc_context_s *ctx - Context. 145 | * @param[in] struct klvanc_line_s *line - the VANC line to operate on 146 | * @param[out] uint8_t *out_buf - a pointer to the buffer the function will output into. The 147 | * memory for the output buffer should be allocated by the caller (or in the case 148 | * of working with Blackmagic cards, pass the buffer returned from 149 | * vanc->GetBufferForVerticalBlankingLine(). Note that this function will determine 150 | * whether to do HD interleaving (inserting into the Y region only) or SD 151 | * interleaving (using both Y and UV regions) based on the value provided via the 152 | * line_pixel_width argument. 153 | * @param[in] int line_pixel_width - Size of the output buffer, measured in number of samples. 154 | * When working with Blackmagic cards, this value will typically be the line width 155 | * (e.g. 1920 for 1080i video), but there are special exceptions for certain 4K 156 | * cards so review the Blackmagic SDK documentation for details. This function 157 | * will it insert VANC packets which exceed the line width specified. 158 | * @return 0 - Success 159 | * @return -ENOMEM - insufficient memory to store the VANC packet 160 | */ 161 | int klvanc_generate_vanc_line_v210(struct klvanc_context_s *ctx, struct klvanc_line_s *line, 162 | uint8_t *out_buf, int line_pixel_width); 163 | 164 | #ifdef __cplusplus 165 | }; 166 | #endif 167 | 168 | #endif /* _VANC_LINES_H */ 169 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-packets.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-packets.h 24 | * @author Steven Toth 25 | * @copyright Copyright (c) 2016-2017 Kernel Labs Inc. All Rights Reserved. 26 | * @brief VANC Headers and packet structure 27 | */ 28 | 29 | #ifndef _VANC_PACKETS_H 30 | #define _VANC_PACKETS_H 31 | 32 | #include 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** 40 | * @brief TODO - Brief description goes here. 41 | */ 42 | enum klvanc_packet_type_e 43 | { 44 | VANC_TYPE_UNDEFINED = 0, 45 | VANC_TYPE_AFD, 46 | VANC_TYPE_EIA_708B, 47 | VANC_TYPE_EIA_608, 48 | VANC_TYPE_SCTE_104, 49 | VANC_TYPE_KL_UINT64_COUNTER, 50 | VANC_TYPE_SDP, 51 | VANC_TYPE_SMPTE_S12_2, 52 | VANC_TYPE_SMPTE_S2108_1, 53 | }; 54 | 55 | /** 56 | * @brief TODO - Brief description goes here. 57 | */ 58 | struct klvanc_packet_header_s 59 | { 60 | enum klvanc_packet_type_e type; 61 | unsigned short adf[3]; 62 | unsigned short did; 63 | unsigned short dbnsdid; 64 | unsigned short checksum; 65 | #define LIBKLVANC_PACKET_MAX_PAYLOAD (16384) 66 | unsigned short payload[LIBKLVANC_PACKET_MAX_PAYLOAD]; 67 | unsigned short payloadLengthWords; 68 | unsigned int checksumValid; 69 | unsigned int lineNr; /**< The vanc in this header came from line.... */ 70 | unsigned short raw[LIBKLVANC_PACKET_MAX_PAYLOAD]; 71 | unsigned int rawLengthWords; 72 | unsigned short horizontalOffset; /**< Horizontal word where the ADF was detected. */ 73 | }; 74 | 75 | /** 76 | * @brief SMPTE 291-1-2011 Section 6.3 77 | * "An ancillary data packet with a DID word value equal to 80h may be deleted by any equipment 78 | * during a subsequent processing cycle (see Annex C). The occupied ancillary data space, however, 79 | * shall remain contiguous as defined in Section 7.3. 80 | * Note: Designers of equipment are advised that, in 8-bit systems, ancillary data packets with 81 | * DID words in the range of 80h – 83h all are considered to be marked for deletion." 82 | */ 83 | #define klvanc_packetType1(pkt) (((pkt)->did >= 0x80) && ((pkt)->did <= 0x83)) 84 | 85 | #ifdef __cplusplus 86 | }; 87 | #endif 88 | 89 | #endif /* _VANC_PACKETS_H */ 90 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-sdp.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file vanc-sdp.h 4 | * @author Yves De Muyter , tidy-ups: Steven Toth 5 | * @copyright Copyright (c) 2023 Kernel Labs Inc. All Rights Reserved. 6 | * @brief WST / OP-47 / RDD8 - Subtitling Distribution Packet (SDP) Format 7 | */ 8 | 9 | #ifndef _VANC_SDP_H 10 | #define _VANC_SDP_H 11 | 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | enum klvanc_sdp_format_code_e 19 | { 20 | SDP_WSS_TELETEXT = 0x02 21 | }; 22 | 23 | /** 24 | * @brief TODO - Brief description goes here. 25 | */ 26 | struct klvanc_sdp_desc_s 27 | { 28 | uint8_t line; // Line number, only 5 bits 29 | uint8_t field; // Field number, only 1 bit, 0 = even field 30 | uint8_t data[45]; // WSS Teletext data representing a subtitle line 31 | }; 32 | 33 | /** 34 | * @brief TODO - Brief description goes here. 35 | */ 36 | struct klvanc_packet_sdp_s 37 | { 38 | struct klvanc_packet_header_s hdr; 39 | uint16_t identifier; 40 | enum klvanc_sdp_format_code_e format_code; 41 | struct klvanc_sdp_desc_s descriptors[5]; 42 | uint16_t sequence_counter; 43 | }; 44 | 45 | int klvanc_dump_SDP(struct klvanc_context_s *ctx, void *p); 46 | 47 | /** 48 | * @brief Allocate a new SDP packet 49 | * @param[out] struct klvanc_packet_sdp_s **pkt - object created 50 | * @return 0 - Success 51 | * @return < 0 - Error 52 | */ 53 | int klvanc_create_SDP(struct klvanc_packet_sdp_s **pkt); 54 | 55 | /** 56 | * @brief Free a previously allocated SDP packet. 57 | * @param[in] struct klvanc_packet_sdp_s *pkt - object to be freed 58 | */ 59 | void klvanc_destroy_SDP(struct klvanc_packet_sdp_s *pkt); 60 | 61 | #ifdef __cplusplus 62 | }; 63 | #endif 64 | 65 | #endif /* _VANC_SDP_H */ 66 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-smpte_12_2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-smpte_12_2.h 24 | * @author Devin Heitmueller 25 | * @copyright Copyright (c) 2019 Kernel Labs Inc. All Rights Reserved. 26 | * @brief SMPTE ST 12-2 Timecode over VANC 27 | */ 28 | 29 | #ifndef _VANC_SMPTE_12_2_H 30 | #define _VANC_SMPTE_12_2_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /* DBB1 payload types (See Sec 6.2.1 Table 2) */ 39 | #define KLVANC_ATC_LTC 0x00 40 | #define KLVANC_ATC_VITC1 0x01 41 | #define KLVANC_ATC_VITC2 0x02 42 | /* Codes 3-5 are user defined */ 43 | #define KLVANC_FILM_DATA_BLOCK 0x06 44 | #define KLVANC_PROD_DATA_BLOCK 0x07 45 | /* Codes 0x08 to 0x7c are "locally generated time address and user data (user defined) */ 46 | #define KLVANC_VID_TAPE_DATA_BLOCK_LOCAL 0x7d 47 | #define KLVANC_FILM_DATA_BLOCK_LOCAL 0x7e 48 | #define KLVANC_PROD_DATA_BLOCK_LOCAL 0x7f 49 | /* Codes 0x80 to 0xff are Reserved */ 50 | 51 | /** 52 | * @brief TODO - Brief description goes here. 53 | */ 54 | struct klvanc_packet_smpte_12_2_s 55 | { 56 | struct klvanc_packet_header_s hdr; 57 | 58 | unsigned char payload[256]; 59 | unsigned int payloadLengthBytes; 60 | 61 | uint8_t dbb1; 62 | uint8_t dbb2; 63 | 64 | uint8_t vitc_line_select; 65 | uint8_t line_duplication_flag; 66 | uint8_t tc_validity_flag; 67 | uint8_t user_bits_process_flag; 68 | 69 | /* Timecode data */ 70 | uint8_t frames; 71 | uint8_t seconds; 72 | uint8_t minutes; 73 | uint8_t hours; 74 | 75 | /* See ST 12-1:2014 Table 11 for the meanings of these 76 | flags, which may vary depending on the framerate */ 77 | 78 | /* Drop frame flag in 30/60. Always zero in 25/50/24/48 */ 79 | uint8_t flag14; 80 | /* Color frame flag in 30/60/25/50. Always zero in 24/48 */ 81 | uint8_t flag15; 82 | /* Field Bit/LTC Polarity in 30/60/24/48. BGF0 in 25/50 */ 83 | uint8_t flag35; 84 | /* BGF0 in 30/60/24/48. BGF2 in 25/50 */ 85 | uint8_t flag55; 86 | /* BGF1 in all framerates */ 87 | uint8_t flag74; 88 | /* BGF2 in 30/60/24/48. Field Bit/LTC Polarity in 25/50 */ 89 | uint8_t flag75; 90 | }; 91 | 92 | /** 93 | * @brief Create SMPTE ST 12-2 timecode 94 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 95 | * @return 0 - Success 96 | * @return < 0 - Error 97 | */ 98 | int klvanc_alloc_SMPTE_12_2(struct klvanc_packet_smpte_12_2_s **pkt); 99 | 100 | /** 101 | * @brief Create SMPTE ST 12-2 timecode from SMPTE 370 / 314 timecode 102 | * @param[in] uint32_t st370_tc - Packed binary representation of timecode as described in SMPTE ST 370:2013 Sec 3.4.2.2.1 and SMPTE S314M-2015 Sec 4.4.2.2.1 103 | * @param[in] int frate_num - framerate numerator (e.g. 1001) 104 | * @param[in] int frate_den - framerate denominator (e.g. 30000) 105 | * @param[out] struct klvanc_packet_smpte_12_2_s **pkt - newly created packet 106 | * @return 0 - Success 107 | * @return < 0 - Error 108 | */ 109 | int klvanc_create_SMPTE_12_2_from_ST370(uint32_t st370_tc, 110 | int frate_num, int frate_den, 111 | struct klvanc_packet_smpte_12_2_s **pkt); 112 | 113 | 114 | /** 115 | * @brief TODO - Brief description goes here. 116 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 117 | * @return 0 - Success 118 | * @return < 0 - Error 119 | */ 120 | int klvanc_dump_SMPTE_12_2(struct klvanc_context_s *ctx, void *p); 121 | 122 | /** 123 | * @brief TODO - Brief description goes here. 124 | * @param[in] void *p - Pointer to struct (klvanc_packet_smpte_12_2_s *) 125 | */ 126 | void klvanc_free_SMPTE_12_2(void *p); 127 | 128 | /** 129 | * @brief Convert type struct packet_smpte_12_2_s into a more traditional line of\n 130 | * vanc words, so that we may push out as VANC data. 131 | * On success, caller MUST free the resulting *words array. 132 | * @param[in] struct packet_smpte_12_2_s *pkt - A SMPTE 12_2-2 VANC entry, received from the 12_2 parser 133 | * @param[out] uint16_t **words - An array of words reppresenting a fully formed vanc line. 134 | * @param[out] uint16_t *wordCount - Number of words in the array. 135 | * @return 0 - Success 136 | * @return < 0 - Error 137 | * @return -ENOMEM - Not enough memory to satisfy request 138 | */ 139 | int klvanc_convert_SMPTE_12_2_to_words(struct klvanc_context_s *ctx, 140 | struct klvanc_packet_smpte_12_2_s *pkt, 141 | uint16_t **words, uint16_t *wordCount); 142 | 143 | /** 144 | * @brief Convert type struct packet_smpte_12_2_s into a block of bytes which can be\n 145 | * embedded into a VANC line 146 | * On success, caller MUST free the resulting *words array. 147 | * @param[in] struct packet_smpte_12_2_s *pkt - A SMPTE 12_2 VANC entry, received from the 12_2 parser 148 | * @param[out] uint8_t **bytes - An array of words reppresenting a fully formed vanc line. 149 | * @param[out] uint16_t *byteCount - Number of byes in the array. 150 | * @return 0 - Success 151 | * @return < 0 - Error 152 | * @return -ENOMEM - Not enough memory to satisfy request 153 | */ 154 | int klvanc_convert_SMPTE_12_2_to_packetBytes(struct klvanc_context_s *ctx, 155 | const struct klvanc_packet_smpte_12_2_s *pkt, 156 | uint8_t **bytes, uint16_t *byteCount); 157 | 158 | /** 159 | * @brief Determine the appropriate line to insert this S-12 packet onto. 160 | * This takes into consideration interoperability with legacy 161 | * equipment, as described in SMPTE S-12-2:2014 Sec 8.2.1. 162 | * @param[in] int dbb1 - The Payload type of this S-12-2 packet 163 | * @param[in] int lineCount - The number of lines in the video frame 164 | * @param[in] int interlaced - whether the video frame is interlaced 165 | * @return > 0 Line number to insert into 166 | * @return < 0 - Error 167 | */ 168 | 169 | int klvanc_SMPTE_12_2_preferred_line(int dbb1, int lineCount, int interlaced); 170 | 171 | #ifdef __cplusplus 172 | }; 173 | #endif 174 | 175 | #endif /* _VANC_SMPTE_12_2_H */ 176 | -------------------------------------------------------------------------------- /src/libklvanc/vanc-smpte_2108_1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /** 23 | * @file vanc-smpte_2108_1.h 24 | * @author Devin Heitmueller 25 | * @copyright Copyright (c) 2023 Kernel Labs Inc. All Rights Reserved. 26 | * @brief SMPTE ST 2108-1 HDR/WCG over VANC 27 | */ 28 | 29 | #ifndef _VANC_SMPTE_2108_1_H 30 | #define _VANC_SMPTE_2108_1_H 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #define MAX_S2108_1_FRAMES 10 39 | 40 | /* HDR Frame types (See Sec 5.3.1 Table 3) */ 41 | #define KLVANC_HDR_STATIC1 0x00 /* H.265 */ 42 | #define KLVANC_HDR_STATIC2 0x01 /* H.265 */ 43 | #define KLVANC_HDR_DYNAMIC2 0x02 /* ATSC A/341 */ 44 | /* Codes 3-5 are reserved */ 45 | #define KLVANC_HDR_DYNAMIC5 0x06 /* ETSI TS 103 433-1 SL-HDR */ 46 | 47 | struct klvanc_packet_smpte_2108_1_static1 { 48 | uint16_t display_primaries_x[3]; 49 | uint16_t display_primaries_y[3]; 50 | uint16_t white_point_x; 51 | uint16_t white_point_y; 52 | uint32_t max_display_mastering_luminance; 53 | uint32_t min_display_mastering_luminance; 54 | }; 55 | 56 | struct klvanc_packet_smpte_2108_1_static2 { 57 | uint16_t max_content_light_level; 58 | uint16_t max_pic_average_light_level; 59 | }; 60 | 61 | struct klvanc_s2108_1_frame { 62 | uint8_t frame_type; 63 | uint8_t frame_length; 64 | union { 65 | struct klvanc_packet_smpte_2108_1_static1 static1; 66 | struct klvanc_packet_smpte_2108_1_static2 static2; 67 | }; 68 | }; 69 | 70 | /** 71 | * @brief Describes an ST2108 packet 72 | */ 73 | struct klvanc_packet_smpte_2108_1_s 74 | { 75 | struct klvanc_packet_header_s hdr; 76 | 77 | uint8_t payload[256]; 78 | unsigned int payloadLengthBytes; 79 | 80 | uint8_t num_frames; 81 | struct klvanc_s2108_1_frame frames[MAX_S2108_1_FRAMES]; 82 | }; 83 | 84 | /** 85 | * @brief Create SMPTE ST 2108_1 HDR metadata 86 | * @param[in] struct klvanc_packet_smpte_2108_1_s **pkt - Pointer to the newly created structure 87 | * @return 0 - Success 88 | * @return < 0 - Error 89 | */ 90 | int klvanc_alloc_SMPTE_2108_1(struct klvanc_packet_smpte_2108_1_s **pkt); 91 | 92 | /** 93 | * @brief TODO - Brief description goes here. 94 | * @param[in] struct vanc_context_s *ctx, void *p - Brief description goes here. 95 | * @return 0 - Success 96 | * @return < 0 - Error 97 | */ 98 | int klvanc_dump_SMPTE_2108_1(struct klvanc_context_s *ctx, void *p); 99 | 100 | /** 101 | * @brief TODO - Brief description goes here. 102 | * @param[in] void *p - Pointer to struct (klvanc_packet_smpte_2108_1_s *) 103 | */ 104 | void klvanc_free_SMPTE_2108_1(void *p); 105 | 106 | #ifdef __cplusplus 107 | }; 108 | #endif 109 | 110 | #endif /* _VANC_SMPTE_2108_1_H */ 111 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | klvanc_sources = files( 2 | 'core.c', 3 | 'core-packet-eia_708b.c', 4 | 'core-packet-eia_608.c', 5 | 'core-packet-scte_104.c', 6 | 'core-packet-afd.c', 7 | 'core-packet-sdp.c', 8 | 'core-packet-smpte_12_2.c', 9 | 'core-packet-smpte_2108_1.c', 10 | 'core-packets.c', 11 | 'core-lines.c', 12 | 'core-did.c', 13 | 'core-pixels.c', 14 | 'core-checksum.c', 15 | 'smpte2038.c', 16 | 'core-cache.c', 17 | 'core-packet-kl_u64le_counter.c', 18 | ) 19 | 20 | klvanc_headers = files( 21 | 'libklvanc/vanc.h', 22 | 'libklvanc/did.h', 23 | 'libklvanc/pixels.h', 24 | 'libklvanc/smpte2038.h', 25 | 'libklvanc/vanc-eia_708b.h', 26 | 'libklvanc/vanc-eia_608.h', 27 | 'libklvanc/vanc-scte_104.h', 28 | 'libklvanc/vanc-smpte_12_2.h', 29 | 'libklvanc/vanc-smpte_2108_1.h', 30 | 'libklvanc/vanc-packets.h', 31 | 'libklvanc/vanc-lines.h', 32 | 'libklvanc/vanc-afd.h', 33 | 'libklvanc/vanc-sdp.h', 34 | 'libklvanc/vanc-checksum.h', 35 | 'libklvanc/klrestricted_code_path.h', 36 | 'libklvanc/cache.h', 37 | 'libklvanc/vanc-kl_u64le_counter.h', 38 | ) 39 | 40 | install_headers(klvanc_headers, subdir : 'libklvanc') 41 | 42 | klvanc_incdirs = include_directories('.') 43 | 44 | thread_dep = dependency('threads') 45 | 46 | libklvanc = library('klvanc', klvanc_sources, 47 | include_directories : klvanc_incdirs, 48 | install : true, 49 | dependencies: [thread_dep], 50 | ) 51 | 52 | libklvanc_dep = declare_dependency(link_with : libklvanc, 53 | include_directories : klvanc_incdirs, 54 | ) 55 | -------------------------------------------------------------------------------- /tools/.gitignore: -------------------------------------------------------------------------------- 1 | klvanc_util 2 | klvanc_capture 3 | klvanc_smpte2038 4 | klvanc_scte104 5 | klvanc_eia708 6 | klvanc_genscte104 7 | klvanc_gensmpte2038 8 | klvanc_smpte12_2 9 | klvanc_parse 10 | klvanc_afd 11 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | AUTOMAKE_OPTIONS = foreign 3 | 4 | AM_CPPFLAGS = -DVERSION=\"$(VERSION)\" -DPROG="\"$(PACKAGE)\"" -D_FILE_OFFSET_BITS=64 \ 5 | -D_BSD_SOURCE \ 6 | -I$(top_srcdir)/src \ 7 | -D__STDC_FORMAT_MACROS 8 | 9 | AM_CFLAGS = -Wall -O3 10 | 11 | LDADD = ../src/libklvanc.la -lpthread -ldl 12 | 13 | if DEBUG 14 | CFLAGS += -g 15 | endif 16 | 17 | SRC = klvanc_util.c 18 | SRC += demo.c 19 | SRC += parse.c 20 | SRC += smpte2038.c 21 | SRC += scte104.c 22 | SRC += genscte104.c 23 | SRC += gensmpte2038.c 24 | SRC += eia708.c 25 | SRC += smpte12_2.c 26 | SRC += afd.c 27 | SRC += udp.c 28 | SRC += url.c 29 | SRC += ts_packetizer.c 30 | SRC += klringbuffer.c 31 | SRC += pes_extractor.c 32 | 33 | bin_PROGRAMS = klvanc_util 34 | bin_PROGRAMS += klvanc_parse 35 | bin_PROGRAMS += klvanc_smpte2038 36 | bin_PROGRAMS += klvanc_scte104 37 | bin_PROGRAMS += klvanc_genscte104 38 | bin_PROGRAMS += klvanc_gensmpte2038 39 | bin_PROGRAMS += klvanc_eia708 40 | bin_PROGRAMS += klvanc_smpte12_2 41 | bin_PROGRAMS += klvanc_afd 42 | 43 | klvanc_util_SOURCES = $(SRC) 44 | klvanc_parse_SOURCES = $(SRC) 45 | klvanc_smpte2038_SOURCES = $(SRC) 46 | klvanc_scte104_SOURCES = $(SRC) 47 | klvanc_genscte104_SOURCES = $(SRC) 48 | klvanc_gensmpte2038_SOURCES = $(SRC) 49 | klvanc_eia708_SOURCES = $(SRC) 50 | klvanc_smpte12_2_SOURCES = $(SRC) 51 | klvanc_afd_SOURCES = $(SRC) 52 | 53 | libklvanc_noinst_includedir = $(includedir) 54 | 55 | noinst_HEADERS = hexdump.h 56 | noinst_HEADERS += klringbuffer.h 57 | noinst_HEADERS += pes_extractor.h 58 | noinst_HEADERS += ts_packetizer.h 59 | noinst_HEADERS += udp.h 60 | noinst_HEADERS += url.h 61 | noinst_HEADERS += version.h 62 | 63 | test: klvanc_eia708 klvanc_genscte104 klvanc_scte104 klvanc_smpte12_2 klvanc_afd klvanc_smpte2038 klvanc_gensmpte2038 64 | ./klvanc_eia708 65 | ./klvanc_genscte104 66 | ./klvanc_scte104 67 | ./klvanc_smpte12_2 68 | ./klvanc_gensmpte2038 69 | ./klvanc_afd 70 | ./klvanc_smpte2038 -i ../samples/smpte2038-sample-pid-01e9.ts -P 0x1e9 71 | -------------------------------------------------------------------------------- /tools/afd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* Normally we don't use a global, but we know our test harness will never be 27 | multi-threaded, and this is a really easy way to get the results out of the 28 | callback for comparison */ 29 | static uint16_t vancResult[16384]; 30 | static size_t vancResultCount; 31 | static int passCount = 0; 32 | static int failCount = 0; 33 | 34 | #define SHOW_DETAIL 1 35 | 36 | /* CALLBACKS for message notification */ 37 | static int cb_afd(void *callback_context, struct klvanc_context_s *ctx, 38 | struct klvanc_packet_afd_s *pkt) 39 | { 40 | int ret = -1; 41 | 42 | #ifdef SHOW_DETAIL 43 | /* Have the library display some debug */ 44 | printf("Asking libklvanc to dump a struct\n"); 45 | ret = klvanc_dump_AFD(ctx, pkt); 46 | if (ret != 0) { 47 | fprintf(stderr, "Error dumping AFD packet!\n"); 48 | return -1; 49 | } 50 | #endif 51 | 52 | uint16_t *words; 53 | uint16_t wordCount; 54 | ret = klvanc_convert_AFD_to_words(pkt, &words, &wordCount); 55 | if (ret != 0) { 56 | fprintf(stderr, "Failed to convert 104 to words: %d\n", ret); 57 | return -1; 58 | } 59 | 60 | memcpy(vancResult, words, wordCount * sizeof(uint16_t)); 61 | vancResultCount = wordCount; 62 | free(words); 63 | 64 | return 0; 65 | } 66 | 67 | static struct klvanc_callbacks_s callbacks = 68 | { 69 | .afd = cb_afd, 70 | }; 71 | /* END - CALLBACKS for message notification */ 72 | 73 | /* svcinfo_present flag set but section missing */ 74 | unsigned short test_data_afd_1[] = { 75 | 0x0000, 0x03ff, 0x03ff, 0x0241, 0x0205, 0x0108, 0x0200, 0x0200, 76 | 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x014e 77 | }; 78 | 79 | static int test_afd_u16(struct klvanc_context_s *ctx, const unsigned short *arr, int items) 80 | { 81 | int mismatch = 0; 82 | 83 | printf("\nParsing a new AFD VANC packet (%d words)......\n", items); 84 | 85 | /* Clear out any previous results in case the callback never fires */ 86 | vancResultCount = 0; 87 | 88 | printf("Original Input\n"); 89 | for (int i = 0; i < items; i++) { 90 | printf("%04x ", arr[i]); 91 | } 92 | printf("\n"); 93 | 94 | int ret = klvanc_packet_parse(ctx, 9, arr, items); 95 | 96 | printf("Final output\n"); 97 | for (int i = 0; i < vancResultCount; i++) { 98 | printf("%04x ", vancResult[i]); 99 | } 100 | printf("\n"); 101 | 102 | for (int i = 0; i < vancResultCount; i++) { 103 | if (arr[i] != vancResult[i]) { 104 | fprintf(stderr, "Mismatch starting at offset 0x%02x\n", i); 105 | mismatch = 1; 106 | break; 107 | } 108 | } 109 | if (vancResultCount == 0) { 110 | /* No output at all. This is usually because the VANC parser choked 111 | on the VANC checksum and thus the parser never ran */ 112 | fprintf(stderr, "No output generated\n"); 113 | mismatch = 1; 114 | } 115 | 116 | if (mismatch) { 117 | printf("Printing mismatched structure:\n"); 118 | failCount++; 119 | ret = klvanc_packet_parse(ctx, 13, vancResult, vancResultCount); 120 | } else { 121 | printf("Original and generated versions match!\n"); 122 | passCount++; 123 | } 124 | 125 | return ret; 126 | } 127 | 128 | #ifdef UNUSED 129 | static int test_afd(struct klvanc_context_s *ctx, const uint8_t *buf, size_t bufSize) 130 | { 131 | int numWords = bufSize / 2; 132 | int ret; 133 | 134 | 135 | uint16_t *arr = malloc(bufSize); 136 | if (arr == NULL) 137 | return -1; 138 | 139 | for (int i = 0; i < numWords; i++) { 140 | arr[i] = buf[i * 2] << 8 | buf[i * 2 + 1]; 141 | } 142 | 143 | ret = test_afd_u16(ctx, arr, numWords); 144 | 145 | free(arr); 146 | 147 | return ret; 148 | } 149 | #endif 150 | 151 | int afd_main(int argc, char *argv[]) 152 | { 153 | struct klvanc_context_s *ctx; 154 | int ret; 155 | 156 | if (klvanc_context_create(&ctx) < 0) { 157 | fprintf(stderr, "Error initializing library context\n"); 158 | exit(1); 159 | } 160 | #ifdef SHOW_DETAIL 161 | ctx->verbose = 1; 162 | #endif 163 | ctx->callbacks = &callbacks; 164 | printf("Library initialized.\n"); 165 | 166 | ret = test_afd_u16(ctx, test_data_afd_1, sizeof(test_data_afd_1) / sizeof(unsigned short)); 167 | if (ret < 0) 168 | fprintf(stderr, "AFD-1 failed to parse\n"); 169 | 170 | klvanc_context_destroy(ctx); 171 | printf("Library destroyed.\n"); 172 | 173 | printf("Final result: PASS: %d/%d, Failures: %d\n", 174 | passCount, passCount + failCount, failCount); 175 | if (failCount != 0) 176 | return 1; 177 | return 0; 178 | } 179 | -------------------------------------------------------------------------------- /tools/gensmpte2038.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "klbitstream_readwriter.h" 31 | #include "ts_packetizer.h" 32 | #include "version.h" 33 | #include "hexdump.h" 34 | 35 | #define DEFAULT_PID 0x80 36 | 37 | static struct app_context_s 38 | { 39 | int verbose; 40 | unsigned int pid; 41 | } app_context; 42 | 43 | static struct app_context_s *ctx = &app_context; 44 | 45 | /* Create a PES array containing 8 lines of VANC data. 46 | */ 47 | static void smpte2038_generate_sample_708B_packet(struct app_context_s *ctx) 48 | { 49 | /* STEP 1. Generate some useful VANC packed into a PES frame. */ 50 | 51 | /* This is a fully formed 708B VANC message. We'll bury 52 | * this inside a SMPTE2038 wrapper and prepare a TS packet 53 | * that could be used for sample/test data. 54 | */ 55 | unsigned short arr[] = { 56 | 0x000, 0x3ff, 0x3ff, 0x161, 0x101, 0x152, 0x296, 0x269, 57 | 0x152, 0x14f, 0x277, 0x2b8, 0x1ad, 0x272, 0x1f4, 0x2fc, 58 | 0x180, 0x180, 0x1fd, 0x180, 0x180, 0x2fa, 0x200, 0x200, 59 | 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 60 | 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 61 | 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 62 | 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 63 | 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 64 | 0x200, 0x200, 0x2fa, 0x200, 0x200, 0x2fa, 0x200, 0x200, 65 | 0x2fa, 0x200, 0x200, 0x173, 0x2d1, 0x1e0, 0x200, 0x200, 66 | 0x200, 0x200, 0x200, 0x200, 0x274, 0x2b8, 0x1ad, 0x194, 67 | 0x1b4, /* Checksum */ 68 | }; 69 | 70 | /* See smpte 2038-2008 - Page 5, Table 2 for description. */ 71 | struct klbs_context_s *bs = klbs_alloc(); 72 | 73 | uint8_t buf[8192] = { 0 }; 74 | klbs_write_set_buffer(bs, buf, sizeof(buf)); 75 | 76 | /* PES Header - Bug: bitstream can't write 32bit values */ 77 | klbs_write_bits(bs, 1, 24); /* packet_start_code_prefix */ 78 | klbs_write_bits(bs, 0xBD, 8); /* stream_id */ 79 | klbs_write_bits(bs, 0, 16); /* PES_packet_length */ 80 | klbs_write_bits(bs, 2, 2); /* '10' fixed value */ 81 | klbs_write_bits(bs, 0, 2); /* PES_scrambling_control (not scrambled) */ 82 | klbs_write_bits(bs, 0, 1); /* PES_priority */ 83 | klbs_write_bits(bs, 1, 1); /* data_alignment_indicator (aligned) */ 84 | klbs_write_bits(bs, 0, 1); /* copyright (not-copyright) */ 85 | klbs_write_bits(bs, 0, 1); /* original-or-copy (copy) */ 86 | klbs_write_bits(bs, 2, 2); /* PTS_DTS_flags (PTS Present) */ 87 | klbs_write_bits(bs, 0, 1); /* ESCR_flag (not present) */ 88 | klbs_write_bits(bs, 0, 1); /* ES_RATE_flag (not present) */ 89 | klbs_write_bits(bs, 0, 1); /* DSM_TRICK_MODE_flag (not present) */ 90 | klbs_write_bits(bs, 0, 1); /* additional_copy_info_flag (not present) */ 91 | klbs_write_bits(bs, 0, 1); /* PES_CRC_flag (not present) */ 92 | klbs_write_bits(bs, 0, 1); /* PES_EXTENSION_flag (not present) */ 93 | klbs_write_bits(bs, 5, 8); /* PES_HEADER_DATA_length */ 94 | klbs_write_bits(bs, 2, 4); /* '0010' fixed value */ 95 | 96 | uint64_t pts = 0; 97 | klbs_write_bits(bs, (pts >> 30), 3); /* PTS[32:30] */ 98 | klbs_write_bits(bs, 1, 1); /* marker_bit */ 99 | klbs_write_bits(bs, (pts >> 15) & 0xefff, 15); /* PTS[29:15] */ 100 | klbs_write_bits(bs, 1, 1); /* marker_bit */ 101 | klbs_write_bits(bs, (pts & 0xefff), 15); /* PTS[14:0] */ 102 | klbs_write_bits(bs, 1, 1); /* marker_bit */ 103 | 104 | int lineCount = 4; 105 | for (int i = 0; i < lineCount; i++) { 106 | /* VANC Payload */ 107 | klbs_write_bits(bs, 0, 6); /* fixed value '000000' */ 108 | klbs_write_bits(bs, 0, 1); /* c_not_y_channel_flag (HD luminance) */ 109 | klbs_write_bits(bs, 10 + i, 11); /* line_number (9) */ 110 | klbs_write_bits(bs, 0, 12); /* horizonal_offset (0 words from SAV) */ 111 | klbs_write_bits(bs, arr[3], 10); /* DID */ 112 | klbs_write_bits(bs, arr[4], 10); /* SDID */ 113 | klbs_write_bits(bs, arr[5], 10); /* data_count */ 114 | for (int i = 6; i < (sizeof(arr) / sizeof(unsigned short)); i++) { 115 | /* This data_count AND checksum */ 116 | klbs_write_bits(bs, arr[i], 10); 117 | } 118 | 119 | /* Byte alignment stuffing */ 120 | while (bs->reg_used > 0) { 121 | klbs_write_bits(bs, 1, 1); /* Stuffing byte */ 122 | } 123 | } 124 | 125 | /* Flush the remaining bits out into buffer, else we lose up to 126 | * the last 7 bits that are cached in the bitstream implementation. 127 | */ 128 | klbs_write_buffer_complete(bs); 129 | 130 | /* Now updated the PES packet length */ 131 | int len = klbs_get_byte_count(bs) - 6; 132 | klbs_get_buffer(bs)[4] = (len >> 8) & 0xff; 133 | klbs_get_buffer(bs)[5] = len & 0xff; 134 | 135 | /* STEP 2. Do something useful with the PES, now that its fully assembled. */ 136 | 137 | /* The PES is ready. Save a file copy. */ 138 | printf("%s() We've constructed a fake PES, here it is:\n", __func__); 139 | hexdump(buf, klbs_get_byte_count(bs), 16); 140 | klbs_save(bs, "/tmp/bitstream-scte2038-EIA708B.raw"); 141 | 142 | /* STEP 3. Maybe we should packetize the PES into TS packets. */ 143 | 144 | uint8_t section[8192]; 145 | int section_length = klbs_get_byte_count(bs); 146 | memset(section, 0xff, sizeof(section)); 147 | memcpy(section, klbs_get_buffer(bs), section_length); 148 | 149 | uint8_t *pkts = 0; 150 | uint32_t packetCount = 0; 151 | uint8_t cc = 0; 152 | ts_packetizer(section, section_length, &pkts, &packetCount, 188, &cc, ctx->pid); 153 | for (uint32_t i = 0; i < packetCount; i++) { 154 | printf("%s() We've constructed some TS packets, here they are:\n", __func__); 155 | hexdump(pkts + (i * 188), 188, 16); 156 | } 157 | 158 | /* Write all the TS packets to a temp file. */ 159 | FILE *fh = fopen("/tmp/bitstream-scte2038-EIA708B.ts", "wb"); 160 | if (fh) { 161 | fwrite(pkts, packetCount, 188, fh); 162 | fclose(fh); 163 | } 164 | 165 | free(pkts); /* Results from the packetizer have to be caller freed. */ 166 | 167 | klbs_free(bs); 168 | } 169 | 170 | static int _usage(const char *progname, int status) 171 | { 172 | fprintf(stderr, COPYRIGHT "\n"); 173 | fprintf(stderr, "Generate a SMPTE2038 stream containing 708 VANC\n"); 174 | fprintf(stderr, "Usage: %s [OPTIONS]\n" 175 | " -P VANC PID to generate to (def: 0x%x)\n" 176 | " -h This help page\n", 177 | basename((char *)progname), 178 | DEFAULT_PID 179 | ); 180 | exit(status); 181 | } 182 | 183 | static int _main(int argc, char *argv[]) 184 | { 185 | int opt; 186 | ctx->pid = DEFAULT_PID; 187 | 188 | while ((opt = getopt(argc, argv, "?h:P")) != -1) { 189 | switch (opt) { 190 | case 'P': 191 | if ((sscanf(optarg, "0x%x", &ctx->pid) != 1) || (ctx->pid > 0x1fff)) 192 | _usage(argv[0], 1); 193 | break; 194 | case '?': 195 | case 'h': 196 | _usage(argv[0], 0); 197 | } 198 | } 199 | 200 | smpte2038_generate_sample_708B_packet(ctx); 201 | exit(0); 202 | } 203 | 204 | int gensmpte2038_main(int argc, char *argv[]) 205 | { 206 | return _main(argc, argv); 207 | } 208 | -------------------------------------------------------------------------------- /tools/hexdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef HEXDUMP_H 23 | #define HEXDUMP_H 24 | 25 | __inline__ static void hexdump(unsigned char *buf, unsigned int len, int bytesPerRow /* Typically 16 */) 26 | { 27 | for (unsigned int i = 0; i < len; i++) 28 | printf("%02x%s", buf[i], ((i + 1) % bytesPerRow) ? " " : "\n"); 29 | printf("\n"); 30 | } 31 | 32 | #endif /* HEXDUMP_H */ 33 | -------------------------------------------------------------------------------- /tools/klringbuffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include "klringbuffer.h" 23 | 24 | KLRingBuffer *rb_new(size_t size, size_t size_max) 25 | { 26 | if ((size == 0) || (size > size_max)) 27 | return 0; 28 | 29 | KLRingBuffer *buf = malloc(sizeof(*buf)); 30 | if (!buf) 31 | return 0; 32 | 33 | buf->data = malloc(size); 34 | if (!buf->data) { 35 | free(buf); 36 | return 0; 37 | } 38 | 39 | buf->size = size; 40 | buf->size_initial = size; 41 | buf->head = buf->fill = 0; 42 | buf->size_max = size_max; 43 | 44 | return buf; 45 | } 46 | 47 | static int rb_grow(KLRingBuffer *buf, size_t increment) 48 | { 49 | if (!buf) 50 | return -1; 51 | 52 | if ((rb_size(buf) + increment) > buf->size_max) 53 | return -2; 54 | 55 | buf->data = realloc(buf->data, buf->size + increment); 56 | buf->size += increment; 57 | return 0; 58 | } 59 | 60 | static void rb_shrink_reset(KLRingBuffer *buf) 61 | { 62 | buf->data = realloc(buf->data, buf->size_initial); 63 | buf->size = buf->size_initial; 64 | buf->head = buf->fill = 0; 65 | } 66 | 67 | static inline void advance_tail(KLRingBuffer *buf, size_t bytes) 68 | { 69 | buf->fill += bytes; 70 | } 71 | 72 | size_t rb_write(KLRingBuffer *buf, const char *from, size_t bytes) 73 | { 74 | assert(buf); 75 | assert(from); 76 | 77 | if (bytes > rb_remain(buf)) { 78 | if (rb_grow(buf, bytes * 128) < 0) 79 | return 0; 80 | } 81 | 82 | unsigned char *tail = buf->data + ((buf->head + buf->fill) % buf->size); 83 | unsigned char *write_end = buf->data + ((buf->head + buf->fill + bytes) % buf->size); 84 | 85 | if (tail <= write_end) { 86 | memcpy(tail, from, bytes); 87 | } else { 88 | unsigned char *end = buf->data + buf->size; 89 | 90 | size_t first_write = end - tail; 91 | memcpy(tail, from, first_write); 92 | 93 | size_t second_write = bytes - first_write; 94 | memcpy(buf->data, from + first_write, second_write); 95 | } 96 | 97 | advance_tail(buf, bytes); 98 | return bytes; 99 | } 100 | 101 | #if 0 102 | char *rb_write_pointer(KLRingBuffer *buf, size_t *writable) 103 | { 104 | if(rb_is_full(buf)) 105 | { 106 | *writable = 0; 107 | return NULL; 108 | } 109 | 110 | char *head = buf->data + buf->head; 111 | char *tail = buf->data + ((buf->head + buf->fill) % buf->size); 112 | 113 | if(tail < head) 114 | { 115 | *writable = head - tail; 116 | } 117 | else 118 | { 119 | char *end = buf->data + buf->size; 120 | *writable = end - tail; 121 | } 122 | 123 | return tail; 124 | } 125 | 126 | void rb_write_commit(KLRingBuffer *buf, size_t bytes) 127 | { 128 | assert(bytes <= rb_remain(buf)); 129 | advance_tail(buf, bytes); 130 | } 131 | #endif 132 | 133 | static inline void advance_head(KLRingBuffer *buf, size_t bytes) 134 | { 135 | buf->head = (buf->head + bytes) % buf->size; 136 | buf->fill -= bytes; 137 | } 138 | 139 | static size_t rb_reader(KLRingBuffer *buf, char *to, size_t bytes, int advance_read_head) 140 | { 141 | assert(buf); 142 | assert(to); 143 | 144 | if (bytes > rb_used(buf)) 145 | bytes = rb_used(buf); 146 | 147 | if (bytes == 0) 148 | return 0; 149 | 150 | unsigned char *head = buf->data + buf->head; 151 | unsigned char *end_read = buf->data + ((buf->head + bytes) % buf->size); 152 | 153 | if (end_read <= head) { 154 | unsigned char *end = buf->data + buf->size; 155 | 156 | size_t first_read = end - head; 157 | memcpy(to, head, first_read); 158 | 159 | size_t second_read = bytes - first_read; 160 | memcpy(to + first_read, buf->data, second_read); 161 | } else { 162 | memcpy(to, head, bytes); 163 | } 164 | 165 | if (advance_read_head) 166 | advance_head(buf, bytes); 167 | 168 | /* When the buffer is empty its a good time to 169 | * free any prior large allocations. 170 | */ 171 | if ((rb_used(buf) == 0) && (buf->size > buf->size_initial)) 172 | rb_shrink_reset(buf); 173 | 174 | return bytes; 175 | } 176 | 177 | size_t rb_read(KLRingBuffer *buf, char *to, size_t bytes) 178 | { 179 | return rb_reader(buf, to, bytes, 1); /* Advance read head */ 180 | } 181 | 182 | size_t rb_peek(KLRingBuffer *buf, char *to, size_t bytes) 183 | { 184 | return rb_reader(buf, to, bytes, 0); /* Don't Advance read head */ 185 | } 186 | 187 | #if 0 188 | const char *rb_read_pointer(KLRingBuffer *buf, size_t offset, size_t *readable) 189 | { 190 | if(rb_is_empty(buf)) 191 | { 192 | *readable = 0; 193 | return NULL; 194 | } 195 | 196 | char *head = buf->data + buf->head + offset; 197 | char *tail = buf->data + ((buf->head + offset + buf->fill) % buf->size); 198 | 199 | if(tail <= head) 200 | { 201 | char *end = buf->data + buf->size; 202 | *readable = end - head; 203 | } 204 | else 205 | { 206 | *readable = tail - head; 207 | } 208 | 209 | return head; 210 | } 211 | 212 | void rb_read_commit(KLRingBuffer *buf, size_t bytes) 213 | { 214 | assert(rb_used(buf) >= bytes); 215 | advance_head(buf, bytes); 216 | } 217 | 218 | void rb_stream(KLRingBuffer *from, KLRingBuffer *to, size_t bytes) 219 | { 220 | assert(rb_used(from) <= bytes); 221 | assert(rb_remain(to) >= bytes); 222 | 223 | size_t copied = 0; 224 | while(copied < bytes) 225 | { 226 | size_t can_read; 227 | const char *from_ptr = rb_read_pointer(from, copied, &can_read); 228 | 229 | size_t copied_this_read = 0; 230 | 231 | while(copied_this_read < can_read) 232 | { 233 | size_t can_write; 234 | char *to_ptr = rb_write_pointer(to, &can_write); 235 | 236 | size_t write = (can_read > can_write) ? can_write : can_read; 237 | memcpy(to_ptr, from_ptr, write); 238 | 239 | copied_this_read += write; 240 | } 241 | 242 | copied += copied_this_read; 243 | } 244 | 245 | advance_tail(to, copied); 246 | } 247 | #endif 248 | 249 | void rb_free(KLRingBuffer *buf) 250 | { 251 | assert(buf); 252 | if (buf) { 253 | free(buf->data); 254 | free(buf); 255 | } 256 | } 257 | 258 | void rb_fwrite(KLRingBuffer *buf, FILE *fh) 259 | { 260 | if (rb_is_empty(buf)) 261 | return; 262 | 263 | unsigned char head[4] = { 'H', 'E', 'A', 'D' }; 264 | fwrite(&head[0], 1, sizeof(head), fh); 265 | 266 | unsigned int rb_len = rb_used(buf); 267 | unsigned char hdrlen[4] = { 268 | (rb_len >> 24) & 0xff, 269 | (rb_len >> 16) & 0xff, 270 | (rb_len >> 8) & 0xff, 271 | (rb_len >> 0) & 0xff 272 | }; 273 | fwrite(&hdrlen[0], 1, sizeof(hdrlen), fh); 274 | 275 | unsigned char b[8192]; 276 | size_t len = 1; 277 | while (len) { 278 | len = rb_read(buf, (char *)&b[0], sizeof(b)); 279 | if (len) 280 | fwrite(&b[0], 1, len, fh); 281 | } 282 | 283 | unsigned char tail[4] = { 'T', 'A', 'I', 'L' }; 284 | fwrite(&tail[0], 1, sizeof(tail), fh); 285 | } 286 | 287 | -------------------------------------------------------------------------------- /tools/klringbuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef KLRINGBUFFER_H 23 | #define KLRINGBUFFER_H 24 | 25 | /* Based on: https://gist.github.com/jsimmons/609674 */ 26 | 27 | /* A copy on write/read ring buffer, with the ability 28 | * to dynamically grow the buffer up to a user defined 29 | * maximum. Shrink buffer when its empty. 30 | */ 31 | 32 | /* KL Modifications for return values (read/write) so we 33 | * can track the number of bytes transferred. 34 | * Modifications to support dynamic growing of the 35 | * circular buffer. 36 | */ 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #define KLRINGBUFFER_STATUS(rb) \ 46 | printf("rb.size = %zu rb.remain = %zu rb.used = %zu\n", \ 47 | rb_size(rb), rb_remain(rb), rb_used(rb)); \ 48 | 49 | typedef struct 50 | { 51 | unsigned char *data; 52 | size_t size; 53 | size_t size_max; 54 | size_t size_initial; 55 | size_t head; 56 | size_t fill; 57 | } KLRingBuffer; 58 | 59 | KLRingBuffer *rb_new(size_t size, size_t size_max); 60 | 61 | static inline bool rb_is_empty(KLRingBuffer *buf) 62 | { 63 | return buf->fill == 0; 64 | } 65 | 66 | static inline bool rb_is_full(KLRingBuffer *buf) 67 | { 68 | return buf->fill == buf->size; 69 | } 70 | 71 | static inline size_t rb_size(KLRingBuffer *buf) 72 | { 73 | return buf->size; 74 | } 75 | 76 | static inline size_t rb_used(KLRingBuffer *buf) 77 | { 78 | return buf->fill; 79 | } 80 | 81 | static inline size_t rb_remain(KLRingBuffer *buf) 82 | { 83 | return buf->size - buf->fill; 84 | } 85 | 86 | static inline void rb_empty(KLRingBuffer *buf) 87 | { 88 | buf->head = buf->fill = 0; 89 | } 90 | 91 | size_t rb_write(KLRingBuffer *buf, const char *from, size_t bytes); 92 | #if 0 93 | char *rb_write_pointer(KLRingBuffer *buf, size_t *writable); 94 | void rb_write_commit(KLRingBuffer *buf, size_t bytes); 95 | #endif 96 | 97 | size_t rb_read(KLRingBuffer *buf, char *to, size_t bytes); 98 | size_t rb_peek(KLRingBuffer *buf, char *to, size_t bytes); 99 | 100 | #if 0 101 | const char *rb_read_pointer(KLRingBuffer *buf, size_t offset, size_t *readable); 102 | void rb_read_commit(KLRingBuffer *buf, size_t bytes); 103 | void rb_stream(KLRingBuffer *from, KLRingBuffer *to, size_t bytes); 104 | #endif 105 | 106 | void rb_free(KLRingBuffer *buf); 107 | 108 | void rb_fwrite(KLRingBuffer *buf, FILE *fh); 109 | 110 | #endif /* KLRINGBUFFER_H */ 111 | -------------------------------------------------------------------------------- /tools/klvanc_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* External tool hooks */ 27 | extern int demo_main(int argc, char *argv[]); 28 | extern int parse_main(int argc, char *argv[]); 29 | extern int smpte2038_main(int argc, char *argv[]); 30 | extern int scte104_main(int argc, char *argv[]); 31 | extern int genscte104_main(int argc, char *argv[]); 32 | extern int gensmpte2038_main(int argc, char *argv[]); 33 | extern int eia708_main(int argc, char *argv[]); 34 | extern int smpte12_2_main(int argc, char *argv[]); 35 | extern int afd_main(int argc, char *argv[]); 36 | 37 | typedef int (*func_ptr)(int, char *argv[]); 38 | 39 | int main(int argc, char *argv[]) 40 | { 41 | struct app_s { 42 | char *name; 43 | func_ptr func; 44 | } apps[] = { 45 | { "klvanc_util", demo_main, }, 46 | { "klvanc_parse", parse_main, }, 47 | { "klvanc_smpte2038", smpte2038_main, }, 48 | { "klvanc_scte104", scte104_main, }, 49 | { "klvanc_eia708", eia708_main, }, 50 | { "klvanc_genscte104", genscte104_main, }, 51 | { "klvanc_gensmpte2038", gensmpte2038_main, }, 52 | { "klvanc_smpte12_2", smpte12_2_main, }, 53 | { "klvanc_afd", afd_main, }, 54 | { 0, 0 }, 55 | }; 56 | char *appname = basename(argv[0]); 57 | 58 | int i = 0; 59 | struct app_s *app = &apps[i++]; 60 | while (app->name) { 61 | if (strcmp(appname, app->name) == 0) 62 | return app->func(argc, argv); 63 | 64 | app = &apps[i++]; 65 | } 66 | 67 | printf("No application called %s, aborting.\n", appname); 68 | i = 0; 69 | app = &apps[i++]; 70 | while (app->name) { 71 | printf("%s ", app->name); 72 | app = &apps[i++]; 73 | } 74 | 75 | return 1; 76 | } 77 | -------------------------------------------------------------------------------- /tools/meson.build: -------------------------------------------------------------------------------- 1 | sources = files( 2 | 'klvanc_util.c', 3 | 'demo.c', 4 | 'parse.c', 5 | 'smpte2038.c', 6 | 'scte104.c', 7 | 'genscte104.c', 8 | 'gensmpte2038.c', 9 | 'eia708.c', 10 | 'smpte12_2.c', 11 | 'afd.c', 12 | 'udp.c', 13 | 'url.c', 14 | 'ts_packetizer.c', 15 | 'klringbuffer.c', 16 | 'pes_extractor.c', 17 | ) 18 | 19 | thread_dep = dependency('threads') 20 | 21 | foreach exe_name: [ 22 | 'klvanc_util', 23 | 'klvanc_parse', 24 | 'klvanc_smpte2038', 25 | 'klvanc_scte104', 26 | 'klvanc_genscte104', 27 | 'klvanc_gensmpte2038', 28 | 'klvanc_eia708', 29 | 'klvanc_smpte12_2', 30 | 'klvanc_afd', 31 | ] 32 | exe = executable(exe_name, 33 | sources, 34 | install: true, 35 | install_tag: 'bin', 36 | dependencies: [libklvanc_dep, thread_dep] 37 | ) 38 | if exe_name in [ 39 | 'klvanc_eia708', 40 | 'klvanc_genscte104', 41 | 'klvanc_scte104', 42 | 'klvanc_smpte12_2', 43 | 'klvanc_gensmpte2038', 44 | 'klvanc_afd'] 45 | test_name = 'test_' + exe_name 46 | test(test_name, exe) 47 | elif exe_name == 'klvanc_smpte2038' 48 | test_name = 'test_' + exe_name 49 | test(test_name, exe, 50 | args : [ 51 | '-i ../samples/smpte2038-sample-pid-01e9.ts', 52 | '-P 0x1e9' 53 | ] 54 | ) 55 | endif 56 | endforeach 57 | -------------------------------------------------------------------------------- /tools/pes_extractor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "hexdump.h" 26 | #include "pes_extractor.h" 27 | 28 | #define MAX_PES_SIZE 16384 29 | #define LOCAL_DEBUG 0 30 | 31 | /* PES Extractor mechanism, so convert MULTIPLE TS packets containing PES VANC, into PES array. */ 32 | int pe_alloc(struct pes_extractor_s **pe, void *user_context, pes_extractor_callback cb, uint16_t pid) 33 | { 34 | struct pes_extractor_s *p = calloc(1, sizeof(*p)); 35 | if (!p) 36 | return -1; 37 | 38 | p->rb = rb_new(MAX_PES_SIZE, 1048576); 39 | if (!p->rb) { 40 | free(p); 41 | return -1; 42 | } 43 | 44 | p->pid = pid; 45 | p->cb_context = user_context; 46 | p->cb = cb; 47 | p->packet_size = 188; 48 | 49 | *pe = p; 50 | return 0; 51 | } 52 | 53 | void pe_free(struct pes_extractor_s **pe) 54 | { 55 | rb_free((*pe)->rb); 56 | free(*pe); 57 | } 58 | 59 | /* Take a single transport packet. 60 | * Calculate where the data begins. 61 | * Place all the data into a ring buffer. 62 | * Walk the ring buffer, locating any PES private data packets, 63 | * callback for each packet we detect. 64 | * ONLY PES_PRIVATE packets are supported, type 0xBD with 65 | * a valid length field. 66 | * Other packet types would be trivial to add, but know that 67 | * only VIDEO ES streams may have the pes_length value of zero 68 | * according to the spec. 69 | */ 70 | static void pe_processPacket(struct pes_extractor_s *pe, unsigned char *pkt, int len) 71 | { 72 | #if LOCAL_DEBUG 73 | printf("%s(len = %d)\n", __func__, len); 74 | #endif 75 | int offset = 4; 76 | #if 0 77 | if (*(pkt + 1) & 0x40) 78 | section_offset++; 79 | #endif 80 | 81 | unsigned char adaption = (*(pkt + 3) >> 4) & 0x03; 82 | if ((adaption == 2) || (adaption == 3)) { 83 | if (offset == 4) 84 | offset++; 85 | offset += *(pkt + 4); 86 | } 87 | 88 | /* Regardless, append all packete data from offset to end of packet into the buffer */ 89 | size_t wlen = pe->packet_size - offset; 90 | size_t l = rb_write(pe->rb, (const char *)pkt + offset, wlen); 91 | if (l != wlen) { 92 | printf("Write error, l = %zu, wlen = %zu\n", l, wlen); 93 | return; 94 | } 95 | 96 | /* Now, peek in the buffer, obtain packet sync and dequeue packets */ 97 | while (1) { 98 | /* If we have no yet syncronized, make that happen */ 99 | if (!pe->has_sync && rb_used(pe->rb) > 16) { 100 | unsigned char hdr[] = { 0, 0, 1, 0xbd }; 101 | unsigned char b[4]; 102 | rb_read(pe->rb, (char *)&b[0], sizeof(b)); 103 | for (size_t i = 0; i < rb_used(pe->rb); i++) { 104 | if (memcmp(b, hdr, sizeof(hdr)) == 0) { 105 | pe->has_sync = 1; 106 | break; 107 | } 108 | b[0] = b[1]; 109 | b[1] = b[2]; 110 | b[2] = b[3]; 111 | rb_read(pe->rb, (char *)&b[3], 1); 112 | } 113 | } 114 | 115 | if (!pe->has_sync) { 116 | /* Need more data */ 117 | #if LOCAL_DEBUG 118 | printf("Need more data #1\n"); 119 | #endif 120 | break; 121 | } 122 | 123 | /* We have at least one viable message, probably..... */ 124 | char l[2]; 125 | if (rb_peek(pe->rb, (char *)&l[0], 2) != 2) { 126 | fprintf(stderr, "Unable to peek two ring buffer bytes\n"); 127 | break; 128 | } 129 | 130 | uint16_t pes_length = ((l[0] & 0xff) << 8) | (l[1] & 0xff); 131 | 132 | if (rb_used(pe->rb) >= pes_length + 2) { 133 | /* Dequeue and process a complete pes message */ 134 | unsigned char *msg = malloc(pes_length + 6); 135 | if (msg) { 136 | msg[0] = 0; 137 | msg[1] = 0; 138 | msg[2] = 1; 139 | msg[3] = 0xbd; 140 | 141 | /* Read the peeked length and the entire message */ 142 | rb_read(pe->rb, (char *)msg + 4, pes_length + 2); 143 | #if LOCAL_DEBUG 144 | hexdump(msg, pes_length + 6, 16); 145 | #endif 146 | if (pe->cb) 147 | pe->cb(pe->cb_context, msg, pes_length + 6); 148 | free(msg); 149 | } 150 | pe->has_sync = 0; 151 | } else { 152 | #if LOCAL_DEBUG 153 | printf("Need more data #2 - got 0x%x (%d) need 0x%x (%d)\n", 154 | rb_used(pe->rb) + 2, 155 | rb_used(pe->rb) + 2, 156 | pes_length, 157 | pes_length); 158 | #endif 159 | break; /* Need more data */ 160 | } 161 | } 162 | } 163 | 164 | size_t pe_push(struct pes_extractor_s *pe, unsigned char *pkt, int packetCount) 165 | { 166 | #if LOCAL_DEBUG 167 | printf("%s(packetCount = 0x%x)\n", __func__, packetCount); 168 | #endif 169 | if ((!pe) || (packetCount < 1) || (!pkt)) 170 | return 0; 171 | 172 | for (int i = 0; i < packetCount; i++) { 173 | uint16_t pid = ((*(pkt + (i * pe->packet_size) + 1) << 8) | *(pkt + (i * pe->packet_size) + 2)) & 0x1fff; 174 | if (pid == pe->pid) { 175 | pe_processPacket(pe, pkt + (i * pe->packet_size), pe->packet_size); 176 | } 177 | } 178 | return packetCount; 179 | } 180 | -------------------------------------------------------------------------------- /tools/pes_extractor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | /* A mechanism to collect PES_PRIVATE_1 packets from 23 | * ISO13818 transport packets, dequeue them and feed them 24 | * to the caller via callbacks. 25 | */ 26 | 27 | #ifndef PES_EXTRATOR_H 28 | #define PES_EXTRATOR_H 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "klringbuffer.h" 37 | 38 | /* The PES Extractor will call your application in the same thread as the pe_processPacket 39 | * call happens. The buffer passed will be automatically freed upon completion of each callback, 40 | * under no circumstances attempt to retain it. 41 | */ 42 | typedef void (*pes_extractor_callback)(void *cb_context, unsigned char *buf, int byteCount); 43 | struct pes_extractor_s 44 | { 45 | /* Private data. None of these members are considered user visible. */ 46 | uint16_t pid; 47 | KLRingBuffer *rb; 48 | int packet_size; 49 | void *cb_context; 50 | pes_extractor_callback cb; 51 | int has_sync; 52 | }; 53 | 54 | /* PES Extractor mechanism, so convert MULTIPLE TS packets containing PES VANC, into PES array. */ 55 | int pe_alloc(struct pes_extractor_s **pe, void *user_context, pes_extractor_callback cb, uint16_t pid); 56 | 57 | /* Push one or more transport packets (buffer aligned) into the extraction framework. */ 58 | size_t pe_push(struct pes_extractor_s *pe, unsigned char *pkt, int packetCount); 59 | 60 | /* dealloc any private members inside the user allocated struct pes_extractor_s object. */ 61 | void pe_free(struct pes_extractor_s **pe); 62 | 63 | #endif /* PES_EXTRATOR_H */ 64 | -------------------------------------------------------------------------------- /tools/smpte12_2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | /* Normally we don't use a global, but we know our test harness will never be 27 | multi-threaded, and this is a really easy way to get the results out of the 28 | callback for comparison */ 29 | static uint16_t vancResult[16384]; 30 | static size_t vancResultCount; 31 | static int passCount = 0; 32 | static int failCount = 0; 33 | 34 | #define SHOW_DETAIL 1 35 | 36 | /* CALLBACKS for message notification */ 37 | static int cb_SMPTE_12_2(void *callback_context, struct klvanc_context_s *ctx, 38 | struct klvanc_packet_smpte_12_2_s *pkt) 39 | { 40 | int ret = -1; 41 | 42 | #ifdef SHOW_DETAIL 43 | /* Have the library display some debug */ 44 | printf("Asking libklvanc to dump a struct\n"); 45 | ret = klvanc_dump_SMPTE_12_2(ctx, pkt); 46 | if (ret != 0) { 47 | fprintf(stderr, "Error dumping SMPTE 12-2 packet!\n"); 48 | return -1; 49 | } 50 | #endif 51 | 52 | uint16_t *words; 53 | uint16_t wordCount; 54 | ret = klvanc_convert_SMPTE_12_2_to_words(ctx, pkt, &words, &wordCount); 55 | if (ret != 0) { 56 | fprintf(stderr, "Failed to convert SMPTE 12-2 to words: %d\n", ret); 57 | return -1; 58 | } 59 | 60 | memcpy(vancResult, words, wordCount * sizeof(uint16_t)); 61 | vancResultCount = wordCount; 62 | free(words); 63 | 64 | return 0; 65 | } 66 | 67 | static struct klvanc_callbacks_s callbacks = 68 | { 69 | .smpte_12_2 = cb_SMPTE_12_2, 70 | }; 71 | /* END - CALLBACKS for message notification */ 72 | 73 | static unsigned char test1[] = { 74 | 0x00, 0x00, 0x03, 0xff, 0x03, 0xff, 0x02, 0x60, 0x02, 0x60, 0x01, 0x10, 75 | 0x02, 0x28, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 76 | 0x01, 0x40, 0x02, 0x00, 0x01, 0x20, 0x02, 0x00, 0x02, 0x50, 0x02, 0x00, 77 | 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0xa8 78 | }; 79 | 80 | static int test_smpte_12_2(struct klvanc_context_s *ctx, const uint8_t *buf, size_t bufSize) 81 | { 82 | int numWords = bufSize / 2; 83 | int mismatch = 0; 84 | 85 | /* Clear out any previous results in case the callback never fires */ 86 | vancResultCount = 0; 87 | 88 | printf("\nParsing a new SMPTE 12-2 VANC packet......\n"); 89 | uint16_t *arr = malloc(bufSize); 90 | if (arr == NULL) 91 | return -1; 92 | 93 | for (int i = 0; i < numWords; i++) { 94 | arr[i] = buf[i * 2] << 8 | buf[i * 2 + 1]; 95 | } 96 | 97 | printf("Original Input\n"); 98 | for (int i = 0; i < numWords; i++) { 99 | printf("%04x ", arr[i]); 100 | } 101 | printf("\n"); 102 | 103 | int ret = klvanc_packet_parse(ctx, 13, arr, numWords); 104 | 105 | printf("Final output\n"); 106 | for (int i = 0; i < vancResultCount; i++) { 107 | printf("%04x ", vancResult[i]); 108 | } 109 | printf("\n"); 110 | 111 | for (int i = 0; i < vancResultCount; i++) { 112 | if (arr[i] != vancResult[i]) { 113 | fprintf(stderr, "Mismatch starting at offset 0x%02x\n", i); 114 | mismatch = 1; 115 | break; 116 | } 117 | } 118 | if (vancResultCount == 0) { 119 | /* No output at all. This is usually because the VANC parser choked 120 | on the VANC checksum and thus the parser never ran */ 121 | fprintf(stderr, "No output generated\n"); 122 | mismatch = 1; 123 | } 124 | 125 | free(arr); 126 | 127 | if (mismatch) { 128 | printf("Printing mismatched structure:\n"); 129 | failCount++; 130 | ret = klvanc_packet_parse(ctx, 13, vancResult, vancResultCount); 131 | } else { 132 | printf("Original and generated versions match!\n"); 133 | passCount++; 134 | } 135 | 136 | return ret; 137 | } 138 | 139 | int smpte12_2_main(int argc, char *argv[]) 140 | { 141 | struct klvanc_context_s *ctx; 142 | int ret; 143 | 144 | if (klvanc_context_create(&ctx) < 0) { 145 | fprintf(stderr, "Error initializing library context\n"); 146 | exit(1); 147 | } 148 | #ifdef SHOW_DETAIL 149 | ctx->verbose = 1; 150 | #endif 151 | ctx->callbacks = &callbacks; 152 | printf("Library initialized.\n"); 153 | 154 | ret = test_smpte_12_2(ctx, test1, sizeof(test1)); 155 | if (ret < 0) 156 | fprintf(stderr, "SMPTE 12-2 failed to parse\n"); 157 | 158 | 159 | klvanc_context_destroy(ctx); 160 | printf("Library destroyed.\n"); 161 | 162 | printf("Final result: PASS: %d/%d, Failures: %d\n", 163 | passCount, passCount + failCount, failCount); 164 | if (failCount != 0) 165 | return 1; 166 | return 0; 167 | } 168 | -------------------------------------------------------------------------------- /tools/ts_packetizer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "ts_packetizer.h" 27 | 28 | /* Convert PES data into a series of TS packets */ 29 | int ts_packetizer(uint8_t *buf, unsigned int byteCount, uint8_t **pkts, uint32_t *packetCount, 30 | int packetSize, uint8_t *cc, uint16_t pid) 31 | { 32 | if ((!buf) || (byteCount == 0) || (!pkts) || (!packetCount) || (packetSize != 188) || (!cc) || (pid > 0x1fff)) 33 | return -1; 34 | 35 | unsigned int offset = 0; 36 | 37 | int max = packetSize - 4; 38 | int packets = ((byteCount / max) + 1) * packetSize; 39 | int cnt = 0; 40 | 41 | uint8_t *arr = calloc(packets, packetSize); 42 | 43 | unsigned int rem = byteCount - offset; 44 | while (rem) { 45 | if (rem > max) 46 | rem = max; 47 | 48 | uint8_t *p = arr + (cnt * packetSize); 49 | *(p + 0) = 0x47; 50 | *(p + 1) = pid >> 8; 51 | *(p + 2) = pid; 52 | *(p + 3) = 0x10 | ((*cc) & 0x0f); 53 | memcpy(p + 4, buf + offset, rem); 54 | memset(p + 4 + rem, 0xff, packetSize - rem - 4); 55 | offset += rem; 56 | (*cc)++; 57 | 58 | if (cnt++ == 0) 59 | *(p + 1) |= 0x40; /* PES Header */ 60 | 61 | rem = byteCount - offset; 62 | } 63 | 64 | *pkts = arr; 65 | *packetCount = cnt; 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tools/ts_packetizer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef TS_PACKETIZER_H 23 | #define TS_PACKETIZER_H 24 | 25 | #include 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | int ts_packetizer(uint8_t *buf, unsigned int byteCount, uint8_t **pkts, uint32_t *packetCount, int packetSize, uint8_t *cc, uint16_t pid); 32 | 33 | #ifdef __cplusplus 34 | }; 35 | #endif 36 | 37 | 38 | #endif /* TS_PACKETIZER_H */ 39 | -------------------------------------------------------------------------------- /tools/udp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "udp.h" 37 | 38 | /* Compilation issues on centos, trouble headers won't include 39 | * * even with reasonable #defines. 40 | * */ 41 | #ifndef NI_MAXHOST 42 | #define NI_MAXHOST 1025 43 | #endif 44 | #ifndef NI_NUMERICHOST 45 | #define NI_NUMERICHOST 0x01 46 | #endif 47 | 48 | /* UDP Receiver ... */ 49 | 50 | static int modifyMulticastInterfaces(int skt, struct sockaddr_in *sin, char *ipaddr, unsigned short port, int option, char *ifname) 51 | { 52 | /* Setup multicast on all IPV4 network interfaces, IPV6 interfaces are ignored */ 53 | struct ifaddrs *addrs; 54 | int result = getifaddrs(&addrs); 55 | int didModify = 0; 56 | if (result >= 0) { 57 | const struct ifaddrs *cursor = addrs; 58 | while (cursor != NULL) { 59 | if ((cursor->ifa_flags & IFF_BROADCAST) && (cursor->ifa_flags & IFF_UP) && 60 | (cursor->ifa_addr->sa_family == AF_INET)) { 61 | 62 | char host[NI_MAXHOST]; 63 | 64 | int r = getnameinfo(cursor->ifa_addr, 65 | cursor->ifa_addr->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), 66 | host, NI_MAXHOST, 67 | NULL, 0, NI_NUMERICHOST); 68 | if (r == 0) { 69 | #if 0 70 | printf("ifa_name:%s flags:%x host:%s\n", cursor->ifa_name, cursor->ifa_flags, host); 71 | #endif 72 | int shouldModify = 1; 73 | 74 | if (ifname && (strcasecmp(ifname, cursor->ifa_name) != 0)) 75 | shouldModify = 0; 76 | 77 | if (shouldModify) { 78 | 79 | /* Enable multicast reception on this specific interface */ 80 | /* join multicast group */ 81 | struct ip_mreq mreq; 82 | mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; 83 | mreq.imr_interface.s_addr = ((struct sockaddr_in *)cursor->ifa_addr)->sin_addr.s_addr; 84 | if (setsockopt(skt, IPPROTO_IP, option, (void *)&mreq, sizeof(mreq)) < 0) { 85 | fprintf(stderr, "%s() cannot %s multicast group %s on iface %s\n", __func__, ipaddr, 86 | option == IP_ADD_MEMBERSHIP ? "join" : "leave", 87 | cursor->ifa_name 88 | ); 89 | return -1; 90 | } else { 91 | didModify++; 92 | fprintf(stderr, "%s() %s multicast group %s ok on iface %s\n", __func__, ipaddr, 93 | option == IP_ADD_MEMBERSHIP ? "join" : "leave", 94 | cursor->ifa_name 95 | ); 96 | } 97 | } 98 | } 99 | } 100 | cursor = cursor->ifa_next; 101 | } 102 | } 103 | 104 | if (didModify) 105 | return 0; /* Success */ 106 | else 107 | return -1; 108 | } 109 | 110 | int iso13818_udp_receiver_alloc(struct iso13818_udp_receiver_s **p, 111 | unsigned int socket_buffer_size, 112 | const char *ip_addr, 113 | unsigned short ip_port, 114 | tsudp_receiver_callback cb, 115 | void *userContext, 116 | int stripRTPHeader) 117 | { 118 | if (!ip_addr) 119 | return -1; 120 | 121 | struct iso13818_udp_receiver_s *ctx = (struct iso13818_udp_receiver_s *)calloc(1, sizeof(*ctx)); 122 | 123 | ctx->ip_port = ip_port; 124 | ctx->rxbuffer_size = 2048; 125 | ctx->threadId = 0; 126 | ctx->thread_running = ctx->thread_terminate = ctx->thread_complete = 0; 127 | strncpy(ctx->ip_addr, ip_addr, sizeof(ctx->ip_addr) - 1); 128 | ctx->cb = cb; 129 | ctx->userContext = userContext; 130 | ctx->stripRTPHeader = stripRTPHeader; 131 | 132 | /* Create the UDP discover socket */ 133 | ctx->skt = socket(AF_INET, SOCK_DGRAM, 0); 134 | if (ctx->skt < 0) { 135 | free(ctx); 136 | return -1; 137 | } 138 | 139 | int n = socket_buffer_size; 140 | if (setsockopt(ctx->skt, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) { 141 | perror("so_rcvbuf"); 142 | free(ctx); 143 | return -1; 144 | } 145 | 146 | int reuse = 1; 147 | if (setsockopt(ctx->skt, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { 148 | free(ctx); 149 | return -1; 150 | } 151 | 152 | ctx->sin.sin_family = AF_INET; 153 | ctx->sin.sin_port = htons(ctx->ip_port); 154 | ctx->sin.sin_addr.s_addr = inet_addr(ctx->ip_addr); 155 | if (bind(ctx->skt, (struct sockaddr *)&ctx->sin, sizeof(ctx->sin)) < 0) { 156 | perror("bind"); 157 | free(ctx); 158 | return -1; 159 | } 160 | 161 | if (IN_MULTICAST(ntohl(ctx->sin.sin_addr.s_addr))) { 162 | //modifyMulticastInterfaces(ctx->skt, &ctx->sin, ctx->ip_addr, ctx->ip_port, IP_ADD_MEMBERSHIP, 0); 163 | } 164 | 165 | /* Non-blocking required */ 166 | int fl = fcntl(ctx->skt, F_GETFL, 0); 167 | if (fcntl(ctx->skt, F_SETFL, fl | O_NONBLOCK) < 0) { 168 | perror("fcntl"); 169 | free(ctx); 170 | return -1; 171 | } 172 | 173 | ctx->rxbuffer = malloc(ctx->rxbuffer_size); 174 | if (!ctx->rxbuffer) { 175 | free(ctx); 176 | return -1; 177 | } 178 | 179 | pthread_mutex_init(&ctx->fh_mutex, NULL); 180 | *p = ctx; 181 | return 0; 182 | } 183 | 184 | void iso13818_udp_receiver_free(struct iso13818_udp_receiver_s **p) 185 | { 186 | struct iso13818_udp_receiver_s *ctx = (struct iso13818_udp_receiver_s *)*p; 187 | 188 | ctx->thread_terminate = 1; 189 | if (ctx->thread_running) { 190 | while (!ctx->thread_complete) 191 | usleep(50 * 1000); 192 | } 193 | 194 | if (ctx->skt != -1) { 195 | if (IN_MULTICAST(ntohl(ctx->sin.sin_addr.s_addr))) 196 | modifyMulticastInterfaces(ctx->skt, &ctx->sin, ctx->ip_addr, ctx->ip_port, IP_DROP_MEMBERSHIP, 0); 197 | close(ctx->skt); 198 | } 199 | 200 | free(ctx->rxbuffer); 201 | free(ctx); 202 | *p = 0; 203 | } 204 | 205 | int iso13818_udp_receiver_join_multicast(struct iso13818_udp_receiver_s *ctx, char *ifname) 206 | { 207 | assert(ctx && ifname); 208 | if (!IN_MULTICAST(ntohl(ctx->sin.sin_addr.s_addr))) 209 | return -1; 210 | 211 | return modifyMulticastInterfaces(ctx->skt, &ctx->sin, ctx->ip_addr, ctx->ip_port, IP_ADD_MEMBERSHIP, ifname); 212 | } 213 | 214 | int iso13818_udp_receiver_drop_multicast(struct iso13818_udp_receiver_s *ctx, char *ifname) 215 | { 216 | assert(ctx && ifname); 217 | if (!IN_MULTICAST(ntohl(ctx->sin.sin_addr.s_addr))) 218 | return -1; 219 | 220 | return modifyMulticastInterfaces(ctx->skt, &ctx->sin, ctx->ip_addr, ctx->ip_port, IP_DROP_MEMBERSHIP, ifname); 221 | } 222 | 223 | static void *udp_receiver_threadfunc(void *p) 224 | { 225 | struct iso13818_udp_receiver_s *ctx = (struct iso13818_udp_receiver_s *)p; 226 | 227 | ctx->thread_running = 1; 228 | while (!ctx->thread_terminate) { 229 | struct pollfd fds = { .fd = ctx->skt, .events = POLLIN, .revents = 0 }; 230 | 231 | /* Wait for up to 250ms on a timeout based on socket activity */ 232 | int ret = poll(&fds, 1, 250); 233 | if (ret == 0) { 234 | /* Timeout */ 235 | continue; 236 | } 237 | 238 | if (ret < 0) { 239 | /* Unspecified error */ 240 | continue; 241 | } 242 | 243 | /* Ret > 0, meaning our FD returned data is available. */ 244 | 245 | /* Push the arbitrary buffer of bytes, output is fully aligned 246 | * packets via the tool_realign_callback callback, which are 247 | * then pushed directly into the core. 248 | */ 249 | size_t rxbytes = recv(ctx->skt, ctx->rxbuffer, ctx->rxbuffer_size, 0); 250 | if (rxbytes && ctx->cb && !ctx->stripRTPHeader) { 251 | ctx->cb(ctx->userContext, ctx->rxbuffer, rxbytes); 252 | } 253 | else 254 | if (rxbytes && ctx->cb && ctx->stripRTPHeader) { 255 | /* Some implementations pad the trailer of the packet with 256 | * dummy bytes, we don't want to pass these along. 257 | * Hint: Ceton does, silicondust doesn't */ 258 | int bytes = ((rxbytes - 12) / 188) * 188; 259 | ctx->cb(ctx->userContext, ctx->rxbuffer + 12, bytes); 260 | } 261 | 262 | } 263 | ctx->thread_complete = 1; 264 | ctx->thread_running = 0; 265 | pthread_exit(0); 266 | } 267 | 268 | int iso13818_udp_receiver_thread_start(struct iso13818_udp_receiver_s *ctx) 269 | { 270 | assert(ctx); 271 | assert(ctx->threadId == 0); 272 | return pthread_create(&ctx->threadId, 0, udp_receiver_threadfunc, ctx); 273 | } 274 | 275 | /* UDP Transmitter ... */ 276 | -------------------------------------------------------------------------------- /tools/udp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef ISO13818_H 23 | #define ISO13818_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | typedef void (*tsudp_receiver_callback)(void *userContext, unsigned char *buf, int byteCount); 40 | struct iso13818_udp_receiver_s 41 | { 42 | int skt; 43 | 44 | struct sockaddr_in sin; 45 | unsigned int ip_port; 46 | char ip_addr[32]; 47 | int stripRTPHeader; 48 | 49 | unsigned char *rxbuffer; 50 | unsigned int rxbuffer_size; 51 | 52 | pthread_t threadId; 53 | int thread_running; 54 | int thread_terminate; 55 | int thread_complete; 56 | 57 | tsudp_receiver_callback cb; 58 | void *userContext; 59 | 60 | /* Debug dumping to disk */ 61 | pthread_mutex_t fh_mutex; 62 | FILE *fh; 63 | }; 64 | 65 | int iso13818_udp_receiver_alloc(struct iso13818_udp_receiver_s **p, 66 | unsigned int socket_buffer_size, 67 | const char *ip_addr, 68 | unsigned short ip_port, 69 | tsudp_receiver_callback cb, 70 | void *userContext, 71 | int stripRTPHeader); 72 | void iso13818_udp_receiver_free(struct iso13818_udp_receiver_s **p); 73 | ssize_t iso13818_udp_receiver_read(struct iso13818_udp_receiver_s *ctx, unsigned char *buf, unsigned int byteCount); 74 | int iso13818_udp_receiver_thread_start(struct iso13818_udp_receiver_s *ctx); 75 | 76 | /* Add or remove a specific network interface from the receiver, if its a multicast address */ 77 | int iso13818_udp_receiver_join_multicast(struct iso13818_udp_receiver_s *p, char *ifname); 78 | int iso13818_udp_receiver_drop_multicast(struct iso13818_udp_receiver_s *p, char *ifname); 79 | 80 | #ifdef __cplusplus 81 | }; 82 | #endif 83 | #endif /* ISO13818_H */ 84 | -------------------------------------------------------------------------------- /tools/url.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "url.h" 28 | 29 | static int url_argsplit(char *arg, char **tag, char **value) 30 | { 31 | if (!arg) 32 | return -1; 33 | 34 | /* Dup the string as we may want to modify it */ 35 | char *tmp = calloc(1, 256); 36 | strcpy(tmp, arg); 37 | char *str = tmp; 38 | 39 | char *p = strsep(&str, "="); 40 | if (!p || !str) { 41 | free(tmp); 42 | return -2; 43 | } 44 | *tag = strdup(p); 45 | if (*tag == NULL) { 46 | free(tmp); 47 | return -1; 48 | } 49 | 50 | p = strsep(&str, "="); 51 | /* Strip any trailing args */ 52 | for (int i = 0; i < strlen(p); i++) { 53 | if ((*(p + i) == '?') || (*(p + i) == '&')) { 54 | *(p + i) = 0; 55 | break; 56 | } 57 | } 58 | *value = strdup(p); 59 | if (*value == NULL) { 60 | free(tmp); 61 | return -1; 62 | } 63 | 64 | free(tmp); 65 | return 0; 66 | } 67 | 68 | static int regex_match(const char *str, const char *pattern) 69 | { 70 | int ret = -1; 71 | regex_t rex; 72 | if (regcomp(&rex, pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE) == 0) { 73 | 74 | if (regexec(&rex, str, 0, 0, 0) == REG_NOMATCH) { 75 | ret = -1; 76 | } else { 77 | ret = 0; 78 | } 79 | } 80 | 81 | regfree(&rex); 82 | return ret; 83 | } 84 | 85 | void url_print(struct url_opts_s *url) 86 | { 87 | printf("url = %s\n", url->url); 88 | printf("\tprotocol = %s\n", url->protocol); 89 | printf("\tprotocol_type = %d [ %s ]\n", 90 | url->protocol_type, 91 | url->protocol_type == P_UDP ? "P_UDP" : 92 | url->protocol_type == P_RTP ? "P_RTP" : "UNDEFINED" 93 | ); 94 | printf("\thostname = %s\n", url->hostname); 95 | printf("\thas_ipaddress = %d\n", url->has_ipaddress); 96 | if (url->has_port) { 97 | printf("\thas_port = %d\n", url->has_port); 98 | printf("\t\tport = %d\n", url->port); 99 | } 100 | if (url->has_ifname) { 101 | printf("\thas_ifname = %d\n", url->has_ifname); 102 | printf("\t\tifname = %s\n", url->ifname); 103 | } 104 | #if 0 105 | if (url->has_buffersize) { 106 | printf("\thas_buffersize = %d\n", url->has_buffersize); 107 | printf("\t\tbuffersize = %d\n", url->buffersize); 108 | } 109 | #endif 110 | if (url->has_fifosize) { 111 | printf("\thas_fifosize = %d\n", url->has_fifosize); 112 | printf("\t\tfifosize = %d\n", url->fifosize); 113 | } 114 | } 115 | 116 | static int has_url_argname(const char *url, const char *argname) 117 | { 118 | char tmp[256]; 119 | sprintf(tmp, "\\?%s=", argname); 120 | if (regex_match(url, tmp) < 0) { 121 | tmp[1] = '&'; 122 | if (regex_match(url, tmp) < 0) { 123 | return 0; 124 | } 125 | } 126 | return 1; 127 | } 128 | 129 | int url_parse(const char *url, struct url_opts_s **result) 130 | { 131 | int ret; 132 | int has_args = 0; 133 | struct url_opts_s *opts = calloc(1, sizeof(*opts)); 134 | strncpy(opts->url, url, sizeof(opts->url) - 1); 135 | 136 | /* Check the protocol */ 137 | if (regex_match(url, "^(udp|rtp)://") < 0) { 138 | ret = -1; 139 | goto err; 140 | } 141 | 142 | if (has_url_argname(url, "ifname") == 0) { 143 | opts->has_ifname = 0; 144 | } else { 145 | opts->has_ifname = 1; 146 | has_args++; 147 | } 148 | 149 | #if 0 150 | if (has_url_argname(url, "buffersize") == 0) { 151 | opts->has_buffersize = 0; 152 | } else 153 | opts->has_buffersize = 1; 154 | #endif 155 | 156 | if (has_url_argname(url, "fifosize") == 0) { 157 | opts->has_fifosize = 0; 158 | } else { 159 | opts->has_fifosize = 1; 160 | has_args++; 161 | } 162 | 163 | /* Validate the basic shape of the URL */ 164 | if (regex_match(url, "://[0-9a-zA-Z].*:[0-9]*") < 0) { 165 | free(opts); 166 | return -1; 167 | } 168 | 169 | /* Clone the string into a tmp buffer as strsep will want to modify it */ 170 | char tmp[256]; 171 | memset(tmp, 0, sizeof(tmp)); 172 | strncpy(tmp, url, sizeof(tmp) - 1); 173 | 174 | char *str = &tmp[0]; 175 | char *p = strsep(&str, ":"); 176 | if (!p || !str) { 177 | free(opts); 178 | return -1; 179 | } 180 | 181 | strncpy(opts->protocol, p, sizeof(opts->protocol) - 1); 182 | if (strcasecmp(opts->protocol, "udp") == 0) 183 | opts->protocol_type = P_UDP; 184 | else 185 | if (strcasecmp(opts->protocol, "rtp") == 0) 186 | opts->protocol_type = P_RTP; 187 | 188 | /* Skip the "//" after the : */ 189 | if ((*(str + 0) == '/') && *(str + 1) == '/') 190 | str += 2; 191 | 192 | /* ip address */ 193 | p = strsep(&str, ":"); 194 | if (!p) { 195 | /* No hostname */ 196 | free(opts); 197 | return -2; 198 | } 199 | 200 | if (regex_match(p, "^\[0-9].*.$") == 0) 201 | opts->has_ipaddress = 1; 202 | 203 | strncpy(opts->hostname, p, sizeof(opts->hostname) - 1); 204 | 205 | /* ip port */ 206 | p = strsep(&str, ":"); 207 | if (!p) { 208 | /* No port */ 209 | free(opts); 210 | return -2; 211 | } 212 | 213 | opts->port = atoi(p); 214 | if (opts->port <= 65535) 215 | opts->has_port = 1; 216 | 217 | char tmp2[256]; 218 | memset(tmp2, 0, sizeof(tmp)); 219 | strncpy(tmp2, url, sizeof(tmp2) - 1); 220 | char *str2 = &tmp2[0]; 221 | 222 | char *q = strsep(&str2, "?&"); 223 | while (q && has_args) { 224 | 225 | q = strsep(&str2, "?&"); 226 | if (!q) 227 | break; 228 | 229 | char *tag = 0, *value = 0; 230 | if (url_argsplit(q, &tag, &value) < 0) { 231 | printf("split error\n"); 232 | } 233 | //printf("tag = [%s] = [%s]\n", tag, value); 234 | if (tag) { 235 | if (strcasecmp(tag, "ifname") == 0) 236 | strncpy(opts->ifname, value, sizeof(opts->ifname) - 1); 237 | else 238 | #if 0 239 | if (strcasecmp(tag, "buffersize") == 0) 240 | opts->buffersize = atoi(value); 241 | else 242 | #endif 243 | if (strcasecmp(tag, "fifosize") == 0) 244 | opts->fifosize = atoi(value); 245 | else { 246 | fprintf(stderr, "Unknown tag [%s], aborting.\n", tag); 247 | free(tag); 248 | free(value); 249 | ret = -1; 250 | goto err; 251 | } 252 | free(tag); 253 | } 254 | if (value) 255 | free(value); 256 | } 257 | 258 | /* Success */ 259 | ret = 0; 260 | 261 | *result = opts; 262 | return ret; 263 | err: 264 | *result = 0; 265 | free(opts); 266 | return ret; 267 | } 268 | 269 | void url_free(struct url_opts_s *arg) 270 | { 271 | free(arg); 272 | } 273 | 274 | -------------------------------------------------------------------------------- /tools/url.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef ISO13818_URL_H 23 | #define ISO13818_URL_H 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /* udp://hostname:port/?ifname=eth0&fifosize=1048576 */ 30 | struct url_opts_s 31 | { 32 | char url[256]; 33 | 34 | char protocol[16]; 35 | enum protocol_e { 36 | P_UNDEFINED = 0, 37 | P_UDP, 38 | P_RTP 39 | } protocol_type; 40 | 41 | /* Whether we think hostname contains a pure ip address */ 42 | int has_ipaddress; 43 | char hostname[64]; 44 | 45 | /* 1-65535 */ 46 | int has_port; 47 | int port; 48 | 49 | #if 0 50 | int has_buffersize; 51 | int buffersize; 52 | #endif 53 | 54 | /* socket buffer rx/tx size (bytes) */ 55 | int has_fifosize; 56 | int fifosize; 57 | 58 | int has_ifname; 59 | char ifname[16]; 60 | }; 61 | 62 | void url_print(struct url_opts_s *url); 63 | int url_parse(const char *url, struct url_opts_s **result); 64 | void url_free(struct url_opts_s *arg); 65 | 66 | #ifdef __cplusplus 67 | }; 68 | #endif 69 | 70 | #endif /* ISO13818_URL_H */ 71 | -------------------------------------------------------------------------------- /tools/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 Kernel Labs Inc. All Rights Reserved 3 | * 4 | * Address: Kernel Labs Inc., PO Box 745, St James, NY. 11780 5 | * Contact: sales@kernellabs.com 6 | * 7 | * This library is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU Lesser General Public 9 | * License as published by the Free Software Foundation; either 10 | * version 2.1 of the License, or (at your option) any later version. 11 | * 12 | * This library is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * Lesser General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public 18 | * License along with this library; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #define COPYRIGHT "Copyright Kernel Labs Inc 2014-2016. All Rights Reserved." 23 | --------------------------------------------------------------------------------