"""
Author: Ismael Seidel (ismael.seidel@ufsc.br)
Affiliation: Embedded Computing Lab (ECL), Federal University of Santa Catarina (UFSC)
Description:
This module contains the implementation of PPM->YUV conversion. It is a wrapper class for calling FFMPEG.
FFMPEG will perform the conversion considering the aspects of the LF, such as width, height, number of views, encoding order.
Also, more importantly, it will deal with the colour conversion.
"""
import os
import subprocess
from pathlib import Path
from typing import TYPE_CHECKING, Union
from lfc_toolkit.src.data_handlers.encoding_orders import (
ScanFunctionType, get_serpentine_scan_list)
from lfc_toolkit.src.data_handlers.formatters import \
get_view_name_with_leading_zeros
from lfc_toolkit.src.data_handlers.lightfield import \
RAW_BT709_FR_YUV444p10le_LightField_Data
if TYPE_CHECKING:
from lfc_toolkit.src.data_handlers.lightfield import RAWLightFieldData
FFMPEG_COMMAND_TEMPLATE = """
ffmpeg
-y
-r 30
-f concat
-safe 0
-i {list_filename}
-s {view_width}x{view_height}
-framerate 30
-c:v rawvideo
-vf scale=out_color_matrix=bt709:out_range=full,format={pix_fmt}
-colorspace bt709
-color_primaries bt709
{output_filename}
"""
[docs]
def generate_list_for_ffmpeg(
n_views_width: int,
n_views_height: int,
initial_width: int = 0,
initial_height: int = 0,
step_width: int = 1,
step_height: int = 1,
views_path: Union[str, Path] = ".",
scan_order: ScanFunctionType = get_serpentine_scan_list,
) -> str:
"""
Generate a list of views for FFMPEG conversion.
:param n_views_width: Number of views in width
:type n_views_width: int
:param n_views_height: Number of views in height
:type n_views_height: int
:param initial_width: Initial width offset
:type initial_width: int
:param initial_height: Initial height offset
:type initial_height: int
:param step_width: Step size in width
:type step_width: int
:param step_height: Step size in height
:type step_height: int
:param views_path: Path to the views
:type views_path: Union[str, Path]
:param scan_order: Function defining the scan order
:type scan_order: ScanFunctionType
:return: List string for FFMPEG
:rtype: str
"""
scan_list = scan_order(
n_views_width * step_width,
n_views_height * step_height,
initial_width,
initial_height,
step_width,
step_height,
)
list_string = ""
for j, i in scan_list:
view_name = get_view_name_with_leading_zeros(j, i)
list_string += f"file '{views_path}/{view_name}.ppm'\nduration 1\n"
return list_string
[docs]
def create_list_file_for_ffmpeg(
list_filename: Union[str, Path],
n_views_width: int,
n_views_height: int,
initial_width: int = 0,
initial_height: int = 0,
step_width: int = 1,
step_height: int = 1,
views_path: Union[str, Path] = ".",
scan_order: ScanFunctionType = get_serpentine_scan_list,
) -> None:
"""
Create a list file for FFMPEG conversion.
:param list_filename: Filename for the list file
:type list_filename: Union[str, Path]
:param n_views_width: Number of views in width
:type n_views_width: int
:param n_views_height: Number of views in height
:type n_views_height: int
:param initial_width: Initial width offset
:type initial_width: int
:param initial_height: Initial height offset
:type initial_height: int
:param step_width: Step size in width
:type step_width: int
:param step_height: Step size in height
:type step_height: int
:param views_path: Path to the views
:type views_path: Union[str, Path]
:param scan_order: Function defining the scan order
:type scan_order: ScanFunctionType
:return: None
:rtype: None
"""
list_string = generate_list_for_ffmpeg(
n_views_width,
n_views_height,
initial_width,
initial_height,
step_width,
step_height,
views_path,
scan_order,
)
Path(list_filename).write_text(list_string)
with open(list_filename, "w") as text_file:
text_file.write(list_string)