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 class definitions for the MPEG PS demultiplexer module 10 11 Written by Moritz Bunkus <moritz@bunkus.org>. 12 */ 13 14 #pragma once 15 16 #include "common/common_pch.h" 17 18 #include "common/bit_reader.h" 19 #include "common/codec.h" 20 #include "common/debugging.h" 21 #include "common/dts.h" 22 #include "common/mm_multi_file_io.h" 23 #include "common/mpeg1_2.h" 24 #include "merge/packet_extensions.h" 25 #include "merge/generic_reader.h" 26 27 struct mpeg_ps_id_t { 28 int id; 29 int sub_id; 30 31 mpeg_ps_id_t(int n_id = 0, int n_sub_id = 0) idmpeg_ps_id_t32 : id(n_id) 33 , sub_id(n_sub_id) { 34 } 35 idxmpeg_ps_id_t36 inline unsigned int idx() const { 37 return ((id & 0xff) << 8) | (sub_id & 0xff); 38 } 39 }; 40 41 inline std::ostream & 42 operator <<(std::ostream &out, 43 mpeg_ps_id_t const &id) { 44 out << fmt::format("{0:02x}.{1:02x}", id.id, id.sub_id); 45 46 return out; 47 } 48 49 class mpeg_ps_packet_c { 50 public: 51 mpeg_ps_id_t m_id; 52 int64_t m_pts, m_dts; 53 unsigned int m_length, m_full_length; 54 bool m_valid; 55 memory_cptr m_buffer; 56 57 public: 58 mpeg_ps_packet_c(mpeg_ps_id_t id = mpeg_ps_id_t{}) 59 : m_id{id} 60 , m_pts{-1} 61 , m_dts{-1} 62 , m_length{0} 63 , m_full_length{0} 64 , m_valid{false} 65 { 66 } 67 has_pts()68 bool has_pts() const { 69 return -1 != m_pts; 70 } 71 has_dts()72 bool has_dts() const { 73 return -1 != m_dts; 74 } 75 pts()76 int64_t pts() const { 77 return has_pts() ? m_pts : std::numeric_limits<int64_t>::max(); 78 } 79 dts()80 int64_t dts() const { 81 return has_dts() ? m_dts : pts(); 82 } 83 84 operator bool() const { 85 return m_valid; 86 } 87 has_been_read()88 bool has_been_read() const { 89 return m_valid && m_buffer; 90 } 91 }; 92 93 inline std::ostream & 94 operator <<(std::ostream &out, 95 mpeg_ps_packet_c const &p) { 96 out << fmt::format("[ID {0} PTS {1} DTS {2} length {3} full_length {4} valid? {5} read? {6}]", 97 p.m_id, 98 p.has_pts() ? mtx::string::format_timestamp(p.pts()) : "none"s, 99 p.has_dts() ? mtx::string::format_timestamp(p.dts()) : "none"s, 100 p.m_length, p.m_full_length, p.m_valid, 101 p.has_been_read() ? "yes, fully" : p.m_buffer ? "only partially" : "no"); 102 103 return out; 104 } 105 106 struct mpeg_ps_track_t { 107 int ptzr; 108 109 char type; // 'v' for video, 'a' for audio, 's' for subs 110 mpeg_ps_id_t id; 111 int sort_key; 112 codec_c codec; 113 114 bool provide_timestamps; 115 int64_t timestamp_offset, timestamp_b_frame_offset; 116 117 bool v_interlaced; 118 int v_version, v_width, v_height, v_dwidth, v_dheight; 119 mtx_mp_rational_t v_field_duration, v_aspect_ratio; 120 121 int a_channels, a_sample_rate, a_bits_per_sample, a_bsid; 122 mtx::dts::header_t dts_header; 123 124 unsigned char *buffer; 125 unsigned int buffer_usage, buffer_size; 126 127 multiple_timestamps_packet_extension_c *multiple_timestamps_packet_extension; 128 129 unsigned int skip_packet_data_bytes; 130 mpeg_ps_track_tmpeg_ps_track_t131 mpeg_ps_track_t(): 132 ptzr(-1), 133 type(0), 134 sort_key(0), 135 provide_timestamps(false), 136 timestamp_offset(std::numeric_limits<int64_t>::max()), 137 timestamp_b_frame_offset{0}, 138 v_interlaced(false), 139 v_version(0), 140 v_width(0), 141 v_height(0), 142 v_dwidth(0), 143 v_dheight(0), 144 a_channels(0), 145 a_sample_rate(0), 146 a_bits_per_sample(0), 147 a_bsid(0), 148 buffer(nullptr), 149 buffer_usage(0), 150 buffer_size(0), 151 multiple_timestamps_packet_extension(new multiple_timestamps_packet_extension_c) 152 , skip_packet_data_bytes{} 153 { 154 }; 155 use_buffermpeg_ps_track_t156 void use_buffer(size_t size) { 157 safefree(buffer); 158 buffer = (unsigned char *)safemalloc(size); 159 buffer_size = size; 160 buffer_usage = 0; 161 } 162 assert_buffer_sizempeg_ps_track_t163 void assert_buffer_size(size_t size) { 164 if (!buffer) 165 use_buffer(size); 166 else if (size > buffer_size) { 167 buffer = (unsigned char *)saferealloc(buffer, size); 168 buffer_size = size; 169 } 170 } 171 ~mpeg_ps_track_tmpeg_ps_track_t172 ~mpeg_ps_track_t() { 173 safefree(buffer); 174 delete multiple_timestamps_packet_extension; 175 } 176 }; 177 using mpeg_ps_track_ptr = std::shared_ptr<mpeg_ps_track_t>; 178 179 inline bool 180 operator <(mpeg_ps_track_ptr const &a, 181 mpeg_ps_track_ptr const &b) { 182 return a->sort_key < b->sort_key; 183 } 184 185 class mpeg_ps_reader_c: public generic_reader_c { 186 private: 187 int64_t global_timestamp_offset; 188 189 std::map<int, int> id2idx; 190 std::map<int, bool> m_blocked_ids; 191 192 std::map<int, int> es_map; 193 int version{}; 194 bool file_done{}; 195 196 std::vector<mpeg_ps_track_ptr> tracks; 197 std::map<generic_packetizer_c *, mpeg_ps_track_ptr> m_ptzr_to_track_map; 198 199 uint64_t m_probe_range{}; 200 201 debugging_option_c 202 m_debug_timestamps{"mpeg_ps|mpeg_ps_timestamps"} 203 , m_debug_headers{ "mpeg_ps|mpeg_ps_headers"} 204 , m_debug_packets{ "mpeg_ps|mpeg_ps_packets"} 205 , m_debug_resync{ "mpeg_ps|mpeg_ps_resync"}; 206 207 public: get_format_type()208 virtual mtx::file_type_e get_format_type() const { 209 return mtx::file_type_e::mpeg_ps; 210 } 211 212 virtual void read_headers(); 213 virtual void identify(); 214 virtual void create_packetizer(int64_t id); 215 virtual void create_packetizers(); 216 virtual void add_available_track_ids(); 217 218 virtual void found_new_stream(mpeg_ps_id_t id); 219 220 virtual bool read_timestamp(mtx::bits::reader_c &bc, int64_t ×tamp); 221 virtual bool read_timestamp(int c, int64_t ×tamp); 222 virtual mpeg_ps_packet_c parse_packet(mpeg_ps_id_t id, bool read_data = true); 223 virtual bool find_next_packet(mpeg_ps_id_t &id, int64_t max_file_pos = -1); 224 virtual bool find_next_packet_for_id(mpeg_ps_id_t id, int64_t max_file_pos = -1); 225 226 virtual void parse_program_stream_map(); 227 228 virtual bool probe_file() override; 229 230 private: 231 virtual file_status_e read(generic_packetizer_c *packetizer, bool force = false) override; 232 233 virtual void new_stream_v_avc_or_mpeg_1_2(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 234 virtual void new_stream_v_mpeg_1_2(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 235 virtual void new_stream_v_avc(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 236 virtual void new_stream_v_vc1(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 237 virtual void new_stream_a_mpeg(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 238 virtual void new_stream_a_ac3(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 239 virtual void new_stream_a_dts(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 240 virtual void new_stream_a_pcm(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 241 virtual void new_stream_a_truehd(mpeg_ps_id_t id, unsigned char *buf, unsigned int length, mpeg_ps_track_ptr &track); 242 virtual bool resync_stream(uint32_t &header); 243 virtual file_status_e finish(); 244 void sort_tracks(); 245 void calculate_global_timestamp_offset(); 246 }; 247