diff --git a/src/common/avc/es_parser.cpp b/src/common/avc/es_parser.cpp index 2f673ecba..547547416 100644 --- a/src/common/avc/es_parser.cpp +++ b/src/common/avc/es_parser.cpp @@ -608,11 +608,22 @@ es_parser_c::create_nalu_with_size(const memory_cptr &src, } memory_cptr -es_parser_c::get_avcc() +es_parser_c::get_configuration_record() const { return avcc_c{static_cast(m_nalu_size_length), m_sps_list, m_pps_list}.pack(); } +void +es_parser_c::set_configuration_record(memory_cptr const &bytes) { + auto avcc = avcc_c::unpack(bytes); + + for (auto const &nalu : avcc.m_sps_list) + handle_sps_nalu(nalu); // TODO: , extra_data_position_e::dont_store); + + for (auto const &nalu : avcc.m_pps_list) + handle_pps_nalu(nalu); // TODO: , extra_data_position_e::dont_store); +} + void es_parser_c::dump_info() const { diff --git a/src/common/avc/es_parser.h b/src/common/avc/es_parser.h index 0250a853f..34dd9a2da 100644 --- a/src/common/avc/es_parser.h +++ b/src/common/avc/es_parser.h @@ -58,7 +58,8 @@ public: virtual void flush() override; virtual void clear() override; - memory_cptr get_avcc() const; + virtual void set_configuration_record(memory_cptr const &bytes) override; + virtual memory_cptr get_configuration_record() const override; virtual int get_width() const override { assert(!m_sps_info_list.empty()); diff --git a/src/common/avc_hevc/es_parser.h b/src/common/avc_hevc/es_parser.h index 5ff5e8299..6217f16af 100644 --- a/src/common/avc_hevc/es_parser.h +++ b/src/common/avc_hevc/es_parser.h @@ -123,6 +123,8 @@ public: virtual void handle_nalu(memory_cptr const &nalu, uint64_t nalu_pos) = 0; + virtual void set_configuration_record(memory_cptr const &bytes) = 0; + virtual memory_cptr get_configuration_record() const = 0; virtual int get_width() const = 0; virtual int get_height() const = 0; diff --git a/src/common/hevc/es_parser.cpp b/src/common/hevc/es_parser.cpp index 402938774..71fc48d03 100644 --- a/src/common/hevc/es_parser.cpp +++ b/src/common/hevc/es_parser.cpp @@ -694,14 +694,14 @@ es_parser_c::calculate_frame_order() { } memory_cptr -es_parser_c::get_hevcc() +es_parser_c::get_configuration_record() const { return hevcc_c{static_cast(m_nalu_size_length), m_vps_list, m_sps_list, m_pps_list, m_user_data, m_codec_private}.pack(); } void -es_parser_c::set_hevcc(memory_cptr const &hevcc_bytes) { - auto hevcc = hevcc_c::unpack(hevcc_bytes); +es_parser_c::set_configuration_record(memory_cptr const &bytes) { + auto hevcc = hevcc_c::unpack(bytes); for (auto const &nalu : hevcc.m_vps_list) handle_vps_nalu(nalu, extra_data_position_e::dont_store); diff --git a/src/common/hevc/es_parser.h b/src/common/hevc/es_parser.h index 8cb8b4593..171b6f150 100644 --- a/src/common/hevc/es_parser.h +++ b/src/common/hevc/es_parser.h @@ -53,8 +53,8 @@ public: virtual void flush() override; virtual void clear() override; - void set_hevcc(memory_cptr const &hevcc_bytes); - memory_cptr get_hevcc() const; + virtual void set_configuration_record(memory_cptr const &bytes) override; + virtual memory_cptr get_configuration_record() const override; virtual int get_width() const override { assert(!m_sps_info_list.empty()); diff --git a/src/extract/xtr_hevc.cpp b/src/extract/xtr_hevc.cpp index 787ce47a8..2151c8d27 100644 --- a/src/extract/xtr_hevc.cpp +++ b/src/extract/xtr_hevc.cpp @@ -39,7 +39,7 @@ xtr_hevc_c::create_file(xtr_base_c *master, 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_hevcc(m_decoded_codec_private); + m_parser.set_configuration_record(m_decoded_codec_private); m_nal_size_size = 1 + (m_decoded_codec_private->get_buffer()[21] & 3); } diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index 616c8cdab..638a4d1bc 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -3395,7 +3395,7 @@ qtmp4_demuxer_c::check_for_hevc_video_annex_b_bitstream() { } priv.clear(); - priv.emplace_back(parser.get_hevcc()); + priv.emplace_back(parser.get_configuration_record()); break; } @@ -3527,7 +3527,7 @@ qtmp4_demuxer_c::derive_track_params_from_avc_bitstream() { parser.flush(); if (parser.headers_parsed()) - priv.emplace_back(parser.get_avcc()); + priv.emplace_back(parser.get_configuration_record()); mxdebug_if(m_debug_headers, fmt::format("derive_track_params_from_avc_bitstream: avcC derived? size {0} bytes\n", !priv.empty() && priv[0] ? priv[0]->get_size() : 0)); diff --git a/src/output/p_avc_es.cpp b/src/output/p_avc_es.cpp index e31e2491f..d53bcb41a 100644 --- a/src/output/p_avc_es.cpp +++ b/src/output/p_avc_es.cpp @@ -38,28 +38,8 @@ avc_es_video_packetizer_c(generic_reader_c *p_reader, } void -avc_es_video_packetizer_c::process_impl(packet_cptr const &packet) { - try { - if (packet->has_timestamp()) - m_parser.add_timestamp(packet->timestamp); - m_parser.add_bytes(packet->data->get_buffer(), packet->data->get_size()); - flush_frames(); - - } catch (mtx::exception &error) { - mxerror_tid(m_ti.m_fname, m_ti.m_id, - fmt::format(Y("mkvmerge encountered broken or unparsable data in this AVC/H.264 video track. " - "Either your file is damaged (which mkvmerge cannot cope with yet) or this is a bug in mkvmerge itself. " - "The error message was:\n{0}\n"), error.error())); - } -} - -void -avc_es_video_packetizer_c::handle_delayed_headers() { - if (0 < m_parser.get_num_skipped_frames()) - mxwarn_tid(m_ti.m_fname, m_ti.m_id, fmt::format(Y("This AVC/H.264 track does not start with a key frame. The first {0} frames have been skipped.\n"), m_parser.get_num_skipped_frames())); - - set_codec_private(m_parser.get_avcc()); - +avc_es_video_packetizer_c::check_if_default_duration_available() + const { if ( !m_reader->is_providing_timestamps() && !m_timestamp_factory && !m_parser.is_default_duration_forced() @@ -69,88 +49,6 @@ avc_es_video_packetizer_c::handle_delayed_headers() { mxwarn_tid(m_ti.m_fname, m_ti.m_id, Y("This AVC/H.264 track's timing information indicates that it uses a variable frame rate. " "However, no default duration nor an external timestamp file has been provided for it, nor does the source container provide timestamps. " "The resulting timestamps may not be useful.\n")); - - handle_aspect_ratio(); - handle_actual_default_duration(); - - rerender_track_headers(); -} - -void -avc_es_video_packetizer_c::handle_aspect_ratio() { - mxdebug_if(m_debug_aspect_ratio, fmt::format("already set? {0} has par been found? {1}\n", display_dimensions_or_aspect_ratio_set(), m_parser.has_par_been_found())); - - if (display_dimensions_or_aspect_ratio_set() || !m_parser.has_par_been_found()) - return; - - auto dimensions = m_parser.get_display_dimensions(m_hvideo_pixel_width, m_hvideo_pixel_height); - set_video_display_dimensions(dimensions.first, dimensions.second, generic_packetizer_c::ddu_pixels, OPTION_SOURCE_BITSTREAM); - - mxinfo_tid(m_ti.m_fname, m_ti.m_id, - fmt::format(Y("Extracted the aspect ratio information from the MPEG-4 layer 10 (AVC) video data " - "and set the display dimensions to {0}/{1}.\n"), m_ti.m_display_width, m_ti.m_display_height)); - - mxdebug_if(m_debug_aspect_ratio, - fmt::format("PAR {0} pixel_width/hgith {1}/{2} display_width/height {3}/{4}\n", - m_parser.get_par(), m_hvideo_pixel_width, m_hvideo_pixel_height, m_ti.m_display_width, m_ti.m_display_height)); -} - -void -avc_es_video_packetizer_c::handle_actual_default_duration() { - int64_t actual_default_duration = m_parser.get_most_often_used_duration(); - mxdebug_if(m_debug_timestamps, fmt::format("Most often used duration: {0} forced? {1} current default duration: {2}\n", actual_default_duration, m_default_duration_forced, m_htrack_default_duration)); - - if ( !m_default_duration_forced - && (0 < actual_default_duration) - && (m_htrack_default_duration != actual_default_duration)) - set_track_default_duration(actual_default_duration); - - else if ( m_default_duration_forced - && (0 < m_default_duration_for_interlaced_content) - && (std::abs(actual_default_duration - m_default_duration_for_interlaced_content) <= 20000)) { - m_default_duration_forced = false; - set_track_default_duration(m_default_duration_for_interlaced_content); - } -} - -void -avc_es_video_packetizer_c::flush_frames() { - while (m_parser.frame_available()) { - if (m_first_frame) { - handle_delayed_headers(); - m_first_frame = false; - } - - auto frame = m_parser.get_frame(); - auto duration = frame.m_end > frame.m_start ? frame.m_end - frame.m_start : m_htrack_default_duration; - auto packet = std::make_shared(frame.m_data, frame.m_start, duration, - frame.is_i_frame() ? -1 : frame.m_start + frame.m_ref1, - !frame.is_b_frame() ? -1 : frame.m_start + frame.m_ref2); - packet->key_flag = frame.is_key_frame(); - packet->discardable_flag = frame.is_discardable(); - - add_packet(packet); - } -} - -void -avc_es_video_packetizer_c::connect(generic_packetizer_c *src, - int64_t p_append_timestamp_offset) { - generic_packetizer_c::connect(src, p_append_timestamp_offset); - - if (2 != m_connected_to) - return; - - avc_es_video_packetizer_c *real_src = dynamic_cast(src); - assert(real_src); - - m_htrack_default_duration = real_src->m_htrack_default_duration; - m_default_duration_forced = real_src->m_default_duration_forced; - - if (m_default_duration_forced && (-1 != m_htrack_default_duration)) { - m_default_duration_for_interlaced_content = m_htrack_default_duration / 2; - m_parser.force_default_duration(m_default_duration_for_interlaced_content); - } } connection_result_e diff --git a/src/output/p_avc_es.h b/src/output/p_avc_es.h index 4511ab4aa..56baf1b71 100644 --- a/src/output/p_avc_es.h +++ b/src/output/p_avc_es.h @@ -25,18 +25,12 @@ protected: public: avc_es_video_packetizer_c(generic_reader_c *p_reader, track_info_c &p_ti); - virtual void flush_frames() override; - - virtual translatable_string_c get_format_name() const { + virtual translatable_string_c get_format_name() const override { return YT("AVC/H.264 (unframed)"); }; - virtual void connect(generic_packetizer_c *src, int64_t p_append_timestamp_offset = -1); - virtual connection_result_e can_connect_to(generic_packetizer_c *src, std::string &error_message); + virtual connection_result_e can_connect_to(generic_packetizer_c *src, std::string &error_message) override; protected: - virtual void process_impl(packet_cptr const &packet) override; - virtual void handle_delayed_headers(); - virtual void handle_aspect_ratio(); - virtual void handle_actual_default_duration(); + virtual void check_if_default_duration_available() const override; }; diff --git a/src/output/p_avc_hevc_es.cpp b/src/output/p_avc_hevc_es.cpp index 975e94104..32cdacab1 100644 --- a/src/output/p_avc_hevc_es.cpp +++ b/src/output/p_avc_hevc_es.cpp @@ -83,24 +83,124 @@ avc_hevc_es_video_packetizer_c::add_extra_data(memory_cptr const &data) { m_parser_base->add_bytes(data->get_buffer(), data->get_size()); } +void +avc_hevc_es_video_packetizer_c::process_impl(packet_cptr const &packet) { + try { + if (packet->has_timestamp()) + m_parser_base->add_timestamp(packet->timestamp); + m_parser_base->add_bytes(packet->data->get_buffer(), packet->data->get_size()); + flush_frames(); + + } catch (mtx::exception &error) { + mxerror_tid(m_ti.m_fname, m_ti.m_id, + fmt::format("{0} {1}\n{2}\n", + Y("mkvmerge encountered broken or unparsable data in this video track."), + Y("The error message was:"), + error.error())); + } +} + void avc_hevc_es_video_packetizer_c::flush_impl() { m_parser_base->flush(); flush_frames(); } -// void -// hevc_es_video_packetizer_c::flush_frames() { -// while (m_parser_base->frame_available()) { -// if (m_first_frame) { -// handle_delayed_headers(); -// m_first_frame = false; -// } +void +avc_hevc_es_video_packetizer_c::flush_frames() { + while (m_parser_base->frame_available()) { + if (m_first_frame) { + handle_delayed_headers(); + m_first_frame = false; + } -// auto frame = m_parser_base->get_frame(); -// add_packet(std::make_shared(frame.m_data, frame.m_start, -// frame.m_end > frame.m_start ? frame.m_end - frame.m_start : m_htrack_default_duration, -// frame.is_key_frame() ? -1 : frame.m_start + frame.m_ref1, -// !frame.is_b_frame() ? -1 : frame.m_start + frame.m_ref2)); -// } -// } + auto frame = m_parser_base->get_frame(); + auto duration = frame.m_end > frame.m_start ? frame.m_end - frame.m_start : m_htrack_default_duration; + auto packet = std::make_shared(frame.m_data, frame.m_start, duration, + frame.is_key_frame() ? -1 : frame.m_start + frame.m_ref1, + !frame.is_b_frame() ? -1 : frame.m_start + frame.m_ref2); + + packet->key_flag = frame.is_key_frame(); + packet->discardable_flag = frame.is_discardable(); + + add_packet(packet); + } +} + +void +avc_hevc_es_video_packetizer_c::check_if_default_duration_available() + const { + // No default implementation, but not required either. +} + +void +avc_hevc_es_video_packetizer_c::handle_delayed_headers() { + if (0 < m_parser_base->get_num_skipped_frames()) + mxwarn_tid(m_ti.m_fname, m_ti.m_id, fmt::format(Y("This AVC/H.264 track does not start with a key frame. The first {0} frames have been skipped.\n"), m_parser_base->get_num_skipped_frames())); + + set_codec_private(m_parser_base->get_configuration_record()); + + check_if_default_duration_available(); + + handle_aspect_ratio(); + handle_actual_default_duration(); + + rerender_track_headers(); +} + +void +avc_hevc_es_video_packetizer_c::handle_aspect_ratio() { + mxdebug_if(m_debug_aspect_ratio, fmt::format("already set? {0} has par been found? {1}\n", display_dimensions_or_aspect_ratio_set(), m_parser_base->has_par_been_found())); + + if (display_dimensions_or_aspect_ratio_set() || !m_parser_base->has_par_been_found()) + return; + + auto dimensions = m_parser_base->get_display_dimensions(m_hvideo_pixel_width, m_hvideo_pixel_height); + set_video_display_dimensions(dimensions.first, dimensions.second, generic_packetizer_c::ddu_pixels, OPTION_SOURCE_BITSTREAM); + + mxinfo_tid(m_ti.m_fname, m_ti.m_id, + fmt::format(Y("Extracted the aspect ratio information from the video bitstream and set the display dimensions to {0}/{1}.\n"), + m_ti.m_display_width, m_ti.m_display_height)); + + mxdebug_if(m_debug_aspect_ratio, + fmt::format("PAR {0} pixel_width/hgith {1}/{2} display_width/height {3}/{4}\n", + m_parser_base->get_par(), m_hvideo_pixel_width, m_hvideo_pixel_height, m_ti.m_display_width, m_ti.m_display_height)); +} + +void +avc_hevc_es_video_packetizer_c::handle_actual_default_duration() { + int64_t actual_default_duration = m_parser_base->get_most_often_used_duration(); + mxdebug_if(m_debug_timestamps, fmt::format("Most often used duration: {0} forced? {1} current default duration: {2}\n", actual_default_duration, m_default_duration_forced, m_htrack_default_duration)); + + if ( !m_default_duration_forced + && (0 < actual_default_duration) + && (m_htrack_default_duration != actual_default_duration)) + set_track_default_duration(actual_default_duration); + + else if ( m_default_duration_forced + && (0 < m_default_duration_for_interlaced_content) + && (std::abs(actual_default_duration - m_default_duration_for_interlaced_content) <= 20000)) { + m_default_duration_forced = false; + set_track_default_duration(m_default_duration_for_interlaced_content); + } +} + +void +avc_hevc_es_video_packetizer_c::connect(generic_packetizer_c *src, + int64_t p_append_timestamp_offset) { + generic_packetizer_c::connect(src, p_append_timestamp_offset); + + if (2 != m_connected_to) + return; + + auto real_src = dynamic_cast(src); + assert(real_src); + + m_htrack_default_duration = real_src->m_htrack_default_duration; + m_default_duration_forced = real_src->m_default_duration_forced; + + if (m_default_duration_forced && (-1 != m_htrack_default_duration)) { + m_default_duration_for_interlaced_content = m_htrack_default_duration / 2; + m_parser_base->force_default_duration(m_default_duration_for_interlaced_content); + } +} diff --git a/src/output/p_avc_hevc_es.h b/src/output/p_avc_hevc_es.h index 56bdef63f..81aacb972 100644 --- a/src/output/p_avc_hevc_es.h +++ b/src/output/p_avc_hevc_es.h @@ -35,8 +35,17 @@ public: virtual void set_container_default_field_duration(int64_t default_duration); virtual unsigned int get_nalu_size_length() const; - virtual void flush_frames() = 0; + virtual void connect(generic_packetizer_c *src, int64_t p_append_timestamp_offset) override; protected: + virtual void process_impl(packet_cptr const &packet) override; + virtual void flush_impl() override; + virtual void flush_frames(); + + virtual void check_if_default_duration_available() const; + + virtual void handle_delayed_headers(); + virtual void handle_aspect_ratio(); + virtual void handle_actual_default_duration(); }; diff --git a/src/output/p_hevc.cpp b/src/output/p_hevc.cpp index c57c15559..004b5e1ed 100644 --- a/src/output/p_hevc.cpp +++ b/src/output/p_hevc.cpp @@ -49,7 +49,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_hevcc(m_hcodec_private); + p.parser->set_configuration_record(m_hcodec_private); } void diff --git a/src/output/p_hevc_es.cpp b/src/output/p_hevc_es.cpp index 12469c001..f26959edc 100644 --- a/src/output/p_hevc_es.cpp +++ b/src/output/p_hevc_es.cpp @@ -34,113 +34,6 @@ hevc_es_video_packetizer_c::hevc_es_video_packetizer_c(generic_reader_c *p_reade m_parser.normalize_parameter_sets(!mtx::hacks::is_engaged(mtx::hacks::DONT_NORMALIZE_PARAMETER_SETS)); } -void -hevc_es_video_packetizer_c::process_impl(packet_cptr const &packet) { - try { - if (packet->has_timestamp()) - m_parser.add_timestamp(packet->timestamp); - m_parser.add_bytes(packet->data->get_buffer(), packet->data->get_size()); - flush_frames(); - - } catch (mtx::exception &error) { - mxerror_tid(m_ti.m_fname, m_ti.m_id, - fmt::format(Y("mkvmerge encountered broken or unparsable data in this HEVC video track. " - "Either your file is damaged (which mkvmerge cannot cope with yet) or this is a bug in mkvmerge itself. " - "The error message was:\n{0}\n"), error.error())); - } -} - -void -hevc_es_video_packetizer_c::handle_delayed_headers() { - if (0 < m_parser.get_num_skipped_frames()) - mxwarn_tid(m_ti.m_fname, m_ti.m_id, fmt::format(Y("This HEVC track does not start with a key frame. The first {0} frames have been skipped.\n"), m_parser.get_num_skipped_frames())); - - set_codec_private(m_parser.get_hevcc()); - - handle_aspect_ratio(); - handle_actual_default_duration(); - - rerender_track_headers(); -} - -void -hevc_es_video_packetizer_c::handle_aspect_ratio() { - mxdebug_if(m_debug_aspect_ratio, fmt::format("already set? {0} has par been found? {1}\n", display_dimensions_or_aspect_ratio_set(), m_parser.has_par_been_found())); - - if (display_dimensions_or_aspect_ratio_set() || !m_parser.has_par_been_found()) - return; - - auto dimensions = m_parser.get_display_dimensions(m_hvideo_pixel_width, m_hvideo_pixel_height); - set_video_display_dimensions(dimensions.first, dimensions.second, generic_packetizer_c::ddu_pixels, OPTION_SOURCE_BITSTREAM); - - mxinfo_tid(m_ti.m_fname, m_ti.m_id, - fmt::format(Y("Extracted the aspect ratio information from the HEVC video data " - "and set the display dimensions to {0}/{1}.\n"), m_ti.m_display_width, m_ti.m_display_height)); - - mxdebug_if(m_debug_aspect_ratio, - fmt::format("PAR {0} pixel_width/hgith {1}/{2} display_width/height {3}/{4}\n", - m_parser.get_par(), m_hvideo_pixel_width, m_hvideo_pixel_height, m_ti.m_display_width, m_ti.m_display_height)); -} - -void -hevc_es_video_packetizer_c::handle_actual_default_duration() { - int64_t actual_default_duration = m_parser.get_most_often_used_duration(); - mxdebug_if(m_debug_timestamps, fmt::format("Most often used duration: {0} forced? {1} current default duration: {2}\n", actual_default_duration, m_default_duration_forced, m_htrack_default_duration)); - - if ( !m_default_duration_forced - && (0 < actual_default_duration) - && (m_htrack_default_duration != actual_default_duration)) - set_track_default_duration(actual_default_duration); - - else if ( m_default_duration_forced - && (0 < m_default_duration_for_interlaced_content) - && (std::abs(actual_default_duration - m_default_duration_for_interlaced_content) <= 20000)) { - m_default_duration_forced = false; - set_track_default_duration(m_default_duration_for_interlaced_content); - } -} - -void -hevc_es_video_packetizer_c::flush_frames() { - while (m_parser_base->frame_available()) { - if (m_first_frame) { - handle_delayed_headers(); - m_first_frame = false; - } - - auto frame = m_parser_base->get_frame(); - auto duration = frame.m_end > frame.m_start ? frame.m_end - frame.m_start : m_htrack_default_duration; - auto packet = std::make_shared(frame.m_data, frame.m_start, duration, - frame.is_key_frame() ? -1 : frame.m_start + frame.m_ref1, - !frame.is_b_frame() ? -1 : frame.m_start + frame.m_ref2); - - packet->key_flag = frame.is_key_frame(); - packet->discardable_flag = frame.is_discardable(); - - add_packet(packet); - } -} - -void -hevc_es_video_packetizer_c::connect(generic_packetizer_c *src, - int64_t p_append_timestamp_offset) { - generic_packetizer_c::connect(src, p_append_timestamp_offset); - - if (2 != m_connected_to) - return; - - auto *real_src = dynamic_cast(src); - assert(real_src); - - m_htrack_default_duration = real_src->m_htrack_default_duration; - m_default_duration_forced = real_src->m_default_duration_forced; - - if (m_default_duration_forced && (-1 != m_htrack_default_duration)) { - m_default_duration_for_interlaced_content = m_htrack_default_duration / 2; - m_parser.force_default_duration(m_default_duration_for_interlaced_content); - } -} - connection_result_e hevc_es_video_packetizer_c::can_connect_to(generic_packetizer_c *src, [[maybe_unused]] std::string &error_message) { diff --git a/src/output/p_hevc_es.h b/src/output/p_hevc_es.h index 5edce77d8..b80e13f7f 100644 --- a/src/output/p_hevc_es.h +++ b/src/output/p_hevc_es.h @@ -24,18 +24,9 @@ protected: public: hevc_es_video_packetizer_c(generic_reader_c *p_reader, track_info_c &p_ti); - virtual void flush_frames() override; - - virtual translatable_string_c get_format_name() const { + virtual translatable_string_c get_format_name() const override { return YT("HEVC/H.265 (unframed)"); }; - virtual void connect(generic_packetizer_c *src, int64_t p_append_timestamp_offset = -1); - virtual connection_result_e can_connect_to(generic_packetizer_c *src, std::string &error_message); - -protected: - virtual void process_impl(packet_cptr const &packet) override; - virtual void handle_delayed_headers(); - virtual void handle_aspect_ratio(); - virtual void handle_actual_default_duration(); + virtual connection_result_e can_connect_to(generic_packetizer_c *src, std::string &error_message) override; };