A generic command-line wrapper for various video codecs. This class provides a unified interface for different codecs (e.g., vvenc, VTM, HM, ffmpeg) by automatically generating the correct command-line arguments based on the input configuration dictionary.
| 43 | |
| 44 | |
| 45 | class VideoCodec: |
| 46 | """ |
| 47 | A generic command-line wrapper for various video codecs. |
| 48 | |
| 49 | This class provides a unified interface for different codecs (e.g., vvenc, |
| 50 | VTM, HM, ffmpeg) by automatically generating the correct command-line |
| 51 | arguments based on the input configuration dictionary. |
| 52 | """ |
| 53 | |
| 54 | def __init__(self, |
| 55 | video_codec_type: Literal['vvenc', 'vtm', 'hm', 'ffmpeg'], |
| 56 | encoder_path: str = None, |
| 57 | decoder_path: str = None): |
| 58 | """ |
| 59 | Initializes the video codec wrapper. |
| 60 | |
| 61 | Args: |
| 62 | video_codec_type: The type of video codec to use. |
| 63 | encoder_path (optional): Path to the encoder executable. |
| 64 | decoder_path (optional): Path to the decoder executable. |
| 65 | """ |
| 66 | self.video_codec_type = video_codec_type.lower() |
| 67 | if self.video_codec_type not in VIDEO_CODEC_PATHS: |
| 68 | raise ValueError(f"Unsupported video codec type: {self.video_codec_type}. " |
| 69 | f"Supported types: {', '.join(VIDEO_CODEC_PATHS.keys())}") |
| 70 | |
| 71 | codec_paths = VIDEO_CODEC_PATHS[self.video_codec_type] |
| 72 | self.encoder_path = Path(encoder_path or codec_paths['encoder']) |
| 73 | self.decoder_path = Path(decoder_path or codec_paths['decoder']) |
| 74 | self.intra_lossy_config_path = codec_paths.get('intra_lossy_config_path') |
| 75 | self.inter_lossy_config_path = codec_paths.get('inter_lossy_config_path') |
| 76 | self.intra_lossless_config_path = codec_paths.get('intra_lossless_config_path') |
| 77 | self.inter_lossless_config_path = codec_paths.get('inter_lossless_config_path') |
| 78 | |
| 79 | self._check_executables() |
| 80 | |
| 81 | def _check_executables(self): |
| 82 | """Ensures encoder and decoder executables exist and are accessible.""" |
| 83 | if self.video_codec_type == 'ffmpeg': |
| 84 | # FFmpeg is assumed to be in the system PATH. |
| 85 | return |
| 86 | |
| 87 | if not self.encoder_path.is_file(): |
| 88 | raise FileNotFoundError(f"Encoder not found: {self.encoder_path}") |
| 89 | if not self.decoder_path.is_file(): |
| 90 | raise FileNotFoundError(f"Decoder not found: {self.decoder_path}") |
| 91 | |
| 92 | # This check is more useful on Linux/macOS. |
| 93 | # On Windows, os.access(..., os.X_OK) may return True if the file exists. |
| 94 | if not os.access(self.encoder_path, os.X_OK): |
| 95 | logging.warning(f"Encoder may not be executable: {self.encoder_path}") |
| 96 | if not os.access(self.decoder_path, os.X_OK): |
| 97 | logging.warning(f"Decoder may not be executable: {self.decoder_path}") |
| 98 | |
| 99 | def _run_command(self, cmd: List[str], process_name: str): |
| 100 | """ |
| 101 | Executes a subprocess command and handles logging and errors. |
| 102 |
no outgoing calls
no test coverage detected