diff --git a/.gitignore b/.gitignore index e86b3318f..8d29cbc0d 100644 --- a/.gitignore +++ b/.gitignore @@ -95,6 +95,7 @@ /src/tools/bluray_dump /src/tools/checksum /src/tools/diracparser +/src/tools/dovic_dump /src/tools/dts_dump /src/tools/ebml_validator /src/tools/hevcc_dump diff --git a/Rakefile b/Rakefile index eb964f983..68a8b4bcb 100644 --- a/Rakefile +++ b/Rakefile @@ -85,7 +85,7 @@ def setup_globals $programs = %w{mkvmerge mkvinfo mkvextract mkvpropedit} $programs << "mkvtoolnix" if $build_mkvtoolnix $programs << "mkvtoolnix-gui" if $build_mkvtoolnix_gui - $tools = %w{ac3parser base64tool bluray_dump checksum diracparser dts_dump ebml_validator hevcc_dump pgs_dump vc1parser xyzvc_dump} + $tools = %w{ac3parser base64tool bluray_dump checksum diracparser dovic_dump dts_dump ebml_validator hevcc_dump pgs_dump vc1parser xyzvc_dump} $application_subdirs = { "mkvtoolnix-gui" => "mkvtoolnix-gui/", "mkvtoolnix" => "mkvtoolnix/" } $applications = $programs.map { |name| "src/#{$application_subdirs[name]}#{name}" + c(:EXEEXT) } diff --git a/src/common/dovi_meta.cpp b/src/common/dovi_meta.cpp index d9ff80476..e3941ddd9 100644 --- a/src/common/dovi_meta.cpp +++ b/src/common/dovi_meta.cpp @@ -352,4 +352,22 @@ create_dovi_block_addition_mapping(dovi_decoder_configuration_record_t const &do return mapping; } +dovi_decoder_configuration_record_t +parse_dovi_decoder_configuration_record(mtx::bits::reader_c &r) { + dovi_decoder_configuration_record_t dovi_conf{}; + + dovi_conf.dv_version_major = r.get_bits(8); + dovi_conf.dv_version_minor = r.get_bits(8); + dovi_conf.dv_profile = r.get_bits(7); + dovi_conf.dv_level = r.get_bits(6); + dovi_conf.rpu_present_flag = r.get_bit(); + dovi_conf.el_present_flag = r.get_bit(); + dovi_conf.bl_present_flag = r.get_bit(); + dovi_conf.dv_bl_signal_compatibility_id = r.get_bits(4); + + r.skip_bits(28 + 32 + 32 + 32 + 32); // reserved + + return dovi_conf; +} + } // namespace mtx::dovi diff --git a/src/common/dovi_meta.h b/src/common/dovi_meta.h index e59986122..366d8d04c 100644 --- a/src/common/dovi_meta.h +++ b/src/common/dovi_meta.h @@ -83,6 +83,7 @@ uint8_t calculate_dovi_level(unsigned int width, unsigned int height, uint64_t d dovi_decoder_configuration_record_t create_dovi_configuration_record(dovi_rpu_data_header_t const &hdr, unsigned int width, unsigned int height, mtx::hevc::vui_info_t const &vui, uint64_t duration); dovi_decoder_configuration_record_t create_av1_dovi_configuration_record(dovi_rpu_data_header_t const &hdr, unsigned int width, unsigned int height, mtx::av1::color_config_t const &color_config, uint64_t duration); +dovi_decoder_configuration_record_t parse_dovi_decoder_configuration_record(mtx::bits::reader_c &r); block_addition_mapping_t create_dovi_block_addition_mapping(dovi_decoder_configuration_record_t const &dovi_conf); diff --git a/src/tools/dovic_dump.cpp b/src/tools/dovic_dump.cpp new file mode 100644 index 000000000..772c9d60d --- /dev/null +++ b/src/tools/dovic_dump.cpp @@ -0,0 +1,108 @@ +/* + dovic_dump - A tool for dumping the HEVCC element from the middle of a file + + Distributed under the GPL v2 + see the file COPYING for details + or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html + + Written by Moritz Bunkus . +*/ + +#include "common/common_pch.h" + +#include "common/bit_reader.h" +#include "common/command_line.h" +#include "common/dovi_meta.h" +#include "common/mm_io_x.h" +#include "common/mm_file_io.h" +#include "common/strings/parsing.h" + +static void +setup() { + mtx::cli::g_usage_text = + "dovic_dump [options] input_file_name position_in_file size\n" + "\n" + "General options:\n" + "\n" + " -h, --help This help text\n" + " -V, --version Print version information\n"; +} + +static std::tuple +parse_args(std::vector &args) { + std::string file_name; + int64_t file_pos = 0; + uint64_t size = 0; + + for (auto const &arg: args) { + if (file_name.empty()) + file_name = arg; + + else if (size != 0) + mxerror("Superfluous arguments given.\n"); + + else if (!file_pos) { + if (!mtx::string::parse_number(arg, file_pos)) + mxerror("The file position is not a valid number.\n"); + + } else if (!size) { + if (!mtx::string::parse_number(arg, size)) + mxerror("The size is not a valid number.\n"); + } + } + + if (file_name.empty()) + mxerror("No file name given\n"); + + if (!file_pos) + mxerror("No file position given\n"); + + if (!size) + mxerror("No size given\n"); + + if (file_pos < 0) + file_pos = file_pos * -1 - size; + + return std::make_tuple(file_name, static_cast(file_pos), size); +} + +static void +read_and_parse_dovic(std::string const &file_name, + uint64_t file_pos, + uint64_t size) { + mm_file_io_c in{file_name}; + + in.setFilePointer(file_pos); + auto data = in.read(size); + auto r = mtx::bits::reader_c{data->get_buffer(), data->get_size()}; + + try { + auto dovi_cfg = mtx::dovi::parse_dovi_decoder_configuration_record(r); + dovi_cfg.dump(); + + } catch (...) { + mxerror("Parsing the DOVI decoder configuration record failed\n"); + } +} + +int +main(int argc, + char **argv) { + mtx_common_init("dovic_dump", argv[0]); + + setup(); + + auto args = mtx::cli::args_in_utf8(argc, argv); + while (mtx::cli::handle_common_args(args, "-r")) + ; + + auto file_spec = parse_args(args); + + try { + read_and_parse_dovic(std::get<0>(file_spec), std::get<1>(file_spec), std::get<2>(file_spec)); + } catch (mtx::mm_io::open_x &) { + mxerror("File not found\n"); + } + + mxexit(); +}