1 /* 2 mkvmerge -- utility for splicing together matroska files 3 from component media subtypes 4 5 Distributed under the GPL v2 6 see the file COPYING for details 7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html 8 9 AV1 video output module 10 11 Written by Moritz Bunkus <moritz@bunkus.org>. 12 */ 13 14 #include "common/common_pch.h" 15 16 #include "common/av1.h" 17 #include "common/codec.h" 18 #include "common/hacks.h" 19 #include "merge/connection_checks.h" 20 #include "merge/output_control.h" 21 #include "output/p_av1.h" 22 23 using namespace libmatroska; 24 av1_video_packetizer_c(generic_reader_c * p_reader,track_info_c & p_ti)25av1_video_packetizer_c::av1_video_packetizer_c(generic_reader_c *p_reader, 26 track_info_c &p_ti) 27 : generic_packetizer_c{p_reader, p_ti} 28 { 29 m_timestamp_factory_application_mode = TFA_SHORT_QUEUEING; 30 31 set_track_type(track_video); 32 set_codec_id(MKV_V_AV1); 33 set_codec_private(m_ti.m_private_data); 34 set_video_pixel_width(0); 35 set_video_pixel_height(0); 36 } 37 38 void set_header_parameters()39av1_video_packetizer_c::set_header_parameters() { 40 if (m_header_parameters_set) 41 return; 42 43 if (!m_parser.headers_parsed()) 44 return; 45 46 auto need_to_rerender = false; 47 48 if (!m_hcodec_private) { 49 set_codec_private(m_parser.get_av1c()); 50 need_to_rerender = true; 51 } 52 53 auto dimensions = m_parser.get_pixel_dimensions(); 54 55 if (!m_hvideo_pixel_width || !m_hvideo_pixel_height) { 56 set_video_pixel_width(dimensions.first); 57 set_video_pixel_height(dimensions.second); 58 need_to_rerender = true; 59 } 60 61 if (!m_hvideo_display_width || !m_hvideo_display_height) { 62 set_video_display_width(dimensions.first); 63 set_video_display_height(dimensions.second); 64 need_to_rerender = true; 65 } 66 67 auto frame_duration = m_parser.get_frame_duration(); 68 if ((m_htrack_default_duration <= 0) && frame_duration) { 69 set_track_default_duration(mtx::to_int(frame_duration)); 70 need_to_rerender = true; 71 72 } else if ((m_htrack_default_duration > 0) && !frame_duration) 73 m_parser.set_default_duration(m_htrack_default_duration); 74 75 if (need_to_rerender) 76 rerender_track_headers(); 77 78 m_header_parameters_set = true; 79 80 if (!m_is_framed) 81 return; 82 83 m_parser.set_parse_sequence_header_obus_only(true); 84 85 while (m_parser.frame_available()) 86 m_parser.get_next_frame(); 87 } 88 89 void process_impl(packet_cptr const & packet)90av1_video_packetizer_c::process_impl(packet_cptr const &packet) { 91 m_parser.debug_obu_types(*packet->data); 92 93 m_parser.parse(*packet->data); 94 95 set_header_parameters(); 96 97 if (m_is_framed) 98 process_framed(packet); 99 else 100 process_unframed(); 101 } 102 103 void process_framed(packet_cptr packet)104av1_video_packetizer_c::process_framed(packet_cptr packet) { 105 packet->bref = m_parser.is_keyframe(*packet->data) ? -1 : m_previous_timestamp; 106 m_previous_timestamp = packet->timestamp; 107 108 add_packet(packet); 109 } 110 111 void process_unframed()112av1_video_packetizer_c::process_unframed() { 113 flush_frames(); 114 } 115 116 void flush_impl()117av1_video_packetizer_c::flush_impl() { 118 if (m_is_framed) 119 return; 120 121 m_parser.flush(); 122 flush_frames(); 123 } 124 125 void flush_frames()126av1_video_packetizer_c::flush_frames() { 127 while (m_parser.frame_available()) { 128 auto frame = m_parser.get_next_frame(); 129 auto bref = frame.is_keyframe ? -1 : m_previous_timestamp; 130 auto duration = m_htrack_default_duration > 0 ? m_htrack_default_duration : -1; 131 m_previous_timestamp = frame.timestamp; 132 133 add_packet(std::make_shared<packet_t>(frame.mem, frame.timestamp, duration, bref)); 134 } 135 } 136 137 void set_is_unframed()138av1_video_packetizer_c::set_is_unframed() { 139 m_is_framed = false; 140 } 141 142 connection_result_e can_connect_to(generic_packetizer_c * src,std::string &)143av1_video_packetizer_c::can_connect_to(generic_packetizer_c *src, 144 std::string &) { 145 auto psrc = dynamic_cast<av1_video_packetizer_c *>(src); 146 if (!psrc) 147 return CAN_CONNECT_NO_FORMAT; 148 149 return CAN_CONNECT_YES; 150 } 151 152 bool is_compatible_with(output_compatibility_e compatibility)153av1_video_packetizer_c::is_compatible_with(output_compatibility_e compatibility) { 154 return (OC_MATROSKA == compatibility) || (OC_WEBM == compatibility); 155 } 156