AVC/HEVC ES: move more code to common base class

This commit is contained in:
Moritz Bunkus 2021-08-25 14:19:31 +02:00
parent 54524a08c1
commit bfe0e2c4a8
No known key found for this signature in database
GPG Key ID: 74AF00ADF2E32C85
9 changed files with 98 additions and 82 deletions

View File

@ -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"));

View File

@ -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;
};
}

View File

@ -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)

View File

@ -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:

View File

@ -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 {

View File

@ -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;
};

View File

@ -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);

View File

@ -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);
}

View File

@ -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