Source code for cutcutcodec.core.analysis.video.properties.pix_fmt

#!/usr/bin/env python3

"""Find pixel format of a video stream."""

import collections
import pathlib
import typing

import cv2  # pip install opencv-contrib-python-headless

from cutcutcodec.core.analysis._helper_properties import _check_pathexists_index, _mix_and_check
from cutcutcodec.core.analysis.ffprobe import _estimate_pix_fmt_ffmpeg, _map_index_rel_to_abs
from cutcutcodec.core.exceptions import MissingStreamError, MissingInformation


def _estimate_pix_fmt_cv2(filename: str, index: int) -> tuple[int, int]:
    """Retrieve via cv2, the metadata concerning the pixel format.

    This function is fast because it reads only the header of the file.

    Examples
    --------
    >>> from cutcutcodec.core.analysis.video.properties.pix_fmt import _estimate_pix_fmt_cv2
    >>> from cutcutcodec.utils import get_project_root
    >>> media = str(get_project_root() / "media" / "video" / "intro.webm")
    >>> _estimate_pix_fmt_cv2(media, 0)
    'yuv420'
    >>>
    """
    cap = cv2.VideoCapture(filename, index)
    if not cap.isOpened():
        raise MissingStreamError(f"impossible to open '{filename}' stream {index} with 'cv2'")
    if (code := cap.get(cv2.CAP_PROP_CODEC_PIXEL_FORMAT)) == -1.0:
        raise MissingInformation(
            f"'cv2' did not find the pixel format of '{filename}' stream {index}"
        )
    PIXEL_FORMAT_MAP = {
        134230855.0: "gbrp",
        168440665.0: "yuv422p10le",
        168506201.0: "yuv420p10le",
        808596553.0: "yuv420",
    }
    if code not in PIXEL_FORMAT_MAP:
        raise MissingInformation(
            f"the 'cv2' pixel format code {code} is unknown '{filename}' stream {index}"
        )
    return PIXEL_FORMAT_MAP[code]


[docs] def get_pix_fmt( filename: pathlib.Path | str | bytes, index: int = 0, *, backend: typing.Optional[str] = None ) -> str: """Read in the metadata, the pixel format. Parameters ---------- filename : pathlike The pathlike of the file containing a video stream. index : int The relative index of the video stream being considered, by default the first stream encountered is selected. backend : str, optional - None (default) : Try to read the stream by trying differents backends. - 'ffmpeg' : Uses the modules ``pip install ffmpeg-python`` which are using the ``ffmpeg`` program in the background. - 'cv2' : Uses the module ``pip install opencv-contrib-python-headless``. Returns ------- pix_fmt : int The name of the pixel format. Raises ------ MissingStreamError If the file does not contain a playable video stream. MissingInformation If the information is unavailable. Examples -------- >>> from cutcutcodec.core.analysis.video.properties.pix_fmt import get_pix_fmt >>> from cutcutcodec.utils import get_project_root >>> media = get_project_root() / "media" / "video" / "intro.webm" >>> get_pix_fmt(media) 'yuv420p' >>> """ _check_pathexists_index(filename, index) return _mix_and_check( backend, False, (str(pathlib.Path(filename)), index), collections.OrderedDict([ ( ( lambda filename, index: _estimate_pix_fmt_ffmpeg( filename, _map_index_rel_to_abs(filename, index, "video") ) ), {"accurate": False, "backend": "ffmpeg"}, ), (_estimate_pix_fmt_cv2, {"accurate": False, "backend": "cv2"}), ]) )