diff --git a/fluster/decoder.py b/fluster/decoder.py index a8785c3c..4eb27c5e 100644 --- a/fluster/decoder.py +++ b/fluster/decoder.py @@ -18,7 +18,7 @@ from abc import ABC, abstractmethod from functools import lru_cache from shutil import which -from typing import List, Optional, Type +from typing import Any, Dict, List, Optional, Type from fluster.codec import Codec, OutputFormat from fluster.utils import normalize_binary_cmd @@ -47,6 +47,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" raise Exception("Not implemented") diff --git a/fluster/decoders/av1_aom.py b/fluster/decoders/av1_aom.py index a867904a..480b714a 100644 --- a/fluster/decoders/av1_aom.py +++ b/fluster/decoders/av1_aom.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -38,6 +39,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" fmt = "--rawvideo" diff --git a/fluster/decoders/av1_dav1d.py b/fluster/decoders/av1_dav1d.py index 526cc5e5..e70f50dd 100644 --- a/fluster/decoders/av1_dav1d.py +++ b/fluster/decoders/av1_dav1d.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -37,6 +38,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" fmt = "yuv" diff --git a/fluster/decoders/chromium.py b/fluster/decoders/chromium.py index 04ff48e8..d5f05ad0 100644 --- a/fluster/decoders/chromium.py +++ b/fluster/decoders/chromium.py @@ -16,6 +16,7 @@ # License along with this library. If not, see . from functools import lru_cache +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -50,6 +51,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: return str(main(input_filepath)) diff --git a/fluster/decoders/cros_codecs.py b/fluster/decoders/cros_codecs.py index 718e5437..6f96779d 100644 --- a/fluster/decoders/cros_codecs.py +++ b/fluster/decoders/cros_codecs.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -38,6 +39,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" diff --git a/fluster/decoders/dummy.py b/fluster/decoders/dummy.py index 0fb8eb57..9659e1eb 100644 --- a/fluster/decoders/dummy.py +++ b/fluster/decoders/dummy.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -36,5 +37,6 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: return file_checksum(input_filepath) diff --git a/fluster/decoders/ffmpeg.py b/fluster/decoders/ffmpeg.py index 1e6f9c28..f6724bdf 100644 --- a/fluster/decoders/ffmpeg.py +++ b/fluster/decoders/ffmpeg.py @@ -19,7 +19,7 @@ import re import subprocess from functools import lru_cache -from typing import Dict, Optional, Tuple +from typing import Any, Dict, Optional, Tuple from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -70,6 +70,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" command = [self.binary, "-hide_banner", "-nostdin"] @@ -99,6 +100,11 @@ def decode( elif self.ffmpeg_codec: command.extend(["-codec", self.ffmpeg_codec]) + # Optional decoder parameters + if optional_params: + for key, value in optional_params.items(): + command.extend([key, str(value)]) + # Input file command.extend(["-i", input_filepath]) diff --git a/fluster/decoders/gstreamer.py b/fluster/decoders/gstreamer.py index 7a61f91f..793ad19f 100644 --- a/fluster/decoders/gstreamer.py +++ b/fluster/decoders/gstreamer.py @@ -21,7 +21,7 @@ import shlex import subprocess from functools import lru_cache -from typing import List, Optional +from typing import Any, Dict, List, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -109,14 +109,21 @@ def gen_pipeline( input_filepath: str, output_filepath: Optional[str], output_format: OutputFormat, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Generate the GStreamer pipeline used to decode the test vector""" output = f"location={output_filepath}" if output_filepath else "" + + decoder_params = "" + if optional_params: + for key, value in optional_params.items(): + decoder_params += f" {key}={value} " + return PIPELINE_TPL.format( self.cmd, input_filepath, self.parser if self.parser else "parsebin", - self.decoder_bin, + self.decoder_bin + decoder_params, self.caps, self.sink, output, @@ -149,6 +156,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decode the test vector and do the checksum""" # When using videocodectestsink we can avoid writing files to disk @@ -162,7 +170,7 @@ def decode( data = run_command_with_output(command, timeout=timeout, verbose=verbose).splitlines() return self.parse_videocodectestsink_md5sum(data) - pipeline = self.gen_pipeline(input_filepath, output_filepath, output_format) + pipeline = self.gen_pipeline(input_filepath, output_filepath, output_format, optional_params) run_command(shlex.split(pipeline), timeout=timeout, verbose=verbose) return file_checksum(output_filepath) @@ -193,6 +201,7 @@ def gen_pipeline( input_filepath: str, output_filepath: Optional[str], output_format: OutputFormat, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: raw_caps = "video/x-raw" try: @@ -785,6 +794,7 @@ def gen_pipeline( input_filepath: str, output_filepath: Optional[str], output_format: OutputFormat, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: caps = f"{self.caps} ! videoconvert dither=none ! video/x-raw,format={output_format_to_gst(output_format)}" output = f"location={output_filepath}" if output_filepath else "" diff --git a/fluster/decoders/h264_jct_vt.py b/fluster/decoders/h264_jct_vt.py index c2720f2e..1f35a398 100644 --- a/fluster/decoders/h264_jct_vt.py +++ b/fluster/decoders/h264_jct_vt.py @@ -15,6 +15,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -38,6 +39,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" run_command( diff --git a/fluster/decoders/h265_jct_vt.py b/fluster/decoders/h265_jct_vt.py index 4e9b1702..c70909d9 100644 --- a/fluster/decoders/h265_jct_vt.py +++ b/fluster/decoders/h265_jct_vt.py @@ -15,6 +15,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -38,6 +39,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" run_command( diff --git a/fluster/decoders/h266_vvc_vtm.py b/fluster/decoders/h266_vvc_vtm.py index c7d183e1..9865792f 100644 --- a/fluster/decoders/h266_vvc_vtm.py +++ b/fluster/decoders/h266_vvc_vtm.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -37,6 +38,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" # pylint: disable=unused-argument diff --git a/fluster/decoders/h266_vvdec.py b/fluster/decoders/h266_vvdec.py index cd53c90e..64e86aba 100644 --- a/fluster/decoders/h266_vvdec.py +++ b/fluster/decoders/h266_vvdec.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -37,6 +38,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" run_command( diff --git a/fluster/decoders/iso_mpeg2_aac.py b/fluster/decoders/iso_mpeg2_aac.py index 0c2ee5ee..61da3aa5 100644 --- a/fluster/decoders/iso_mpeg2_aac.py +++ b/fluster/decoders/iso_mpeg2_aac.py @@ -16,6 +16,7 @@ # License along with this library. If not, see . import glob import os +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -40,6 +41,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" # Addition of .pcm as extension is a must. If it is something else, e.g. ".out" the decoder will output a diff --git a/fluster/decoders/iso_mpeg2_video.py b/fluster/decoders/iso_mpeg2_video.py index c0001644..4c2a2aaf 100644 --- a/fluster/decoders/iso_mpeg2_video.py +++ b/fluster/decoders/iso_mpeg2_video.py @@ -17,6 +17,7 @@ import glob import os import tempfile +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -41,6 +42,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" with tempfile.TemporaryDirectory() as temp_dir: diff --git a/fluster/decoders/iso_mpeg4_aac.py b/fluster/decoders/iso_mpeg4_aac.py index c402a837..dd39e115 100644 --- a/fluster/decoders/iso_mpeg4_aac.py +++ b/fluster/decoders/iso_mpeg4_aac.py @@ -16,6 +16,7 @@ # License along with this library. If not, see . import glob +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -40,6 +41,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" # Addition of .pcm as extension is a must. If it is something else, e.g. ".out" the decoder will output a diff --git a/fluster/decoders/iso_mpeg4_aac_er.py b/fluster/decoders/iso_mpeg4_aac_er.py index 280bbdda..b7c948a8 100644 --- a/fluster/decoders/iso_mpeg4_aac_er.py +++ b/fluster/decoders/iso_mpeg4_aac_er.py @@ -16,6 +16,7 @@ # License along with this library. If not, see . import glob +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -40,6 +41,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" output_filepath += ".raw" diff --git a/fluster/decoders/iso_mpeg4_video.py b/fluster/decoders/iso_mpeg4_video.py index a91b7e96..fdeee0d6 100644 --- a/fluster/decoders/iso_mpeg4_video.py +++ b/fluster/decoders/iso_mpeg4_video.py @@ -16,7 +16,7 @@ # License along with this library. If not, see . import os import subprocess -from typing import Tuple +from typing import Any, Dict, Optional, Tuple from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -41,6 +41,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath to output_filepath""" width, height = self._get_video_resolution(input_filepath, verbose) diff --git a/fluster/decoders/libvpx.py b/fluster/decoders/libvpx.py index 1a390455..eca6cccd 100644 --- a/fluster/decoders/libvpx.py +++ b/fluster/decoders/libvpx.py @@ -15,6 +15,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -42,6 +43,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" fmt = None diff --git a/fluster/decoders/vk_video_decoder.py b/fluster/decoders/vk_video_decoder.py index 0ead4ee7..e700ce98 100644 --- a/fluster/decoders/vk_video_decoder.py +++ b/fluster/decoders/vk_video_decoder.py @@ -14,6 +14,7 @@ # # You should have received a copy of the GNU Lesser General Public # License along with this library. If not, see . +from typing import Any, Dict, Optional from fluster.codec import Codec, OutputFormat from fluster.decoder import Decoder, register_decoder @@ -38,6 +39,7 @@ def decode( timeout: int, verbose: bool, keep_files: bool, + optional_params: Optional[Dict[str, Any]] = None, ) -> str: """Decodes input_filepath in output_filepath""" codec_mapping = { diff --git a/fluster/test.py b/fluster/test.py index b068fefc..aa3c39eb 100644 --- a/fluster/test.py +++ b/fluster/test.py @@ -86,6 +86,7 @@ def _execute_decode(self) -> str: self.timeout, self.verbose, keep_files_for_decode, + self.test_vector.optional_params, ) def _cleanup_if_needed(self) -> None: diff --git a/fluster/test_vector.py b/fluster/test_vector.py index d4436cd9..676bd92d 100644 --- a/fluster/test_vector.py +++ b/fluster/test_vector.py @@ -44,6 +44,7 @@ def __init__( output_format: OutputFormat, result: str, profile: Optional[Profile] = None, + optional_params: Optional[Dict[str, Any]] = None, ): # JSON members self.name = name @@ -51,6 +52,7 @@ def __init__( self.source_checksum = source_checksum self.input_file = input_file self.profile = profile + self.optional_params = optional_params self.output_format = output_format self.result = result @@ -84,6 +86,11 @@ def data_to_serialize(self) -> Dict[str, object]: data["profile"] = str(self.profile.value) else: data.pop("profile") + if self.optional_params is not None: + data["optional_params"] = self.optional_params + else: + data.pop("optional_params") + return data def __str__(self) -> str: @@ -92,6 +99,7 @@ def __str__(self) -> str: f" Source: {self.source}\n" f" Input: {self.input_file}\n" f" Profile: {self.profile}\n" + f" Options: {self.optional_params}\n" f" Result: {self.result}" ) return ret