├── .gitignore ├── LICENSE_BSD.txt ├── Makefile ├── README.md ├── edge264.c ├── edge264.h ├── edge264_bitstream.c ├── edge264_deblock.c ├── edge264_headers.c ├── edge264_inter.c ├── edge264_internal.h ├── edge264_intra.c ├── edge264_mvpred.c ├── edge264_residual.c ├── edge264_sei.c ├── edge264_slice.c ├── edge264_test.c └── tools ├── gen_avc.py ├── split_gops.c └── unit_tests.c /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !edge264*.c 4 | !edge264*.h 5 | !LICENSE_BSD.txt 6 | !Makefile 7 | !*.md 8 | -------------------------------------------------------------------------------- /LICENSE_BSD.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014, Celticom / TVLabs 2 | Copyright (c) 2014-2024 Thibault Raffaillac 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ARCH ?= native 2 | OS ?= $(shell uname) 3 | BUILD_TEST ?= yes 4 | VARIANTS ?= logs 5 | 6 | VERSION := 1.0.0 7 | MAJOR := 1 8 | TARGETCC := $(CC) 9 | LDLINUX := -Wl,-soname,libedge264.so.$(MAJOR) -Wl,-rpath,'$$ORIGIN' 10 | override CFLAGS := -std=gnu11 -O3 -flax-vector-conversions -w $(if $(findstring Windows,$(OS)),,-fpic) $(CFLAGS) 11 | override LDFLAGS := -pthread $(if $(findstring Linux,$(OS)),$(LDLINUX),) $(LDFLAGS) 12 | RUNTIME_TESTS := $(if $(findstring x86-64-v2,$(VARIANTS)),-DHAS_X86_64_V2,) $(if $(findstring x86-64-v3,$(VARIANTS)),-DHAS_X86_64_V3,) $(if $(findstring logs,$(VARIANTS)),-DHAS_LOGS,) 13 | OBJ := edge264.o $(if $(findstring x86-64-v2,$(VARIANTS)),edge264_headers_v2.o,) $(if $(findstring x86-64-v3,$(VARIANTS)),edge264_headers_v3.o,) $(if $(findstring logs,$(VARIANTS)),edge264_headers_log.o,) 14 | LIB := $(if $(findstring Windows,$(OS)),edge264.$(MAJOR).dll,$(if $(findstring Linux,$(OS)),libedge264.so.$(VERSION),libedge264.$(VERSION).dylib)) 15 | EXE := $(if $(findstring Windows,$(OS)),edge264_test.exe,edge264_test) 16 | .DEFAULT_GOAL := $(if $(findstring yes,$(BUILD_TEST)),$(EXE),$(LIB)) 17 | 18 | 19 | # check existence of compiler executable 20 | WHICH := $(if $(findstring Windows,$(OS)),where 2>nul,which 2>/dev/null) 21 | ifeq (,$(shell $(WHICH) $(CC))) 22 | $(error CC=$(CC) does not point to a valid command, consider passing CC=gcc or CC=clang and having any of these compilers installed) 23 | endif 24 | 25 | 26 | # rules 27 | $(EXE): edge264_test.c edge264.h $(LIB) 28 | $(TARGETCC) edge264_test.c $(LIB) -march=$(ARCH) -O3 $(LDFLAGS) -o $(EXE) 29 | 30 | $(LIB): $(OBJ) 31 | $(TARGETCC) -shared $(OBJ) $(LDFLAGS) -o $(LIB) 32 | 33 | edge264.o: edge264.h edge264_internal.h edge264.c edge264_bitstream.c edge264_deblock.c edge264_headers.c edge264_inter.c edge264_intra.c edge264_mvpred.c edge264_residual.c edge264_slice.c 34 | $(CC) edge264.c -c -march=$(ARCH) $(CFLAGS) $(RUNTIME_TESTS) -o edge264.o 35 | 36 | edge264_headers_v2.o: edge264.h edge264_internal.h edge264_bitstream.c edge264_deblock.c edge264_headers.c edge264_inter.c edge264_intra.c edge264_mvpred.c edge264_residual.c edge264_slice.c 37 | $(CC) edge264_headers.c -c -march=x86-64-v2 $(CFLAGS) "-DADD_VARIANT(f)=f##_v2" -o edge264_headers_v2.o 38 | 39 | edge264_headers_v3.o: edge264.h edge264_internal.h edge264_bitstream.c edge264_deblock.c edge264_headers.c edge264_inter.c edge264_intra.c edge264_mvpred.c edge264_residual.c edge264_slice.c 40 | $(CC) edge264_headers.c -c -march=x86-64-v3 $(CFLAGS) "-DADD_VARIANT(f)=f##_v3" -o edge264_headers_v3.o 41 | 42 | edge264_headers_log.o: edge264.h edge264_internal.h edge264_bitstream.c edge264_deblock.c edge264_headers.c edge264_inter.c edge264_intra.c edge264_mvpred.c edge264_residual.c edge264_sei.c edge264_slice.c 43 | $(CC) edge264_headers.c -c -march=$(ARCH) $(CFLAGS) -DLOGS "-DADD_VARIANT(f)=f##_log" -o edge264_headers_log.o 44 | 45 | .PHONY: clean clear 46 | clean clear: 47 | rm -f release/* $(EXE) edge264*.o libedge264*.dylib libedge264.so.* edge264*.dll 48 | 49 | 50 | # hard-coded for my machine (mac-x64), edit to make them work on your own 51 | LINUX_GNU_X86_SYSROOT := i686-unknown-linux-gnu/i686-unknown-linux-gnu/sysroot 52 | LINUX_GNU_X86_GCC := i686-unknown-linux-gnu/bin/i686-linux-gnu-gcc 53 | LINUX_GNU_X64_SYSROOT := x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot 54 | LINUX_GNU_X64_GCC := x86_64-unknown-linux-gnu/bin/x86_64-linux-gnu-gcc 55 | LINUX_MUSL_ARM64_SYSROOT := aarch64-unknown-linux-musl/aarch64-unknown-linux-musl/sysroot 56 | LINUX_MUSL_ARM64_GCC := aarch64-unknown-linux-musl/bin/aarch64-unknown-linux-musl-gcc 57 | WINDOWS_MINGW_X86_TOOLCHAIN := /usr/local/Cellar/mingw-w64/12.0.0_1/toolchain-i686 58 | WINDOWS_MINGW_X64_TOOLCHAIN := /usr/local/Cellar/mingw-w64/12.0.0_1/toolchain-x86_64 59 | .PHONY: release 60 | release: edge264*.c edge264*.h Makefile 61 | mkdir -p release 62 | # x86_64-apple-darwinXX 63 | $(MAKE) ARCH=core2 VARIANTS=x86-64-v3,logs BUILD_TEST=no 64 | zip -m release/edge264-$(VERSION)-mac-x64.zip libedge264.$(VERSION).dylib 65 | # i686-linux-gnu 66 | $(MAKE) ARCH=pentium-m OS=Linux VARIANTS=x86-64-v2,x86-64-v3,logs BUILD_TEST=no CFLAGS="--target=i686-linux-gnu --sysroot=$(LINUX_GNU_X86_SYSROOT)" TARGETCC=$(LINUX_GNU_X86_GCC) 67 | zip -m release/edge264-$(VERSION)-linux-gnu-x86.zip libedge264.so.$(VERSION) 68 | # x86_64-linux-gnu 69 | $(MAKE) ARCH=x86-64 OS=Linux VARIANTS=x86-64-v2,x86-64-v3,logs BUILD_TEST=no CFLAGS="--target=x86_64-linux-gnu --sysroot=$(LINUX_GNU_X64_SYSROOT)" TARGETCC=$(LINUX_GNU_X64_GCC) 70 | zip -m release/edge264-$(VERSION)-linux-gnu-x64.zip libedge264.so.$(VERSION) 71 | # i686-w64-mingw32 72 | $(MAKE) ARCH=pentium-m OS=Windows VARIANTS=x86-64-v2,x86-64-v3,logs BUILD_TEST=no CFLAGS="--target=i686-w64-mingw32 --sysroot=$(WINDOWS_MINGW_X86_TOOLCHAIN)" TARGETCC=$(WINDOWS_MINGW_X86_TOOLCHAIN)/bin/i686-w64-mingw32-gcc 73 | zip -m release/edge264-$(VERSION)-windows-mingw-x86.zip edge264.$(MAJOR).dll 74 | # x86_64-w64-mingw32 75 | $(MAKE) ARCH=x86-64 OS=Windows VARIANTS=x86-64-v2,x86-64-v3,logs BUILD_TEST=no CFLAGS="--target=x86_64-w64-mingw32 --sysroot=$(WINDOWS_MINGW_X64_TOOLCHAIN)" TARGETCC=$(WINDOWS_MINGW_X64_TOOLCHAIN)/bin/x86_64-w64-mingw32-gcc 76 | zip -m release/edge264-$(VERSION)-windows-mingw-x64.zip edge264.$(MAJOR).dll 77 | # aarch64-linux-musl 78 | $(MAKE) ARCH=armv8-a+simd OS=Linux VARIANTS=logs BUILD_TEST=no CFLAGS="--target=aarch64-linux-musl --sysroot=$(LINUX_MUSL_ARM64_SYSROOT)" TARGETCC=$(LINUX_MUSL_ARM64_GCC) 79 | zip -m release/edge264-$(VERSION)-linux-musl-arm64.zip libedge264.so.$(VERSION) 80 | 81 | 82 | # cross-compiling edge264_test for aarch64-linux 83 | # make ARCH=armv8-a+simd OS=Linux VARIANTS=logs CFLAGS="--target=aarch64-linux-musl --sysroot=aarch64-unknown-linux-musl/aarch64-unknown-linux-musl/sysroot" TARGETCC=aarch64-unknown-linux-musl/bin/aarch64-unknown-linux-musl-gcc LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'" 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | edge264 2 | ======= 3 | 4 | Minimalist software decoder with state-of-the-art performance for the H.264/AVC video format. 5 | 6 | *Please note this is a work in progress and will be ready for use after making GStreamer/VLC plugins.* 7 | 8 | Features 9 | -------- 10 | 11 | * Supports **Progressive High** and **MVC 3D** profiles, up to level 6.2 12 | * Any resolution up to 8K UHD 13 | * 8-bit 4:2:0 planar YUV output 14 | * Slices and Arbitrary Slice Order 15 | * Slice and frame multi-threading 16 | * Per-slice reference picture list 17 | * Memory Management Control Operations 18 | * Long-term reference frames 19 | 20 | 21 | Supported platforms 22 | ------------------- 23 | 24 | * Windows: x86, x64 25 | * Linux: x86, x64, ARM64 26 | * Mac OS: x64 27 | 28 | 29 | Compiling and testing 30 | --------------------- 31 | 32 | edge264 is entirely developed in C using 128-bit [vector extensions](https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html) and vector intrinsics, and can be compiled with GNU GCC or LLVM Clang. [SDL2](https://www.libsdl.org/) runtime library may be used (optional) to enable display with `edge264_test`. 33 | 34 | Here are the `make` options for tuning the compiled library file: 35 | 36 | * `CC` - C compiler used to convert source file to object files (default `cc`) 37 | * `CFLAGS` - additional compilation flags passed to `CC` 38 | * `ARCH` - target architecture that will be passed to -march (default `native`) 39 | * `OS` - target operating system (defaults to host) 40 | * `TARGETCC` - C compiler used to link object files into library file (defaults to `CC`) 41 | * `LDFLAGS` - additional compilation flags passed to `TARGETCC` 42 | * `VARIANTS` - comma-separated list of additional variants included in the library and selected at runtime (default `logs`) 43 | * `x86-64-v2` - variant compiled for x86-64 microarchitecture level 2 (SSSE3, SSE4.1 and POPCOUNT) 44 | * `x86-64-v3` - variant compiled for x86-64 microarchitecture level 3 (AVX2, BMI, LZCNT, MOVBE) 45 | * `logs` - variant compiled with logging support in YAML format (headers and slices) 46 | * `BUILD_TEST` - toggles compilation of `edge264_test` (default `yes`) 47 | 48 | ```sh 49 | $ make ARCH=x86-64 VARIANTS=x86-64-v2,x86-64-v3 BUILD_TEST=no # example release build 50 | ``` 51 | 52 | The automated test program `edge264_test` can browse files in a given directory, decoding each `