Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ subprojects/jm/
subprojects/libtsp-v7r0
subprojects/mpeg2aac
subprojects/mpeg2video
subprojects/mpeg4video
subprojects/vvcsoftware_vtm/
subprojects/vvdec/

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ For complete setup, usage examples, hardware acceleration configuration, and tro
- `./fluster.py download` downloads all available test suites

2. (Optional) Build the reference decoders for AAC, H.264/AVC, H.265/HEVC,
H.266/VVC. First, download the ISO reference software:
H.266/VVC, MPEG-4 Visual. First, download the ISO reference software:

```bash
python3 build/download_deps.py
Expand Down
56 changes: 56 additions & 0 deletions build/compat/mpeg4video/compat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Fluster - testing framework for decoders conformance
* Copyright (C) 2026, Fluendo, S.A.
*
* Force-included (-include) when building the MPEG-4 Visual reference software (vm_dec):
* its pre-standard C++ uses iostream names without the std:: prefix.
*/

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <strstream>

class CVideoObjectDecoder;
class CVideoObjectDecoderTPS;
class CEnhcBufferEncoder;

using std::cerr;
using std::cin;
using std::cout;
using std::dec;
using std::endl;
using std::ends;
using std::fixed;
using std::flush;
using std::fstream;
using std::hex;
using std::ifstream;
using std::ios;
using std::iostream;
using std::istream;
using std::istrstream;
using std::left;
using std::ofstream;
using std::oct;
using std::ostream;
using std::ostrstream;
using std::right;
using std::scientific;
using std::setfill;
using std::setprecision;
using std::setw;
using std::streambuf;
using std::streamoff;
using std::streampos;
using std::strstream;
using std::strstreambuf;
using std::ws;
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/fstream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <fstream.h> used by the MPEG-4 Visual reference software */
#include <fstream>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/iomanip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <iomanip.h> used by the MPEG-4 Visual reference software */
#include <iomanip>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/ios.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <ios.h> used by the MPEG-4 Visual reference software */
#include <ios>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/iostream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <iostream.h> used by the MPEG-4 Visual reference software */
#include <iostream>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/istream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <istream.h> used by the MPEG-4 Visual reference software */
#include <istream>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/ostream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <ostream.h> used by the MPEG-4 Visual reference software */
#include <ostream>
2 changes: 2 additions & 0 deletions build/compat/mpeg4video/strstream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* Fluster: replacement for the pre-standard <strstream.h> used by the MPEG-4 Visual reference software */
#include <strstream>
82 changes: 80 additions & 2 deletions build/download_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Copyright (C) 2025, Fluendo, S.A.
#
# Helper script to download all ISO reference decoder dependencies
# Downloads: MPEG-2 AAC, MPEG-2 video, MPEG-4 AAC, and libtsp
# Downloads: MPEG-2 AAC, MPEG-2 video, MPEG-4 AAC, MPEG-H, MPEG-4 Visual, and libtsp

import argparse
import hashlib
Expand Down Expand Up @@ -172,6 +172,77 @@ def download_mpegh(contrib_dir):
spatial_decoder.write_text(re.sub(r"^[ \t]*#pragma (end)?region.*\n", "", source, flags=re.M), encoding="utf-8")


# Forward declarations that would clash with the std:: names brought in by the compat header
MPEG4_VIDEO_FORWARD_DECLARATION = re.compile(
rb"^[ \t]*class[ \t]+(istream|ostream|ifstream|strstreambuf)[ \t]*;[ \t]*\r?\n", re.M
)
# "ios::bin" is the pre-standard spelling of "ios::binary"
MPEG4_VIDEO_IOS_BIN = re.compile(rb"\bios::bin\b")


def adapt_mpeg4_video_sources(source_dir):
"""Adapt the MPEG-4 Visual reference software, which predates C++98, to build with current compilers"""
for path in source_dir.rglob("*"):
if not path.is_file() or path.suffix not in (".c", ".cpp", ".h", ".hpp"):
continue
original = path.read_bytes()
adapted = MPEG4_VIDEO_IOS_BIN.sub(b"ios::binary", MPEG4_VIDEO_FORWARD_DECLARATION.sub(b"", original))
if adapted != original:
path.write_bytes(adapted)


def download_mpeg4_video(contrib_dir):
"""Download the MPEG-4 Visual (ISO/IEC 14496-5) reference software, which builds vm_dec"""
print()
print("=== Downloading MPEG-4 Visual reference software ===")

mpeg4_video_dir = contrib_dir / "MPEG-4_video_refSoft"
mpeg4_video_zip = contrib_dir / "mpeg4_video_refsoft.zip"
mpeg4_video_url = (
"https://standards.iso.org/ittf/PubliclyAvailableStandards/"
"c039392_ISO_IEC_14496-5_2001_Amd%205_2004(E)_Reference_Software.zip"
)
# The zip holds several implementations, only this one produces vm_dec
implementation = "microsoft-v2.5-040207-NTU/"

if mpeg4_video_dir.exists():
Comment thread
ylatuya marked this conversation as resolved.
Resolved
print(f"Skipping download of MPEG-4 Visual: {mpeg4_video_dir} already exists")
# Re-apply the source rewrites, in case the tree was extracted before they were added
adapt_mpeg4_video_sources(mpeg4_video_dir)
return

# Get cookies first, then download with cookies and form data
cookie_jar = CookieJar()
build_opener(HTTPCookieProcessor(cookie_jar)).open(mpeg4_video_url)
download_with_cookies(mpeg4_video_url, mpeg4_video_zip, cookie_jar)
if not zipfile.is_zipfile(mpeg4_video_zip):
print(f"Error: {mpeg4_video_zip.name} is not a zip file, the download was probably refused")
sys.exit(1)

print(f"Extracting {implementation} from {mpeg4_video_zip.name}...")
# Extract into a temporary directory renamed once complete, so that an interrupted run
# never leaves a partial MPEG-4_video_refSoft behind
tmp_dir = contrib_dir / f".{mpeg4_video_dir.name}.tmp"
shutil.rmtree(tmp_dir, ignore_errors=True)
with zipfile.ZipFile(mpeg4_video_zip) as zip_ref:
for member in zip_ref.infolist():
_, found, relative_path = member.filename.partition(implementation)
if not found or not relative_path or ".." in Path(relative_path).parts:
continue
target = tmp_dir / relative_path
if member.is_dir():
target.mkdir(parents=True, exist_ok=True)
else:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(zip_ref.read(member))
mpeg4_video_zip.unlink()
if not tmp_dir.exists():
print(f"Error: {implementation} not found in the downloaded MPEG-4 Visual reference software")
sys.exit(1)
adapt_mpeg4_video_sources(tmp_dir)
tmp_dir.rename(mpeg4_video_dir)


def download_libtsp(contrib_dir):
"""Download libtsp audio library"""
print()
Expand Down Expand Up @@ -269,7 +340,8 @@ def prompt_iso_license(auto_accept=False):

def main():
parser = argparse.ArgumentParser(
description="Download ISO reference decoder dependencies (MPEG-2 AAC, MPEG-2 video, MPEG-4 AAC, MPEG-H, libtsp)"
description="Download ISO reference decoder dependencies "
"(MPEG-2 AAC, MPEG-2 video, MPEG-4 AAC, MPEG-H, MPEG-4 Visual, libtsp)"
)
parser.add_argument(
"dest_dir",
Expand Down Expand Up @@ -300,6 +372,7 @@ def main():
print(" - MPEG-2 video decoder")
print(" - MPEG-4 AAC decoders")
print(" - MPEG-H 3D Audio decoder")
print(" - MPEG-4 Visual decoder")
print(" - libtsp audio library")
print()

Expand All @@ -314,6 +387,7 @@ def main():
download_mpeg2(contrib_dir)
download_mpeg4(contrib_dir)
download_mpegh(contrib_dir)
download_mpeg4_video(contrib_dir)
download_libtsp(contrib_dir)

# Copy meson.build files to contrib directories
Expand All @@ -335,13 +409,17 @@ def main():
print("Copying meson.build for libtsp")
shutil.copy2(packagefiles_dir / "libtsp" / "meson.build", contrib_dir / "libtsp-v7r0" / "meson.build")

print("Copying meson.build for MPEG-4 Visual")
shutil.copy2(packagefiles_dir / "mpeg4video" / "meson.build", contrib_dir / "MPEG-4_video_refSoft" / "meson.build")

# Create symlinks for meson subprojects
print()
print("=== Creating symlinks for meson subprojects ===")

symlinks = [
("mpeg2video", "../contrib/video"),
("mpeg2aac", "../contrib/mpeg2aac"),
("mpeg4video", "../contrib/MPEG-4_video_refSoft"),
("libtsp-v7r0", "../contrib/libtsp-v7r0"),
]

Expand Down
36 changes: 36 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ build_mpeg4_aac = get_option('mpeg4_aac_decoder')
build_mpeg4_aac_er = get_option('mpeg4_aac_er_decoder')
build_mpeg2_video = get_option('mpeg2_video_decoder')
build_mpegh = get_option('mpegh_decoder')
build_mpeg4_video = get_option('mpeg4_video_decoder')

missing_deps = []

Expand Down Expand Up @@ -73,6 +74,13 @@ if build_mpegh
endif
endif

# Check MPEG-4 Visual dependency
if build_mpeg4_video
if not fs.is_dir(contrib_dir / 'MPEG-4_video_refSoft')
missing_deps += ['contrib/MPEG-4_video_refSoft (MPEG-4 Visual decoder)']
endif
endif

# Check libtsp dependency (needed for all AAC decoders)
if build_mpeg2_aac or build_mpeg4_aac or build_mpeg4_aac_er
if not fs.is_dir(contrib_dir / 'libtsp-v7r0')
Expand Down Expand Up @@ -242,6 +250,23 @@ if build_mpeg2_aac
endif
endif

# MPEG-4 Visual Reference Decoder (ISO/IEC 14496-5)
mpeg4video_tgt = disabler()
if build_mpeg4_video
# Check if the mpeg4video subproject directory exists (symlinked from contrib/MPEG-4_video_refSoft)
mpeg4video_dir = meson.current_source_dir() / 'subprojects' / 'mpeg4video'
if fs.is_dir(mpeg4video_dir) or fs.is_symlink(mpeg4video_dir)
mpeg4video_subproject = subproject('mpeg4video', required: false)
if mpeg4video_subproject.found()
mpeg4video_tgt = mpeg4video_subproject.get_variable('vm_dec')
else
warning('MPEG-4 Visual decoder subproject configuration failed')
endif
else
error('MPEG-4 Visual decoder: subprojects/mpeg4video symlink not found. Run: python3 build/download_deps.py')
endif
endif

# Extract compiler flags from meson's C compiler configuration
# This ensures ISO decoders use the same architecture as the main build
c_args_list = get_option('c_args')
Expand Down Expand Up @@ -382,6 +407,16 @@ if not is_disabler(aacdec_mc_tgt)
)
endif

# MPEG-4 Visual decoder symlink (vm_dec)
if not is_disabler(mpeg4video_tgt)
custom_target('link-vm_dec',
output: 'vm_dec.link',
input: mpeg4video_tgt,
command: ['sh', '-c', link_script, '_', meson.current_build_dir(), '@INPUT@', decoders_dir / 'vm_dec'],
build_by_default: true,
)
endif

run_target('clean-contrib',
command: ['rm', '-rf', contrib_dir],
)
Expand All @@ -408,6 +443,7 @@ summary({
'MPEG-2 video decoder': build_mpeg2_video,
'MPEG-2 AAC decoder': build_mpeg2_aac,
'MPEG-H 3D Audio decoder': build_mpegh,
'MPEG-4 Visual decoder': build_mpeg4_video,
Comment thread
ylatuya marked this conversation as resolved.
Resolved
'isobmff library': build_isobmff,
}, section: 'Meson Subproject Decoders')

Expand Down
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ option('mpeg4_aac_decoder', type: 'boolean', value: true,
description: 'Build MPEG-4 AAC reference decoder')
option('mpeg4_aac_er_decoder', type: 'boolean', value: true,
description: 'Build MPEG-4 AAC Error Resilient reference decoder')
option('mpeg4_video_decoder', type: 'boolean', value: true,
description: 'Build MPEG-4 Visual reference decoder (ISO/IEC 14496-5, vm_dec)')

# MPEG-H 3D Audio reference decoder (disabled by default, needs build/download_deps.py)
option('mpegh_decoder', type: 'boolean', value: false,
Expand Down
6 changes: 6 additions & 0 deletions subprojects/mpeg4video.wrap
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[wrap-file]
directory = mpeg4video
patch_directory = mpeg4video

[provide]
program_names = vm_dec
Loading
Loading