diff --git a/src/common/id_info.cpp b/src/common/id_info.cpp new file mode 100644 index 000000000..ee0b95512 --- /dev/null +++ b/src/common/id_info.cpp @@ -0,0 +1,37 @@ +/* + mkvmerge -- utility for splicing together matroska files + from component media subtypes + + 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/id_info.h" +#include "common/strings/formatting.h" + +namespace mtx::id { + +info_c & +info_c::add(std::string const &key, + memory_cptr const &value) { + if (value && value->get_size()) + set(key, mtx::string::to_hex(value->get_buffer(), value->get_size(), true)); + + return *this; +} + +info_c & +info_c::add(std::string const &key, + memory_c const *value) { + if (value && value->get_size()) + set(key, mtx::string::to_hex(value->get_buffer(), value->get_size(), true)); + + return *this; +} + +} // namespace mtx::id diff --git a/src/common/id_info.h b/src/common/id_info.h index c7b35ec58..18c58210c 100644 --- a/src/common/id_info.h +++ b/src/common/id_info.h @@ -86,6 +86,29 @@ class info_c { protected: verbose_info_t m_info; +private: + template + bool + all(Args... args) { + return (... && args); + } + + template + std::string + join([[maybe_unused]] std::string const &separator, + T const &value) { + return fmt::to_string(value); + } + + template + std::string + join(std::string const &separator, + Tfirst const &first, + Trest... rest) { + return fmt::to_string(first) + separator + join(separator, rest...); + } + public: template info_c & set(std::string const &key, @@ -103,6 +126,9 @@ public: return *this; } + info_c &add(std::string const &key, memory_c const *value); + info_c &add(std::string const &key, memory_cptr const &value); + info_c & add(std::string const &key, char const *value, @@ -112,14 +138,26 @@ public: return *this; } + template info_c & add(std::string const &key, - std::optional const &value) { + std::optional const &value) { if (value.has_value()) set(key, *value); return *this; } + template + info_c & + add_joined(std::string const &key, + std::string const &separator, + Tvalues... values) { + if (!all(values...)) + return *this; + + return add(key, join(separator, values...)); + } + verbose_info_t const &get() const { return m_info; } diff --git a/src/input/r_avc.cpp b/src/input/r_avc.cpp index 88d5ee528..57b628de4 100644 --- a/src/input/r_avc.cpp +++ b/src/input/r_avc.cpp @@ -102,8 +102,8 @@ void avc_es_reader_c::identify() { auto info = mtx::id::info_c{}; info.add(mtx::id::packetizer, mtx::id::mpeg4_p10_es_video); - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_width, m_height)); info.add(mtx::id::default_duration, m_default_duration); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_width, m_height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec_c::type_e::V_MPEG4_P10, "MPEG-4 part 10 ES"), info.get()); diff --git a/src/input/r_avi.cpp b/src/input/r_avi.cpp index dc4c6c707..4eeb96484 100644 --- a/src/input/r_avi.cpp +++ b/src/input/r_avi.cpp @@ -866,7 +866,7 @@ avi_reader_c::extended_identify_mpeg4_l2(mtx::id::info_c &info) { disp_height = mtx::to_int_rounded(m_video_width / aspect_ratio); } - info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", disp_width, disp_height)); + info.add_joined(mtx::id::display_dimensions, "x"s, disp_width, disp_height); } } @@ -894,10 +894,8 @@ avi_reader_c::identify_video() { else if (codec.is(codec_c::type_e::V_MPEG4_P10)) info.add(mtx::id::packetizer, mtx::id::mpeg4_p10_es_video); - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_video_width, m_video_height)); - - if (m_video_display_width) - info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", m_video_display_width, m_video_display_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_video_width, m_video_height); + info.add_joined(mtx::id::display_dimensions, "x"s, m_video_display_width, m_video_display_height); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec.get_name(fourcc_str), info.get()); } diff --git a/src/input/r_dirac.cpp b/src/input/r_dirac.cpp index 98f8e4c8b..074e9ea9c 100644 --- a/src/input/r_dirac.cpp +++ b/src/input/r_dirac.cpp @@ -96,7 +96,7 @@ dirac_es_reader_c::read(generic_packetizer_c *, void dirac_es_reader_c::identify() { auto info = mtx::id::info_c{}; - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_seqhdr.pixel_width, m_seqhdr.pixel_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_seqhdr.pixel_width, m_seqhdr.pixel_height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec_c::type_e::V_DIRAC, "Dirac"), info.get()); diff --git a/src/input/r_flv.cpp b/src/input/r_flv.cpp index 774569f03..048c7f456 100644 --- a/src/input/r_flv.cpp +++ b/src/input/r_flv.cpp @@ -308,7 +308,7 @@ flv_reader_c::identify() { info.add(mtx::id::packetizer, mtx::id::mpeg4_p10_video); if (track->is_video()) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->m_v_width, track->m_v_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, track->m_v_width, track->m_v_height); else if (track->is_audio()) { info.add(mtx::id::audio_channels, track->m_a_channels); diff --git a/src/input/r_hevc.cpp b/src/input/r_hevc.cpp index 09dd6e118..eea8b3524 100644 --- a/src/input/r_hevc.cpp +++ b/src/input/r_hevc.cpp @@ -123,8 +123,8 @@ void hevc_es_reader_c::identify() { auto info = mtx::id::info_c{}; info.add(mtx::id::packetizer, mtx::id::mpegh_p2_es_video); - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_width, m_height)); info.add(mtx::id::default_duration, m_default_duration); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_width, m_height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec_c::type_e::V_MPEGH_P2, "HEVC"), info.get()); diff --git a/src/input/r_ivf.cpp b/src/input/r_ivf.cpp index 260e4b102..fe6e46f1f 100644 --- a/src/input/r_ivf.cpp +++ b/src/input/r_ivf.cpp @@ -132,6 +132,6 @@ ivf_reader_c::identify() { return; auto info = mtx::id::info_c{}; - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_width, m_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_width, m_height); id_result_track(0, ID_RESULT_TRACK_VIDEO, m_codec.get_name(), info.get()); } diff --git a/src/input/r_matroska.cpp b/src/input/r_matroska.cpp index b415358d9..a89f25680 100644 --- a/src/input/r_matroska.cpp +++ b/src/input/r_matroska.cpp @@ -2749,6 +2749,7 @@ kax_reader_c::identify() { info.add(mtx::id::uid, track->track_uid); info.add(mtx::id::codec_id, track->codec_id); info.set(mtx::id::codec_private_length, track->private_data ? track->private_data->get_size() : 0u); + info.add(mtx::id::codec_private_data, track->private_data); info.add(mtx::id::codec_delay, track->codec_delay.to_ns(0)); info.add(mtx::id::codec_name, track->codec_name); info.add(mtx::id::language, track->language.get_iso639_alpha_3_code()); @@ -2764,21 +2765,11 @@ kax_reader_c::identify() { info.add(mtx::id::flag_text_descriptions, track->text_descriptions_flag); info.add(mtx::id::flag_original, track->original_flag); info.add(mtx::id::flag_commentary, track->commentary_flag); + info.add(mtx::id::display_unit, track->v_dunit); - if (track->private_data && (0 != track->private_data->get_size())) - info.add(mtx::id::codec_private_data, mtx::string::to_hex(track->private_data->get_buffer(), track->private_data->get_size(), true)); - - if ((0 != track->v_width) && (0 != track->v_height)) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->v_width, track->v_height)); - - if ((0 != track->v_dwidth) && (0 != track->v_dheight)) - info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", track->v_dwidth, track->v_dheight)); - - if (track->v_dunit) - info.set(mtx::id::display_unit, *track->v_dunit); - - if ((0 != track->v_pcleft) || (0 != track->v_pctop) || (0 != track->v_pcright) || (0 != track->v_pcbottom)) - info.add(mtx::id::cropping, fmt::format("{0},{1},{2},{3}", track->v_pcleft, track->v_pctop, track->v_pcright, track->v_pcbottom)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, track->v_width, track->v_height); + info.add_joined(mtx::id::display_dimensions, "x"s, track->v_dwidth, track->v_dheight); + info.add_joined(mtx::id::cropping, ","s, track->v_pcleft, track->v_pctop, track->v_pcright, track->v_pcbottom); if (track->codec.is(codec_c::type_e::V_MPEG4_P10)) info.add(mtx::id::packetizer, track->ms_compat ? mtx::id::mpeg4_p10_es_video : mtx::id::mpeg4_p10_video); diff --git a/src/input/r_mpeg_es.cpp b/src/input/r_mpeg_es.cpp index 24f2852a5..6c23ccd47 100644 --- a/src/input/r_mpeg_es.cpp +++ b/src/input/r_mpeg_es.cpp @@ -217,7 +217,7 @@ void mpeg_es_reader_c::identify() { auto codec = fmt::format("mpg{0}", version); auto info = mtx::id::info_c{}; - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", width, height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, width, height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec, codec), info.get()); diff --git a/src/input/r_mpeg_ps.cpp b/src/input/r_mpeg_ps.cpp index bd038cb08..8b22d8dec 100644 --- a/src/input/r_mpeg_ps.cpp +++ b/src/input/r_mpeg_ps.cpp @@ -1406,9 +1406,7 @@ mpeg_ps_reader_c::identify() { info.set(mtx::id::number, (static_cast(track->id.sub_id) << 32) | static_cast(track->id.id)); info.add(mtx::id::stream_id, track->id.id); info.add(mtx::id::sub_stream_id, track->id.sub_id); - - if ((0 != track->v_dwidth) && (0 != track->v_dheight)) - info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", track->v_dwidth, track->v_dheight)); + info.add_joined(mtx::id::display_dimensions, "x"s, track->v_dwidth, track->v_dheight); if ('a' == track->type) { info.add(mtx::id::audio_channels, track->a_channels); @@ -1416,7 +1414,7 @@ mpeg_ps_reader_c::identify() { info.add(mtx::id::audio_bits_per_sample, track->a_bits_per_sample); } else if ('v' == track->type) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->v_width, track->v_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, track->v_width, track->v_height); id_result_track(i, 'a' == track->type ? ID_RESULT_TRACK_AUDIO : ID_RESULT_TRACK_VIDEO, track->codec.get_name(), info.get()); } diff --git a/src/input/r_mpeg_ts.cpp b/src/input/r_mpeg_ts.cpp index 0e91ff4bd..6dbc0b5c7 100644 --- a/src/input/r_mpeg_ts.cpp +++ b/src/input/r_mpeg_ts.cpp @@ -1384,12 +1384,10 @@ reader_c::identify() { for (auto const &track : m_tracks) { info = mtx::id::info_c{}; - info.add(mtx::id::language, track->language.get_iso639_alpha_3_code()); - info.set(mtx::id::stream_id, track->pid); - info.set(mtx::id::number, track->pid); - - if (track->program_number) - info.set(mtx::id::program_number, track->program_number.value()); + info.add(mtx::id::language, track->language.get_iso639_alpha_3_code()); + info.set(mtx::id::stream_id, track->pid); + info.set(mtx::id::number, track->pid); + info.add(mtx::id::program_number, track->program_number); if (pid_type_e::audio == track->type) { info.add(mtx::id::audio_channels, track->a_channels); @@ -1397,12 +1395,11 @@ reader_c::identify() { info.add(mtx::id::audio_bits_per_sample, track->a_bits_per_sample); } else if (pid_type_e::video == track->type) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->v_width, track->v_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, track->v_width, track->v_height); else if (pid_type_e::subtitles == track->type) { info.set(mtx::id::text_subtitles, track->codec.is(codec_c::type_e::S_SRT)); - if (track->m_ttx_wanted_page) - info.set(mtx::id::teletext_page, *track->m_ttx_wanted_page); + info.add(mtx::id::teletext_page, track->m_ttx_wanted_page); } auto multiplexed_track_ids = std::vector{}; diff --git a/src/input/r_obu.cpp b/src/input/r_obu.cpp index 4f7529566..a1dd18ada 100644 --- a/src/input/r_obu.cpp +++ b/src/input/r_obu.cpp @@ -84,7 +84,7 @@ obu_reader_c::read(generic_packetizer_c *, void obu_reader_c::identify() { auto info = mtx::id::info_c{}; - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_width, m_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_width, m_height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec_c::type_e::V_AV1, {}), info.get()); diff --git a/src/input/r_ogm.cpp b/src/input/r_ogm.cpp index ab0119e83..48b7977db 100644 --- a/src/input/r_ogm.cpp +++ b/src/input/r_ogm.cpp @@ -689,8 +689,7 @@ ogm_reader_c::identify() { if (!dmx->title.empty() && !dmx->ms_compat) info.add(mtx::id::track_name, dmx->title); - if ((0 != dmx->display_width) && (0 != dmx->display_height)) - info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", dmx->display_width, dmx->display_height)); + info.add_joined(mtx::id::display_dimensions, "x"s, dmx->display_width, dmx->display_height); if (dynamic_cast(dmx.get()) || dynamic_cast(dmx.get())) { info.add(mtx::id::text_subtitles, true); @@ -698,8 +697,7 @@ ogm_reader_c::identify() { } auto pixel_dimensions = dmx->get_pixel_dimensions(); - if (pixel_dimensions.first && pixel_dimensions.second) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", pixel_dimensions.first, pixel_dimensions.second)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, pixel_dimensions.first, pixel_dimensions.second); info.add(mtx::id::audio_channels, dmx->channels); info.add(mtx::id::audio_sampling_frequency, dmx->sample_rate); diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index 8ff983f2a..ca0a5d48f 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -2029,7 +2029,7 @@ qtmp4_reader_c::identify() { info.add(mtx::id::language, dmx.language.get_iso639_alpha_3_code()); if (dmx.is_video()) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", dmx.v_width, dmx.v_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, dmx.v_width, dmx.v_height); else if (dmx.is_audio()) { info.add(mtx::id::audio_channels, dmx.a_channels); diff --git a/src/input/r_real.cpp b/src/input/r_real.cpp index 5e02f149f..667170cd4 100644 --- a/src/input/r_real.cpp +++ b/src/input/r_real.cpp @@ -566,7 +566,7 @@ real_reader_c::identify() { info.set(mtx::id::number, demuxer->track->id); if (RMFF_TRACK_TYPE_VIDEO == demuxer->track->type) - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", demuxer->width, demuxer->height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, demuxer->width, demuxer->height); else if (RMFF_TRACK_TYPE_AUDIO == demuxer->track->type) { info.add(mtx::id::audio_channels, demuxer->channels); diff --git a/src/input/r_vc1.cpp b/src/input/r_vc1.cpp index 4d2c19ac1..f98d6463f 100644 --- a/src/input/r_vc1.cpp +++ b/src/input/r_vc1.cpp @@ -96,7 +96,7 @@ vc1_es_reader_c::read(generic_packetizer_c *, void vc1_es_reader_c::identify() { auto info = mtx::id::info_c{}; - info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", m_seqhdr.pixel_width, m_seqhdr.pixel_height)); + info.add_joined(mtx::id::pixel_dimensions, "x"s, m_seqhdr.pixel_width, m_seqhdr.pixel_height); id_result_container(); id_result_track(0, ID_RESULT_TRACK_VIDEO, codec_c::get_name(codec_c::type_e::V_VC1, "VC1"), info.get());