mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2025-01-04 01:03:33 +00:00
AVC/HEVC ES: move more code to common base class
This commit is contained in:
parent
54524a08c1
commit
bfe0e2c4a8
@ -21,6 +21,7 @@
|
||||
#include "common/endian.h"
|
||||
#include "common/frame_timing.h"
|
||||
#include "common/hacks.h"
|
||||
#include "common/list_utils.h"
|
||||
#include "common/mpeg.h"
|
||||
#include "common/strings/formatting.h"
|
||||
|
||||
@ -77,6 +78,13 @@ es_parser_c::flush_incomplete_frame() {
|
||||
m_have_incomplete_frame = false;
|
||||
}
|
||||
|
||||
bool
|
||||
es_parser_c::does_nalu_get_included_in_extra_data(memory_c const &nalu)
|
||||
const {
|
||||
auto nalu_type = (nalu.get_buffer())[0] & 0x1f;
|
||||
return mtx::included_in(nalu_type, NALU_TYPE_SEQ_PARAM, NALU_TYPE_PIC_PARAM);
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::add_sps_and_pps_to_extra_data() {
|
||||
mxdebug_if(m_debug_sps_pps_changes, fmt::format("avc: adding all SPS & PPS before key frame due to changes from AVCC\n"));
|
||||
|
@ -89,9 +89,9 @@ protected:
|
||||
|
||||
int64_t duration_for_impl(unsigned int sps, bool field_pic_flag) const;
|
||||
virtual void calculate_frame_order() override;
|
||||
virtual bool does_nalu_get_included_in_extra_data(memory_c const &nalu) const override;
|
||||
|
||||
virtual void init_nalu_names() const override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ es_parser_c::set_next_i_slice_is_key_frame() {
|
||||
m_recovery_point_valid = true;
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::set_normalize_parameter_sets(bool normalize) {
|
||||
m_normalize_parameter_sets = normalize;
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::maybe_dump_raw_data(unsigned char const *buffer,
|
||||
std::size_t size) {
|
||||
@ -254,6 +259,72 @@ es_parser_c::add_nalu_to_extra_data(memory_cptr const &nalu,
|
||||
container.push_back(nalu);
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::add_nalu_to_pending_frame_data(memory_cptr const &nalu) {
|
||||
nalu->take_ownership();
|
||||
m_pending_frame_data.emplace_back(nalu);
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::add_parameter_sets_to_extra_data() {
|
||||
std::unordered_map<uint32_t, bool> is_in_extra_data;
|
||||
|
||||
for (auto const &data : m_extra_data_pre) {
|
||||
if (does_nalu_get_included_in_extra_data(*data))
|
||||
return;
|
||||
|
||||
is_in_extra_data[mtx::checksum::calculate_as_uint(mtx::checksum::algorithm_e::adler32, *data)] = true;
|
||||
}
|
||||
|
||||
auto old_extra_data = std::move(m_extra_data_pre);
|
||||
|
||||
m_extra_data_pre.clear();
|
||||
m_extra_data_pre.reserve(m_vps_list.size() + m_sps_list.size() + m_pps_list.size() + old_extra_data.size() + m_extra_data_initial.size());
|
||||
|
||||
auto inserter = std::back_inserter(m_extra_data_pre);
|
||||
|
||||
std::copy(m_vps_list.begin(), m_vps_list.end(), inserter);
|
||||
std::copy(m_sps_list.begin(), m_sps_list.end(), inserter);
|
||||
std::copy(m_pps_list.begin(), m_pps_list.end(), inserter);
|
||||
|
||||
for (auto const &data : m_extra_data_initial)
|
||||
if (!is_in_extra_data[mtx::checksum::calculate_as_uint(mtx::checksum::algorithm_e::adler32, *data)])
|
||||
inserter = data;
|
||||
|
||||
std::copy(old_extra_data.begin(), old_extra_data.end(), inserter);
|
||||
|
||||
m_extra_data_initial.clear();
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::build_frame_data() {
|
||||
if (m_incomplete_frame.m_keyframe && m_normalize_parameter_sets)
|
||||
add_parameter_sets_to_extra_data();
|
||||
|
||||
auto all_nalus = std::move(m_extra_data_pre);
|
||||
all_nalus.reserve(all_nalus.size() + m_pending_frame_data.size());
|
||||
|
||||
std::copy(m_pending_frame_data.begin(), m_pending_frame_data.end(), std::back_inserter(all_nalus));
|
||||
|
||||
m_extra_data_pre.clear();
|
||||
m_pending_frame_data.clear();
|
||||
|
||||
auto final_size = 0;
|
||||
|
||||
for (auto const &nalu : all_nalus)
|
||||
final_size += m_nalu_size_length + nalu->get_size();
|
||||
|
||||
m_incomplete_frame.m_data = memory_c::alloc(final_size);
|
||||
auto dest = m_incomplete_frame.m_data->get_buffer();
|
||||
|
||||
for (auto const &nalu : all_nalus) {
|
||||
mtx::mpeg::write_nalu_size(dest, nalu->get_size(), m_nalu_size_length);
|
||||
std::memcpy(dest + m_nalu_size_length, nalu->get_buffer(), nalu->get_size());
|
||||
|
||||
dest += m_nalu_size_length + nalu->get_size();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::flush_unhandled_nalus() {
|
||||
for (auto const &nalu_with_pos : m_unhandled_nalus)
|
||||
|
@ -56,7 +56,7 @@ protected:
|
||||
|
||||
std::deque<std::pair<memory_cptr, uint64_t>> m_unhandled_nalus;
|
||||
|
||||
bool m_first_cleanup{true}, m_simple_picture_order{}, m_discard_actual_frames{};
|
||||
bool m_first_cleanup{true}, m_simple_picture_order{}, m_discard_actual_frames{}, m_normalize_parameter_sets{};
|
||||
|
||||
std::string const m_debug_type;
|
||||
debugging_option_c m_debug_keyframe_detection, m_debug_nalu_types, m_debug_timestamps, m_debug_sps_info, m_debug_statistics;
|
||||
@ -96,6 +96,8 @@ public:
|
||||
|
||||
void set_next_i_slice_is_key_frame();
|
||||
|
||||
void set_normalize_parameter_sets(bool normalize = true);
|
||||
|
||||
void set_nalu_size_length(int nalu_size_length);
|
||||
int get_nalu_size_length() const;
|
||||
|
||||
@ -149,6 +151,12 @@ public:
|
||||
|
||||
protected:
|
||||
void add_nalu_to_extra_data(memory_cptr const &nalu, extra_data_position_e position = extra_data_position_e::pre);
|
||||
void add_nalu_to_pending_frame_data(memory_cptr const &nalu);
|
||||
void add_parameter_sets_to_extra_data();
|
||||
void build_frame_data();
|
||||
|
||||
virtual bool does_nalu_get_included_in_extra_data(memory_c const &nalu) const = 0;
|
||||
|
||||
void debug_dump_statistics() const;
|
||||
|
||||
public:
|
||||
|
@ -49,11 +49,6 @@ es_parser_c::headers_parsed()
|
||||
&& (m_sps_info_list.front().get_height() > 0);
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::normalize_parameter_sets(bool normalize) {
|
||||
m_normalize_parameter_sets = normalize;
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::flush() {
|
||||
if (m_unparsed_buffer && (5 <= m_unparsed_buffer->get_size())) {
|
||||
@ -93,42 +88,11 @@ es_parser_c::flush_incomplete_frame() {
|
||||
m_incomplete_frame.clear();
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::add_parameter_sets_to_extra_data() {
|
||||
std::unordered_map<uint32_t, bool> is_in_extra_data;
|
||||
|
||||
for (auto const &data : m_extra_data_pre) {
|
||||
auto nalu_type = (data->get_buffer()[0] >> 1) & 0x3f;
|
||||
if (mtx::included_in(nalu_type, NALU_TYPE_VIDEO_PARAM, NALU_TYPE_SEQ_PARAM, NALU_TYPE_PIC_PARAM))
|
||||
return;
|
||||
|
||||
is_in_extra_data[mtx::checksum::calculate_as_uint(mtx::checksum::algorithm_e::adler32, *data)] = true;
|
||||
}
|
||||
|
||||
auto old_extra_data = std::move(m_extra_data_pre);
|
||||
|
||||
m_extra_data_pre.clear();
|
||||
m_extra_data_pre.reserve(m_vps_list.size() + m_sps_list.size() + m_pps_list.size() + old_extra_data.size() + m_extra_data_initial.size());
|
||||
|
||||
auto inserter = std::back_inserter(m_extra_data_pre);
|
||||
|
||||
std::copy(m_vps_list.begin(), m_vps_list.end(), inserter);
|
||||
std::copy(m_sps_list.begin(), m_sps_list.end(), inserter);
|
||||
std::copy(m_pps_list.begin(), m_pps_list.end(), inserter);
|
||||
|
||||
for (auto const &data : m_extra_data_initial)
|
||||
if (!is_in_extra_data[mtx::checksum::calculate_as_uint(mtx::checksum::algorithm_e::adler32, *data)])
|
||||
inserter = data;
|
||||
|
||||
std::copy(old_extra_data.begin(), old_extra_data.end(), inserter);
|
||||
|
||||
m_extra_data_initial.clear();
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::add_nalu_to_pending_frame_data(memory_cptr const &nalu) {
|
||||
nalu->take_ownership();
|
||||
m_pending_frame_data.emplace_back(nalu);
|
||||
bool
|
||||
es_parser_c::does_nalu_get_included_in_extra_data(memory_c const &nalu)
|
||||
const {
|
||||
auto nalu_type = (nalu.get_buffer()[0] >> 1) & 0x3f;
|
||||
return mtx::included_in(nalu_type, NALU_TYPE_VIDEO_PARAM, NALU_TYPE_SEQ_PARAM, NALU_TYPE_PIC_PARAM);
|
||||
}
|
||||
|
||||
void
|
||||
@ -553,35 +517,6 @@ es_parser_c::parse_slice(memory_cptr const &nalu,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
es_parser_c::build_frame_data() {
|
||||
if (m_incomplete_frame.m_keyframe && m_normalize_parameter_sets)
|
||||
add_parameter_sets_to_extra_data();
|
||||
|
||||
auto all_nalus = std::move(m_extra_data_pre);
|
||||
all_nalus.reserve(all_nalus.size() + m_pending_frame_data.size());
|
||||
|
||||
std::copy(m_pending_frame_data.begin(), m_pending_frame_data.end(), std::back_inserter(all_nalus));
|
||||
|
||||
m_extra_data_pre.clear();
|
||||
m_pending_frame_data.clear();
|
||||
|
||||
auto final_size = 0;
|
||||
|
||||
for (auto const &nalu : all_nalus)
|
||||
final_size += m_nalu_size_length + nalu->get_size();
|
||||
|
||||
m_incomplete_frame.m_data = memory_c::alloc(final_size);
|
||||
auto dest = m_incomplete_frame.m_data->get_buffer();
|
||||
|
||||
for (auto const &nalu : all_nalus) {
|
||||
mtx::mpeg::write_nalu_size(dest, nalu->get_size(), m_nalu_size_length);
|
||||
std::memcpy(dest + m_nalu_size_length, nalu->get_buffer(), nalu->get_size());
|
||||
|
||||
dest += m_nalu_size_length + nalu->get_size();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
es_parser_c::duration_for(mtx::avc_hevc::slice_info_t const &si)
|
||||
const {
|
||||
|
@ -35,8 +35,6 @@ protected:
|
||||
|
||||
mtx::dovi::dovi_rpu_data_header_t m_dovi_rpu_data_header;
|
||||
|
||||
bool m_normalize_parameter_sets{};
|
||||
|
||||
debugging_option_c m_debug_parameter_sets{"hevc_parser|hevc_parameter_sets"}, m_debug_frame_order{"hevc_parser|hevc_frame_order"};
|
||||
|
||||
public:
|
||||
@ -62,8 +60,6 @@ public:
|
||||
|
||||
bool headers_parsed() const;
|
||||
|
||||
void normalize_parameter_sets(bool normalize = true);
|
||||
|
||||
virtual int64_t duration_for(mtx::avc_hevc::slice_info_t const &si) const override;
|
||||
|
||||
bool has_dovi_rpu_header() const {
|
||||
@ -90,9 +86,7 @@ protected:
|
||||
void handle_slice_nalu(memory_cptr const &nalu, uint64_t nalu_pos);
|
||||
void flush_incomplete_frame();
|
||||
virtual void calculate_frame_order() override;
|
||||
void add_parameter_sets_to_extra_data();
|
||||
void add_nalu_to_pending_frame_data(memory_cptr const &nalu);
|
||||
void build_frame_data();
|
||||
virtual bool does_nalu_get_included_in_extra_data(memory_c const &nalu) const override;
|
||||
|
||||
virtual void init_nalu_names() const override;
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ xtr_hevc_c::create_file(xtr_base_c *master,
|
||||
if (m_decoded_codec_private->get_size() < 23)
|
||||
mxerror(fmt::format(Y("Track {0} CodecPrivate is too small.\n"), m_tid));
|
||||
|
||||
m_parser.normalize_parameter_sets(m_normalize_parameter_sets);
|
||||
m_parser.set_normalize_parameter_sets(m_normalize_parameter_sets);
|
||||
m_parser.set_configuration_record(m_decoded_codec_private);
|
||||
|
||||
m_nal_size_size = 1 + (m_decoded_codec_private->get_buffer()[21] & 3);
|
||||
|
@ -48,7 +48,7 @@ hevc_video_packetizer_c(generic_reader_c *p_reader,
|
||||
|
||||
set_codec_private(m_ti.m_private_data);
|
||||
|
||||
p.parser->normalize_parameter_sets(!mtx::hacks::is_engaged(mtx::hacks::DONT_NORMALIZE_PARAMETER_SETS));
|
||||
p.parser->set_normalize_parameter_sets(!mtx::hacks::is_engaged(mtx::hacks::DONT_NORMALIZE_PARAMETER_SETS));
|
||||
p.parser->set_configuration_record(m_hcodec_private);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ hevc_es_video_packetizer_c::hevc_es_video_packetizer_c(generic_reader_c *p_reade
|
||||
{
|
||||
set_codec_id(MKV_V_MPEGH_HEVC);
|
||||
|
||||
m_parser.normalize_parameter_sets(!mtx::hacks::is_engaged(mtx::hacks::DONT_NORMALIZE_PARAMETER_SETS));
|
||||
m_parser.set_normalize_parameter_sets(!mtx::hacks::is_engaged(mtx::hacks::DONT_NORMALIZE_PARAMETER_SETS));
|
||||
}
|
||||
|
||||
connection_result_e
|
||||
|
Loading…
Reference in New Issue
Block a user