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 MPEG TS (transport stream) demultiplexer module
10
11 Written by Massimo Callegari <massimocallegari@yahoo.it>
12 and Moritz Bunkus <moritz@bunkus.org>.
13 */
14
15 #include "common/common_pch.h"
16
17 #include <iostream>
18
19 #include "common/at_scope_exit.h"
20 #include "common/avc/es_parser.h"
21 #include "common/bluray/clpi.h"
22 #include "common/bluray/util.h"
23 #include "common/bswap.h"
24 #include "common/chapters/bluray.h"
25 #include "common/checksums/crc.h"
26 #include "common/checksums/base_fwd.h"
27 #include "common/endian.h"
28 #include "common/hdmv_textst.h"
29 #include "common/mp3.h"
30 #include "common/mm_file_io.h"
31 #include "common/mm_mpls_multi_file_io.h"
32 #include "common/ac3.h"
33 #include "common/id_info.h"
34 #include "common/list_utils.h"
35 #include "common/mm_mem_io.h"
36 #include "common/mm_proxy_io.h"
37 #include "common/mm_text_io.h"
38 #include "common/mpeg1_2.h"
39 #include "common/mpeg4_p2.h"
40 #include "common/path.h"
41 #include "common/qt.h"
42 #include "common/strings/formatting.h"
43 #include "input/aac_framing_packet_converter.h"
44 #include "input/bluray_pcm_channel_layout_packet_converter.h"
45 #include "input/dvbsub_pes_framing_removal_packet_converter.h"
46 #include "input/r_mpeg_ts.h"
47 #include "input/teletext_to_srt_packet_converter.h"
48 #include "input/truehd_ac3_splitting_packet_converter.h"
49 #include "merge/cluster_helper.h"
50 #include "merge/output_control.h"
51 #include "output/p_aac.h"
52 #include "output/p_ac3.h"
53 #include "output/p_avc_es.h"
54 #include "output/p_dts.h"
55 #include "output/p_dvbsub.h"
56 #include "output/p_hdmv_pgs.h"
57 #include "output/p_hdmv_textst.h"
58 #include "output/p_hevc_es.h"
59 #include "output/p_mp3.h"
60 #include "output/p_mpeg1_2.h"
61 #include "output/p_pcm.h"
62 #include "output/p_textsubs.h"
63 #include "output/p_truehd.h"
64 #include "output/p_vc1.h"
65
66 // This is ISO/IEC 13818-1.
67
68 namespace mtx::mpeg_ts {
69
70 constexpr auto TS_PACKET_SIZE = 188;
71 constexpr auto TS_MAX_PACKET_SIZE = 204;
72
73 constexpr auto TS_PAT_PID = 0x0000;
74 constexpr auto TS_SDT_PID = 0x0011;
75
76 constexpr auto TS_SDT_TID = 0x42;
77
78 int reader_c::potential_packet_sizes[] = { 188, 192, 204, 0 };
79
80 // ------------------------------------------------------------
81
track_c(reader_c & p_reader,pid_type_e p_type)82 track_c::track_c(reader_c &p_reader,
83 pid_type_e p_type)
84 : reader{p_reader}
85 , m_file_num{p_reader.m_current_file}
86 , m_id{}
87 , processed{}
88 , type{p_type}
89 , pid{}
90 , program_number{}
91 , pes_payload_size_to_read{}
92 , pes_payload_read{new mtx::bytes::buffer_c}
93 , probed_ok{}
94 , ptzr{-1}
95 , m_timestamp_wrap_add{timestamp_c::ns(0)}
96 , m_subtitle_timestamp_correction{timestamp_c::ns(0)}
97 , v_interlaced{}
98 , v_version{}
99 , v_width{}
100 , v_height{}
101 , v_dwidth{}
102 , v_dheight{}
103 , a_channels{}
104 , a_sample_rate{}
105 , a_bits_per_sample{}
106 , a_bsid{}
107 , m_aac_multiplex_type{aac::parser_c::unknown_multiplex}
108 , m_apply_dts_timestamp_fix{}
109 , m_use_dts{}
110 , m_timestamps_wrapped{}
111 , m_truehd_found_truehd{}
112 , m_truehd_found_ac3{}
113 , m_master{}
114 , skip_packet_data_bytes{}
115 , m_debug_delivery{}
116 , m_debug_timestamp_wrapping{}
117 , m_debug_headers{"mpeg_ts|mpeg_ts_headers"}
118 {
119 }
120
121 void
process(packet_cptr const & packet)122 track_c::process(packet_cptr const &packet) {
123 if (!converter || !converter->convert(packet))
124 reader.m_reader_packetizers[ptzr]->process(packet);
125 }
126
127 void
send_to_packetizer()128 track_c::send_to_packetizer() {
129 auto &f = reader.file();
130 auto timestamp_to_use = !m_timestamp.valid() ? timestamp_c{}
131 : reader.m_dont_use_audio_pts && (pid_type_e::audio == type) ? timestamp_c{}
132 : m_apply_dts_timestamp_fix && (m_previous_timestamp == m_timestamp) ? timestamp_c{}
133 : std::max(m_timestamp, f.m_global_timestamp_offset);
134
135 auto timestamp_to_check = f.m_stream_timestamp.valid() ? f.m_stream_timestamp : timestamp_c::ns(0);
136 auto const &min = f.m_timestamp_restriction_min;
137 auto const &max = f.m_timestamp_restriction_max;
138 auto use_packet = ptzr != -1;
139 auto bytes_to_skip = std::min<size_t>(pes_payload_read->get_size(), skip_packet_data_bytes);
140
141 if ( (min.valid() && (timestamp_to_check < min) && !f.m_timestamp_restriction_min_seen)
142 || (max.valid() && (timestamp_to_check >= max)))
143 use_packet = false;
144
145 if (use_packet && !f.m_timestamp_restriction_min_seen && min.valid())
146 f.m_timestamp_restriction_min_seen = true;
147
148 if (timestamp_to_use.valid() && f.m_global_timestamp_offset.valid())
149 timestamp_to_use -= std::min(timestamp_to_use, f.m_global_timestamp_offset);
150
151 mxdebug_if(m_debug_delivery,
152 fmt::format("send_to_packetizer: PID {0} expected {1} actual {2} timestamp_to_use {3} timestamp_to_check {4} m_timestamp {5} m_previous_timestamp {6} stream_timestamp {7} restriction {8}/{9} min_seen {10} ptzr {11} use? {12}\n",
153 pid, pes_payload_size_to_read, pes_payload_read->get_size() - bytes_to_skip, timestamp_to_use, timestamp_to_check, m_timestamp, m_previous_timestamp, f.m_stream_timestamp, min, max, f.m_timestamp_restriction_min_seen, ptzr, use_packet));
154
155 if (use_packet) {
156 process(std::make_shared<packet_t>(memory_c::clone(pes_payload_read->get_buffer() + bytes_to_skip, pes_payload_read->get_size() - bytes_to_skip), timestamp_to_use.to_ns(-1)));
157
158 f.m_packet_sent_to_packetizer = true;
159 }
160
161 clear_pes_payload();
162 processed = false;
163 m_previous_timestamp = m_timestamp;
164 m_timestamp.reset();
165 }
166
167 bool
is_pes_payload_complete() const168 track_c::is_pes_payload_complete()
169 const {
170 return !is_pes_payload_size_unbounded()
171 && pes_payload_size_to_read
172 && !remaining_payload_size_to_read();
173 }
174
175 bool
is_pes_payload_size_unbounded() const176 track_c::is_pes_payload_size_unbounded()
177 const {
178 return pes_payload_size_to_read == offsetof(pes_header_t, flags1);
179 }
180
181 void
add_pes_payload(unsigned char * ts_payload,size_t ts_payload_size)182 track_c::add_pes_payload(unsigned char *ts_payload,
183 size_t ts_payload_size) {
184 auto to_add = is_pes_payload_size_unbounded() ? ts_payload_size : std::min(ts_payload_size, remaining_payload_size_to_read());
185
186 if (to_add)
187 pes_payload_read->add(ts_payload, to_add);
188 }
189
190 void
add_pes_payload_to_probe_data()191 track_c::add_pes_payload_to_probe_data() {
192 if (!m_probe_data)
193 m_probe_data = mtx::bytes::buffer_cptr(new mtx::bytes::buffer_c);
194 m_probe_data->add(pes_payload_read->get_buffer(), pes_payload_read->get_size());
195 }
196
197 void
clear_pes_payload()198 track_c::clear_pes_payload() {
199 pes_payload_read->clear();
200 pes_payload_size_to_read = 0;
201 }
202
203 int
new_stream_v_mpeg_1_2(bool end_of_detection)204 track_c::new_stream_v_mpeg_1_2(bool end_of_detection) {
205 if (!m_m2v_parser) {
206 m_m2v_parser = std::shared_ptr<M2VParser>(new M2VParser);
207 m_m2v_parser->SetProbeMode();
208 m_m2v_parser->SetThrowOnError(true);
209 }
210
211 m_m2v_parser->WriteData(pes_payload_read->get_buffer(), pes_payload_read->get_size());
212 if (end_of_detection)
213 m_m2v_parser->SetEOS();
214
215 int state = m_m2v_parser->GetState();
216 if (state != MPV_PARSER_STATE_FRAME) {
217 mxdebug_if(m_debug_headers, fmt::format("new_stream_v_mpeg_1_2: no valid frame in {0} bytes\n", pes_payload_read->get_size()));
218 return FILE_STATUS_MOREDATA;
219 }
220
221 MPEG2SequenceHeader seq_hdr = m_m2v_parser->GetSequenceHeader();
222 std::shared_ptr<MPEGFrame> frame(m_m2v_parser->ReadFrame());
223 if (!frame)
224 return FILE_STATUS_MOREDATA;
225
226 codec = codec_c::look_up(codec_c::type_e::V_MPEG12);
227 v_interlaced = !seq_hdr.progressiveSequence;
228 v_version = m_m2v_parser->GetMPEGVersion();
229 v_width = seq_hdr.width;
230 v_height = seq_hdr.height;
231 v_aspect_ratio = seq_hdr.aspectRatio;
232
233 m_default_duration = 1'000'000'000 / seq_hdr.frameRate;
234
235 if ((0 >= v_aspect_ratio) || (1 == v_aspect_ratio))
236 v_dwidth = v_width;
237 else
238 v_dwidth = mtx::to_int_rounded(v_height * v_aspect_ratio);
239 v_dheight = v_height;
240
241 mxdebug_if(m_debug_headers, fmt::format("new_stream_v_mpeg_1_2: width: {0}, height: {1}\n", v_width, v_height));
242 if (v_width == 0 || v_height == 0)
243 return FILE_STATUS_MOREDATA;
244
245 return 0;
246 }
247
248 int
new_stream_v_avc(bool end_of_detection)249 track_c::new_stream_v_avc(bool end_of_detection) {
250 if (!m_avc_parser)
251 m_avc_parser = std::make_shared<mtx::avc::es_parser_c>();
252
253 mxdebug_if(m_debug_headers, fmt::format("new_stream_v_avc: packet size: {0}\n", pes_payload_read->get_size()));
254
255 m_avc_parser->add_bytes(pes_payload_read->get_buffer(), pes_payload_read->get_size());
256 if (end_of_detection)
257 m_avc_parser->flush();
258
259 if (!m_avc_parser->headers_parsed())
260 return FILE_STATUS_MOREDATA;
261
262 codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P10);
263 v_width = m_avc_parser->get_width();
264 v_height = m_avc_parser->get_height();
265
266 if (m_avc_parser->has_par_been_found()) {
267 auto dimensions = m_avc_parser->get_display_dimensions();
268 v_dwidth = dimensions.first;
269 v_dheight = dimensions.second;
270 }
271
272 return 0;
273 }
274
275 int
new_stream_v_hevc(bool end_of_detection)276 track_c::new_stream_v_hevc(bool end_of_detection) {
277 if (!m_hevc_parser)
278 m_hevc_parser = std::make_shared<mtx::hevc::es_parser_c>();
279
280 m_hevc_parser->add_bytes(pes_payload_read->get_buffer(), pes_payload_read->get_size());
281 if (end_of_detection)
282 m_hevc_parser->flush();
283
284 if (!m_hevc_parser->headers_parsed())
285 return FILE_STATUS_MOREDATA;
286
287 codec = codec_c::look_up(codec_c::type_e::V_MPEGH_P2);
288 v_width = m_hevc_parser->get_width();
289 v_height = m_hevc_parser->get_height();
290
291 if (m_hevc_parser->has_par_been_found()) {
292 auto dimensions = m_hevc_parser->get_display_dimensions();
293 v_dwidth = dimensions.first;
294 v_dheight = dimensions.second;
295 }
296
297 return 0;
298 }
299
300 int
new_stream_v_vc1()301 track_c::new_stream_v_vc1() {
302 if (!m_vc1_parser)
303 m_vc1_parser = std::make_shared<mtx::vc1::es_parser_c>();
304
305 m_vc1_parser->add_bytes(pes_payload_read->get_buffer(), pes_payload_read->get_size());
306
307 if (!m_vc1_parser->is_sequence_header_available())
308 return FILE_STATUS_MOREDATA;
309
310 auto seqhdr = mtx::vc1::sequence_header_t{};
311 m_vc1_parser->get_sequence_header(seqhdr);
312
313 v_width = seqhdr.pixel_width;
314 v_height = seqhdr.pixel_height;
315
316 return 0;
317 }
318
319 int
new_stream_a_mpeg()320 track_c::new_stream_a_mpeg() {
321 add_pes_payload_to_probe_data();
322
323 mp3_header_t header;
324
325 int offset = find_mp3_header(m_probe_data->get_buffer(), m_probe_data->get_size());
326 if (-1 == offset)
327 return FILE_STATUS_MOREDATA;
328
329 decode_mp3_header(m_probe_data->get_buffer() + offset, &header);
330 a_channels = header.channels;
331 a_sample_rate = header.sampling_frequency;
332 codec = header.get_codec();
333
334 mxdebug_if(m_debug_headers, fmt::format("new_stream_a_mpeg: Channels: {0}, sample rate: {1}\n",a_channels, a_sample_rate));
335 return 0;
336 }
337
338 int
new_stream_a_aac()339 track_c::new_stream_a_aac() {
340 add_pes_payload_to_probe_data();
341
342 auto pos = aac::parser_c::find_consecutive_frames(m_probe_data->get_buffer(), m_probe_data->get_size(), 5);
343 if (pos == -1)
344 return FILE_STATUS_MOREDATA;
345
346 auto parser = aac::parser_c{};
347 parser.add_bytes(m_probe_data->get_buffer() + pos, m_probe_data->get_size() - pos);
348 if (!parser.frames_available() || !parser.headers_parsed())
349 return FILE_STATUS_MOREDATA;
350
351 m_aac_frame = parser.get_frame();
352 m_aac_multiplex_type = parser.get_multiplex_type();
353 a_channels = m_aac_frame.m_header.config.channels;
354 a_sample_rate = m_aac_frame.m_header.config.sample_rate;
355
356 mxdebug_if(reader.m_debug_aac,
357 fmt::format("new_stream_a_aac: found headers at {0} multiplex type {1} first header: {2}\n",
358 pos, aac::parser_c::get_multiplex_type_name(m_aac_multiplex_type), m_aac_frame.to_string()));
359
360 return 0;
361 }
362
363 int
new_stream_a_ac3()364 track_c::new_stream_a_ac3() {
365 add_pes_payload_to_probe_data();
366
367 ac3::parser_c parser;
368 parser.add_bytes(m_probe_data->get_buffer(), m_probe_data->get_size());
369 if (!parser.frame_available())
370 return FILE_STATUS_MOREDATA;
371
372 ac3::frame_c header = parser.get_frame();
373
374 mxdebug_if(m_debug_headers,
375 fmt::format("new_stream_a_ac3: first ac3 header bsid {0} channels {1} sample_rate {2} bytes {3} samples {4}\n",
376 header.m_bs_id, header.m_channels, header.m_sample_rate, header.m_bytes, header.m_samples));
377
378 a_channels = header.m_channels;
379 a_sample_rate = header.m_sample_rate;
380 a_bsid = header.m_bs_id;
381 codec = header.get_codec();
382
383 return 0;
384 }
385
386 int
new_stream_a_dts()387 track_c::new_stream_a_dts() {
388 add_pes_payload_to_probe_data();
389
390 if (-1 == mtx::dts::find_header(m_probe_data->get_buffer(), m_probe_data->get_size(), a_dts_header))
391 return FILE_STATUS_MOREDATA;
392
393 m_apply_dts_timestamp_fix = true;
394 a_channels = a_dts_header.get_total_num_audio_channels();
395 a_sample_rate = a_dts_header.get_effective_sampling_frequency();
396
397 codec.set_specialization(a_dts_header.get_codec_specialization());
398
399 return 0;
400 }
401
402 int
new_stream_a_pcm()403 track_c::new_stream_a_pcm() {
404 static uint8_t const s_bits_per_samples[4] = { 0, 16, 20, 24 };
405 static uint8_t const s_channels[16] = { 0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0 };
406
407 add_pes_payload_to_probe_data();
408
409 if (4 > m_probe_data->get_size())
410 return FILE_STATUS_MOREDATA;
411
412 skip_packet_data_bytes = 4;
413 auto buffer = m_probe_data->get_buffer();
414 a_channels = s_channels[ buffer[2] >> 4 ];
415 a_bits_per_sample = s_bits_per_samples[ buffer[3] >> 6 ];
416 auto sample_rate_idx = buffer[2] & 0x0f;
417 a_sample_rate = sample_rate_idx == 1 ? 48000
418 : sample_rate_idx == 4 ? 96000
419 : sample_rate_idx == 5 ? 192000
420 : 0;
421
422 mxdebug_if(m_debug_headers,
423 fmt::format("new_stream_a_pcm: header: 0x{0:08x} channels: {1}, sample rate: {2}, bits per channel: {3}\n",
424 get_uint32_be(buffer), a_channels, a_sample_rate, a_bits_per_sample));
425
426 if ((a_sample_rate == 0) || !mtx::included_in(a_bits_per_sample, 16, 24))
427 return FILE_STATUS_DONE;
428
429 converter = std::make_shared<bluray_pcm_channel_layout_packet_converter_c>(a_bits_per_sample / 8, a_channels + 1, a_channels);
430
431 return 0;
432 }
433
434 int
new_stream_a_truehd()435 track_c::new_stream_a_truehd() {
436 if (!m_truehd_parser)
437 m_truehd_parser.reset(new mtx::truehd::parser_c);
438
439 m_truehd_parser->add_data(pes_payload_read->get_buffer(), pes_payload_read->get_size());
440 clear_pes_payload();
441
442 while (m_truehd_parser->frame_available() && (!m_truehd_found_truehd || !m_truehd_found_ac3)) {
443 auto frame = m_truehd_parser->get_next_frame();
444
445 if (frame->is_ac3()) {
446 if (!m_truehd_found_ac3) {
447 m_truehd_found_ac3 = true;
448 auto &header = frame->m_ac3_header;
449
450 mxdebug_if(m_debug_headers,
451 fmt::format("new_stream_a_truehd: first AC-3 header bsid {0} channels {1} sample_rate {2} bytes {3} samples {4}\n",
452 header.m_bs_id, header.m_channels, header.m_sample_rate, header.m_bytes, header.m_samples));
453
454 auto &coupled_track = *m_coupled_tracks[0];
455 coupled_track.a_channels = header.m_channels;
456 coupled_track.a_sample_rate = header.m_sample_rate;
457 coupled_track.a_bsid = header.m_bs_id;
458 coupled_track.probed_ok = true;
459 }
460
461 continue;
462
463 }
464
465 if (!frame->is_sync())
466 continue;
467
468 mxdebug_if(m_debug_headers,
469 fmt::format("new_stream_a_truehd: first TrueHD header channels {0} sampling_rate {1} samples_per_frame {2}\n",
470 frame->m_channels, frame->m_sampling_rate, frame->m_samples_per_frame));
471
472 codec = frame->codec();
473 a_channels = frame->m_channels;
474 a_sample_rate = frame->m_sampling_rate;
475 m_truehd_found_truehd = true;
476 }
477
478 return m_truehd_found_truehd && m_truehd_found_ac3 ? 0 : FILE_STATUS_MOREDATA;
479 }
480
481 int
new_stream_s_hdmv_textst()482 track_c::new_stream_s_hdmv_textst() {
483 add_pes_payload_to_probe_data();
484
485 // CodecPrivate for TextST consists solely of the "dialog style segment" element:
486 // segment descriptor:
487 // 1 byte segment type (0x81 == dialog style segment)
488 // 2 bytes segment size (Big Endian)
489 // x bytes dialog style segment data
490
491 if (!m_probe_data || (m_probe_data->get_size() < 3))
492 return FILE_STATUS_MOREDATA;
493
494 auto buf = m_probe_data->get_buffer();
495 if (static_cast<mtx::hdmv_textst::segment_type_e>(buf[0]) != mtx::hdmv_textst::dialog_style_segment)
496 return FILE_STATUS_DONE;
497
498 auto dialog_segment_size = get_uint16_be(&buf[1]);
499 if ((dialog_segment_size + 3u) > m_probe_data->get_size())
500 return FILE_STATUS_MOREDATA;
501
502 m_codec_private_data = memory_c::clone(buf, dialog_segment_size + 3);
503
504 return 0;
505 }
506
507 int
new_stream_s_dvbsub()508 track_c::new_stream_s_dvbsub() {
509 if (!m_codec_private_data || (5 != m_codec_private_data->get_size()))
510 return FILE_STATUS_DONE;
511
512 return 0;
513 }
514
515 bool
has_packetizer() const516 track_c::has_packetizer()
517 const {
518 return -1 != ptzr;
519 }
520
521 void
set_pid(uint16_t new_pid)522 track_c::set_pid(uint16_t new_pid) {
523 pid = new_pid;
524
525 std::string arg;
526 m_debug_delivery = debugging_c::requested("mpeg_ts")
527 || ( debugging_c::requested("mpeg_ts_delivery", &arg)
528 && (arg.empty() || (arg == fmt::to_string(pid))));
529
530 m_debug_timestamp_wrapping = debugging_c::requested("mpeg_ts")
531 || ( debugging_c::requested("mpeg_ts_timestamp_wrapping", &arg)
532 && (arg.empty() || (arg == fmt::to_string(pid))));
533 }
534
535 bool
detect_timestamp_wrap(timestamp_c const & timestamp) const536 track_c::detect_timestamp_wrap(timestamp_c const ×tamp)
537 const {
538 static auto const s_wrap_limit = timestamp_c::mpeg(1 << 30);
539
540 if ( !timestamp.valid()
541 || !m_previous_valid_timestamp.valid()
542 || ((timestamp - m_previous_valid_timestamp).abs() < s_wrap_limit))
543 return false;
544 return true;
545 }
546
547 void
adjust_timestamp_for_wrap(timestamp_c & timestamp)548 track_c::adjust_timestamp_for_wrap(timestamp_c ×tamp) {
549 static auto const s_wrap_limit = timestamp_c::mpeg(1ll << 30);
550 static auto const s_bad_limit = timestamp_c::m(5);
551
552 if (!timestamp.valid())
553 return;
554
555 if (timestamp < s_wrap_limit)
556 timestamp += m_timestamp_wrap_add;
557
558 // For subtitle tracks only detect jumps backwards in time, not
559 // forward. Subtitles often have holes larger than five minutes
560 // between the entries.
561 if ( ((timestamp < m_previous_valid_timestamp) || (pid_type_e::subtitles != type))
562 && ((timestamp - m_previous_valid_timestamp).abs() >= s_bad_limit))
563 timestamp = timestamp_c{};
564 }
565
566 void
handle_timestamp_wrap(timestamp_c & pts,timestamp_c & dts)567 track_c::handle_timestamp_wrap(timestamp_c &pts,
568 timestamp_c &dts) {
569 static auto const s_wrap_add = timestamp_c::mpeg(1ll << 33);
570 static auto const s_wrap_limit = timestamp_c::mpeg(1ll << 30);
571 static auto const s_reset_limit = timestamp_c::h(1);
572
573 if (!m_timestamps_wrapped) {
574 m_timestamps_wrapped = detect_timestamp_wrap(pts) || detect_timestamp_wrap(dts);
575 if (m_timestamps_wrapped) {
576 m_timestamp_wrap_add += s_wrap_add;
577 mxdebug_if(m_debug_timestamp_wrapping,
578 fmt::format("handle_timestamp_wrap: Timestamp wrapping detected for PID {0} pts {1} dts {2} previous_valid {3} global_offset {4} new wrap_add {5}\n",
579 pid, pts, dts, m_previous_valid_timestamp, reader.file().m_global_timestamp_offset, m_timestamp_wrap_add));
580
581 }
582
583 } else if (pts.valid() && (pts < s_wrap_limit) && (pts > s_reset_limit)) {
584 m_timestamps_wrapped = false;
585 mxdebug_if(m_debug_timestamp_wrapping,
586 fmt::format("handle_timestamp_wrap: Timestamp wrapping reset for PID {0} pts {1} dts {2} previous_valid {3} global_offset {4} current wrap_add {5}\n",
587 pid, pts, dts, m_previous_valid_timestamp, reader.file().m_global_timestamp_offset, m_timestamp_wrap_add));
588 }
589
590 adjust_timestamp_for_wrap(pts);
591 adjust_timestamp_for_wrap(dts);
592
593 // mxinfo(fmt::format("pid {4} PTS before {0} now {1} wrapped {2} reset prevvalid {3} diff {5}\n", before, pts, m_timestamps_wrapped, m_previous_valid_timestamp, pid, pts - m_previous_valid_timestamp));
594 }
595
596 drop_decision_e
handle_bogus_subtitle_timestamps(timestamp_c & pts,timestamp_c & dts)597 track_c::handle_bogus_subtitle_timestamps(timestamp_c &pts,
598 timestamp_c &dts) {
599 auto &f = reader.file();
600
601 if (processing_state_e::muxing != f.m_state)
602 return drop_decision_e::keep;
603
604 // Sometimes the subtitle timestamps aren't valid, they can be off
605 // from the audio/video timestamps by hours. In such a case replace
606 // the subtitle's timestamps with last valid one from audio/video
607 // packets.
608 if ( mtx::included_in(type, pid_type_e::audio, pid_type_e::video)
609 && pts.valid()) {
610 f.m_last_non_subtitle_pts = pts;
611 f.m_last_non_subtitle_dts = dts;
612 return drop_decision_e::keep;
613
614 }
615
616 if (pid_type_e::subtitles != type)
617 return drop_decision_e::keep;
618
619 // PGS subtitles often have their "stop displaying" segments located
620 // right after the "display stuff" segments. In that case their PTS
621 // will differ from the surrounding audio/video PTS
622 // considerably. That's fine, though. No correction must take in
623 // such a case.
624 if (codec.is(codec_c::type_e::S_HDMV_PGS))
625 return drop_decision_e::keep;
626
627 if (pts.valid())
628 pts += m_subtitle_timestamp_correction;
629 if (dts.valid())
630 dts += m_subtitle_timestamp_correction;
631
632 if (!f.m_last_non_subtitle_pts.valid())
633 return f.m_has_audio_or_video_track ? drop_decision_e::drop : drop_decision_e::keep;
634
635 if ( !pts.valid()
636 || ((pts - f.m_last_non_subtitle_pts).abs() >= timestamp_c::s(5))) {
637 auto additional_correction = f.m_last_non_subtitle_pts - pts;
638 m_subtitle_timestamp_correction += additional_correction;
639 pts = f.m_last_non_subtitle_pts;
640 dts = f.m_last_non_subtitle_dts;
641
642 mxdebug_if(m_debug_timestamp_wrapping, fmt::format("additional subtitle correction {0} total {1}\n", additional_correction, m_subtitle_timestamp_correction));
643 }
644
645 return drop_decision_e::keep;
646 }
647
648 bool
parse_ac3_pmt_descriptor(pmt_descriptor_t const &,pmt_pid_info_t const & pmt_pid_info)649 track_c::parse_ac3_pmt_descriptor(pmt_descriptor_t const &,
650 pmt_pid_info_t const &pmt_pid_info) {
651 if (pmt_pid_info.stream_type != stream_type_e::iso_13818_pes_private)
652 return false;
653
654 type = pid_type_e::audio;
655 codec = codec_c::look_up(codec_c::type_e::A_AC3);
656
657 return true;
658 }
659
660 bool
parse_dts_pmt_descriptor(pmt_descriptor_t const &,pmt_pid_info_t const & pmt_pid_info)661 track_c::parse_dts_pmt_descriptor(pmt_descriptor_t const &,
662 pmt_pid_info_t const &pmt_pid_info) {
663 if (pmt_pid_info.stream_type != stream_type_e::iso_13818_pes_private)
664 return false;
665
666 type = pid_type_e::audio;
667 codec = codec_c::look_up(codec_c::type_e::A_DTS);
668
669 return true;
670 }
671
672 bool
parse_srt_pmt_descriptor(pmt_descriptor_t const & pmt_descriptor,pmt_pid_info_t const & pmt_pid_info)673 track_c::parse_srt_pmt_descriptor(pmt_descriptor_t const &pmt_descriptor,
674 pmt_pid_info_t const &pmt_pid_info) {
675 if (pmt_pid_info.stream_type != stream_type_e::iso_13818_pes_private)
676 return false;
677
678 auto buffer = reinterpret_cast<unsigned char const *>(&pmt_descriptor + 1);
679 auto num_entries = static_cast<unsigned int>(pmt_descriptor.length) / 5;
680 mxdebug_if(reader.m_debug_pat_pmt, fmt::format("parse_srt_pmt_descriptor: Teletext PMT descriptor, {0} entries\n", num_entries));
681 for (auto idx = 0u; idx < num_entries; ++idx) {
682 // Bits:
683 // 0–23: ISO 639 language code
684 // 24–28: teletext type
685 // 29-31: teletext magazine number
686 // 32-35: teletext page number (units)
687 // 36-39: teletext page number (tens)
688
689 // Teletext type is:
690 // 0: ?
691 // 1: teletext
692 // 2: teletext subtitles
693 // 3: teletext additional information
694 // 4: teletext program schedule
695 // 5: teletext subtitles: hearing impaired
696
697 mtx::bits::reader_c r{buffer, 5};
698
699 r.skip_bits(24);
700 auto ttx_type = r.get_bits(5);
701 auto ttx_magazine = r.get_bits(3);
702 auto ttx_page = r.get_bits(4) * 10 + r.get_bits(4);
703 ttx_page = (ttx_magazine ? ttx_magazine : 8) * 100 + ttx_page;
704
705 if (reader.m_debug_pat_pmt) {
706 mxdebug(fmt::format(" {0}: language {1} type {2} magazine {3} page {4}\n",
707 idx, std::string(reinterpret_cast<char const *>(buffer), 3), ttx_type, ttx_magazine, ttx_page));
708 }
709
710 if (!mtx::included_in(ttx_type, 2u, 5u)) {
711 buffer += 5;
712 continue;
713 }
714
715 track_c *to_set_up{};
716
717 if (!m_ttx_wanted_page) {
718 converter.reset(new teletext_to_srt_packet_converter_c{});
719 to_set_up = this;
720
721 } else {
722 auto new_track = std::make_shared<track_c>(reader);
723 new_track->m_master = this;
724 m_coupled_tracks.emplace_back(new_track);
725
726 to_set_up = new_track.get();
727 to_set_up->converter = converter;
728 to_set_up->set_pid(pid);
729 }
730
731 to_set_up->parse_iso639_language_from(buffer);
732 to_set_up->m_ttx_wanted_page = ttx_page;
733
734 to_set_up->type = pid_type_e::subtitles;
735 to_set_up->codec = codec_c::look_up(codec_c::type_e::S_SRT);
736 to_set_up->probed_ok = true;
737
738 buffer += 5;
739 }
740
741 return true;
742 }
743
744 bool
parse_registration_pmt_descriptor(pmt_descriptor_t const & pmt_descriptor,pmt_pid_info_t const & pmt_pid_info)745 track_c::parse_registration_pmt_descriptor(pmt_descriptor_t const &pmt_descriptor,
746 pmt_pid_info_t const &pmt_pid_info) {
747 if (pmt_pid_info.stream_type != stream_type_e::iso_13818_pes_private)
748 return false;
749
750 if (pmt_descriptor.length < 4)
751 return false;
752
753 auto fourcc = fourcc_c{reinterpret_cast<unsigned char const *>(&pmt_descriptor + 1)};
754 auto reg_codec = codec_c::look_up(fourcc.str());
755
756 mxdebug_if(reader.m_debug_pat_pmt, fmt::format("parse_registration_pmt_descriptor: Registration descriptor with FourCC: {0} codec: {1}\n", fourcc.description(), reg_codec));
757
758 if (!reg_codec.valid())
759 return false;
760
761 switch (reg_codec.get_track_type()) {
762 case track_audio: type = pid_type_e::audio; break;
763 case track_video: type = pid_type_e::video; break;
764 case track_subtitle: type = pid_type_e::subtitles; break;
765 default:
766 return false;
767 }
768
769 codec = reg_codec;
770
771 return true;
772 }
773
774 bool
parse_subtitling_pmt_descriptor(pmt_descriptor_t const & pmt_descriptor,pmt_pid_info_t const & pmt_pid_info)775 track_c::parse_subtitling_pmt_descriptor(pmt_descriptor_t const &pmt_descriptor,
776 pmt_pid_info_t const &pmt_pid_info) {
777 // Bits:
778 // 24: ISO 639 language code
779 // 8: subtitling type
780 // 16: composition page ID
781 // 16: ancillary page ID
782
783 if ( (pmt_pid_info.stream_type != stream_type_e::iso_13818_pes_private)
784 || (pmt_descriptor.length < 8))
785 return false;
786
787 type = pid_type_e::subtitles;
788 codec = codec_c::look_up(codec_c::type_e::S_DVBSUB);
789 m_codec_private_data = memory_c::alloc(5);
790 auto codec_private = m_codec_private_data->get_buffer();
791 auto descriptor = reinterpret_cast<unsigned char const *>(&pmt_descriptor + 1);
792
793 parse_iso639_language_from(descriptor);
794
795 put_uint16_be(&codec_private[0], get_uint16_be(&descriptor[4])); // composition page ID
796 put_uint16_be(&codec_private[2], get_uint16_be(&descriptor[6])); // ancillary page ID
797 codec_private[4] = descriptor[3]; // subtitling type
798
799 return true;
800 }
801
802 void
parse_iso639_language_from(void const * buffer)803 track_c::parse_iso639_language_from(void const *buffer) {
804 auto value = std::string{ reinterpret_cast<char const *>(buffer), 3 };
805 auto parsed_language = mtx::bcp47::language_c::parse(value);
806
807 if (parsed_language.has_valid_iso639_code())
808 language = parsed_language;
809 }
810
811 std::size_t
remaining_payload_size_to_read() const812 track_c::remaining_payload_size_to_read()
813 const {
814 return pes_payload_size_to_read - std::min(pes_payload_size_to_read, pes_payload_read->get_size());
815 }
816
817 timestamp_c
derive_pts_from_content()818 track_c::derive_pts_from_content() {
819 if (codec.is(codec_c::type_e::S_HDMV_TEXTST))
820 return derive_hdmv_textst_pts_from_content();
821
822 return {};
823 }
824
825 timestamp_c
derive_hdmv_textst_pts_from_content()826 track_c::derive_hdmv_textst_pts_from_content() {
827 if (pes_payload_read->get_size() < 8)
828 return {};
829
830 auto &file = reader.m_files[m_file_num];
831 auto buf = pes_payload_read->get_buffer();
832
833 if (static_cast<mtx::hdmv_textst::segment_type_e>(buf[0]) != mtx::hdmv_textst::dialog_presentation_segment)
834 return file->m_timestamp_mpls_sync;
835
836 auto stream_timestamp = timestamp_c::mpeg((static_cast<int64_t>(buf[3] & 1) << 32) | get_uint32_be(&buf[4]));
837 auto diff = file->m_timestamp_mpls_sync.value_or_zero() - reader.m_files[0]->m_timestamp_restriction_min.value_or_zero();
838 auto timestamp = stream_timestamp + diff;
839
840 return timestamp;
841 }
842
843 void
determine_codec_from_stream_type(stream_type_e stream_type)844 track_c::determine_codec_from_stream_type(stream_type_e stream_type) {
845 switch (stream_type) {
846 case stream_type_e::iso_11172_video:
847 case stream_type_e::iso_13818_video:
848 type = pid_type_e::video;
849 codec = codec_c::look_up(codec_c::type_e::V_MPEG12);
850 break;
851 case stream_type_e::iso_14496_part2_video:
852 type = pid_type_e::video;
853 codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P2);
854 break;
855 case stream_type_e::iso_14496_part10_video:
856 type = pid_type_e::video;
857 codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P10);
858 break;
859 case stream_type_e::iso_23008_part2_video:
860 type = pid_type_e::video;
861 codec = codec_c::look_up(codec_c::type_e::V_MPEGH_P2);
862 break;
863 case stream_type_e::stream_video_vc1:
864 type = pid_type_e::video;
865 codec = codec_c::look_up(codec_c::type_e::V_VC1);
866 break;
867 case stream_type_e::iso_11172_audio:
868 case stream_type_e::iso_13818_audio:
869 type = pid_type_e::audio;
870 codec = codec_c::look_up(codec_c::type_e::A_MP3);
871 break;
872 case stream_type_e::iso_13818_part7_audio:
873 case stream_type_e::iso_14496_part3_audio:
874 type = pid_type_e::audio;
875 codec = codec_c::look_up(codec_c::type_e::A_AAC);
876 break;
877 case stream_type_e::stream_audio_pcm:
878 type = pid_type_e::audio;
879 codec = codec_c::look_up(codec_c::type_e::A_PCM);
880 break;
881
882 case stream_type_e::stream_audio_ac3_lossless: {
883 auto ac3_track = std::make_shared<track_c>(*this);
884 ac3_track->type = pid_type_e::audio;
885 ac3_track->codec = codec_c::look_up(codec_c::type_e::A_AC3);
886 ac3_track->converter = std::make_shared<truehd_ac3_splitting_packet_converter_c>();
887 ac3_track->m_master = this;
888 ac3_track->set_pid(pid);
889
890 type = pid_type_e::audio;
891 codec = codec_c::look_up(codec_c::type_e::A_TRUEHD);
892 converter = ac3_track->converter;
893 m_coupled_tracks.push_back(ac3_track);
894
895 break;
896 }
897
898 case stream_type_e::stream_audio_ac3:
899 case stream_type_e::stream_audio_eac3: // E-AC-3
900 case stream_type_e::stream_audio_eac3_2: // E-AC-3 secondary stream
901 case stream_type_e::stream_audio_eac3_atsc: // E-AC-3 as defined in ATSC A/52:2012 Annex G
902 type = pid_type_e::audio;
903 codec = codec_c::look_up(codec_c::type_e::A_AC3);
904 break;
905 case stream_type_e::stream_audio_dts:
906 case stream_type_e::stream_audio_dts_hd:
907 case stream_type_e::stream_audio_dts_hd_ma:
908 case stream_type_e::stream_audio_dts_hd2:
909 type = pid_type_e::audio;
910 codec = codec_c::look_up(codec_c::type_e::A_DTS);
911 break;
912 case stream_type_e::stream_subtitles_hdmv_pgs:
913 type = pid_type_e::subtitles;
914 codec = codec_c::look_up(codec_c::type_e::S_HDMV_PGS);
915 probed_ok = true;
916 break;
917 case stream_type_e::stream_subtitles_hdmv_textst:
918 type = pid_type_e::subtitles;
919 codec = codec_c::look_up(codec_c::type_e::S_HDMV_TEXTST);
920 break;
921 case stream_type_e::iso_13818_pes_private:
922 break;
923 default:
924 mxdebug_if(reader.m_debug_pat_pmt, fmt::format("parse_pmt: Unknown stream type: {0}\n", static_cast<int>(stream_type)));
925 type = pid_type_e::unknown;
926 break;
927 }
928 }
929
930 void
reset_processing_state()931 track_c::reset_processing_state() {
932 m_timestamp.reset();
933 m_previous_timestamp.reset();
934 m_previous_valid_timestamp.reset();
935 m_expected_next_continuity_counter.reset();
936
937 clear_pes_payload();
938 processed = false;
939 m_timestamps_wrapped = false;
940 m_timestamp_wrap_add = timestamp_c::ns(0);
941 }
942
943 bool
transport_error_detected(packet_header_t & ts_header) const944 track_c::transport_error_detected(packet_header_t &ts_header)
945 const {
946 if (ts_header.has_transport_error())
947 return true;
948
949 if (!m_expected_next_continuity_counter)
950 return false;
951
952 return ts_header.continuity_counter() != m_expected_next_continuity_counter.value();
953 }
954
955 void
set_packetizer_source_id() const956 track_c::set_packetizer_source_id()
957 const {
958 if (!reader.m_is_reading_mpls || (ptzr < 0))
959 return;
960
961 reader.m_reader_packetizers[ptzr]->set_source_id(fmt::format("00{0:04x}", pid));
962 }
963
964 // ------------------------------------------------------------
965
file_t(mm_io_cptr const & in)966 file_t::file_t(mm_io_cptr const &in)
967 : m_in{in}
968 , m_pat_found{}
969 , m_num_pmts_found{}
970 , m_num_pmts_to_find{}
971 , m_es_to_process{}
972 , m_stream_timestamp{timestamp_c::ns(0)}
973 , m_timestamp_mpls_sync{timestamp_c::ns(0)}
974 , m_state{processing_state_e::probing}
975 , m_probe_range{}
976 , m_file_done{}
977 , m_packet_sent_to_packetizer{}
978 , m_detected_packet_size{}
979 , m_num_pat_crc_errors{}
980 , m_num_pmt_crc_errors{}
981 , m_validate_pat_crc{true}
982 , m_validate_pmt_crc{true}
983 , m_has_audio_or_video_track{}
984 {
985 }
986
987 int64_t
get_queued_bytes() const988 file_t::get_queued_bytes()
989 const {
990 int64_t bytes{};
991
992 for (auto ptzr : m_packetizers)
993 bytes += ptzr->get_queued_bytes();
994
995 return bytes;
996 }
997
998 void
reset_processing_state(processing_state_e new_state)999 file_t::reset_processing_state(processing_state_e new_state) {
1000 m_state = new_state;
1001 m_last_non_subtitle_pts.reset();
1002 m_last_non_subtitle_dts.reset();
1003 }
1004
1005 bool
all_pmts_found() const1006 file_t::all_pmts_found()
1007 const {
1008 return (0 != m_num_pmts_to_find) && (m_num_pmts_found >= m_num_pmts_to_find);
1009 }
1010
1011 uint64_t
get_start_source_packet_position() const1012 file_t::get_start_source_packet_position()
1013 const {
1014 return m_start_source_packet_number * m_detected_packet_size;
1015 }
1016
1017 // ------------------------------------------------------------
1018
1019 bool
probe_file()1020 reader_c::probe_file() {
1021 return detect_packet_size(*m_in, m_in->get_size()) > 0;
1022 }
1023
1024 int
detect_packet_size(mm_io_c & in,uint64_t size)1025 reader_c::detect_packet_size(mm_io_c &in,
1026 uint64_t size) {
1027 debugging_option_c debug{"mpeg_ts|mpeg_ts_packet_size"};
1028
1029 try {
1030 size = std::min<uint64_t>(1024 * 1024, size);
1031 auto num_startcodes_required = std::max<uint64_t>(size / 3 / TS_MAX_PACKET_SIZE, 32);
1032 auto buffer = memory_c::alloc(size);
1033 auto mem = buffer->get_buffer();
1034
1035 mxdebug_if(debug, fmt::format("detect_packet_size: size to probe {0} num required startcodes {1}\n", size, num_startcodes_required));
1036
1037 in.setFilePointer(0);
1038 size = in.read(mem, size);
1039
1040 std::vector<int> positions;
1041 for (int i = 0; i < static_cast<int>(size); ++i)
1042 if (0x47 == mem[i])
1043 positions.push_back(i);
1044
1045 for (int i = 0, num_positions = positions.size(); i < num_positions; ++i) {
1046 for (int k = 0; 0 != potential_packet_sizes[k]; ++k) {
1047 unsigned int pos = positions[i];
1048 unsigned int packet_size = potential_packet_sizes[k];
1049 unsigned int num_startcodes = 1;
1050
1051 while ((num_startcodes_required > num_startcodes) && (pos < size) && (0x47 == mem[pos])) {
1052 pos += packet_size;
1053 ++num_startcodes;
1054 }
1055
1056 if (num_startcodes_required <= num_startcodes) {
1057 mxdebug_if(debug, fmt::format("detect_packet_size: detected packet size {0} at offset {1}\n", packet_size, positions[i]));
1058 return packet_size;
1059 }
1060 }
1061 }
1062 } catch (...) {
1063 }
1064
1065 mxdebug_if(debug, "detect_packet_size: packet size could not be determined\n");
1066
1067 return -1;
1068 }
1069
1070 void
setup_initial_tracks()1071 reader_c::setup_initial_tracks() {
1072 m_tracks.clear();
1073
1074 m_tracks.push_back(std::make_shared<track_c>(*this, pid_type_e::pat));
1075 m_tracks.push_back(std::make_shared<track_c>(*this, pid_type_e::sdt));
1076 m_tracks.back()->set_pid(TS_SDT_PID);
1077
1078 auto &f = file();
1079 f.m_ignored_pids[TS_PAT_PID] = true;
1080 f.m_ignored_pids[TS_SDT_PID] = true;
1081 }
1082
1083 void
read_headers_for_file(std::size_t file_num)1084 reader_c::read_headers_for_file(std::size_t file_num) {
1085 m_current_file = file_num;
1086 auto &f = file();
1087
1088 setup_initial_tracks();
1089
1090 try {
1091 auto file_size = f.m_in->get_size();
1092 m_bytes_to_process += file_size;
1093 f.m_probe_range = calculate_probe_range(file_size, 10 * 1024 * 1024);
1094 auto size_to_probe = std::min<uint64_t>(file_size, f.m_probe_range);
1095 auto min_size_to_probe = std::min<uint64_t>(size_to_probe, 5 * 1024 * 1024);
1096 f.m_detected_packet_size = detect_packet_size(*f.m_in, size_to_probe);
1097
1098 f.m_in->setFilePointer(0);
1099
1100 mxdebug_if(m_debug_headers, fmt::format("read_headers: Starting to build PID list. (packet size: {0})\n", f.m_detected_packet_size));
1101
1102 unsigned char buf[TS_MAX_PACKET_SIZE]; // maximum TS packet size + 1
1103
1104 while (true) {
1105 if (f.m_in->read(buf, f.m_detected_packet_size) != static_cast<unsigned int>(f.m_detected_packet_size))
1106 break;
1107
1108 if (buf[0] != 0x47) {
1109 if (resync(f.m_in->getFilePointer() - f.m_detected_packet_size))
1110 continue;
1111 break;
1112 }
1113
1114 parse_packet(buf);
1115
1116 if ( f.m_pat_found
1117 && f.all_pmts_found()
1118 && (0 == f.m_es_to_process)
1119 && (f.m_in->getFilePointer() >= min_size_to_probe))
1120 break;
1121
1122 auto eof = f.m_in->eof() || (f.m_in->getFilePointer() >= size_to_probe);
1123 if (!eof)
1124 continue;
1125
1126 // Determine if we haven't found a PAT or a PMT but have plenty
1127 // of CRC errors (e.g. for badly mastered discs). In such a case
1128 // we should read from the start again, this time ignoring the
1129 // errors for the specific type.
1130 mxdebug_if(m_debug_headers,
1131 fmt::format("read_headers: EOF during detection. #tracks {0} #PAT CRC errors {1} #PMT CRC errors {2} PAT found {3} PMT found {4}/{5}\n",
1132 m_tracks.size(), f.m_num_pat_crc_errors, f.m_num_pmt_crc_errors, f.m_pat_found, f.m_num_pmts_found, f.m_num_pmts_to_find));
1133
1134 if (!f.m_pat_found && f.m_validate_pat_crc)
1135 f.m_validate_pat_crc = false;
1136
1137 else if (f.m_pat_found && !f.all_pmts_found() && f.m_validate_pmt_crc) {
1138 f.m_validate_pmt_crc = false;
1139 f.m_num_pmts_to_find = 0;
1140 f.m_pmt_pid_seen.clear();
1141
1142 } else
1143 break;
1144
1145 f.m_in->setFilePointer(0);
1146 f.m_in->clear_eof();
1147
1148 setup_initial_tracks();
1149 }
1150 } catch (...) {
1151 mxdebug_if(m_debug_headers, fmt::format("read_headers: caught exception\n"));
1152 }
1153
1154 mxdebug_if(m_debug_headers, fmt::format("read_headers: Detection done on {0} bytes\n", f.m_in->getFilePointer()));
1155
1156 // Run probe_packet_complete() for track-type detection once for
1157 // each track. This way tracks that don't actually need their
1158 // content to be found during probing will be set to OK, too.
1159 for (auto const &track : m_tracks) {
1160 if (track->is_pes_payload_size_unbounded() && (track->pes_payload_read->get_size() >= 6))
1161 parse_pes(*track);
1162
1163 track->clear_pes_payload();
1164 probe_packet_complete(*track, true);
1165 }
1166
1167 std::copy(m_tracks.begin(), m_tracks.end(), std::back_inserter(m_all_probed_tracks));
1168 }
1169
1170 void
determine_start_source_packet_number(file_t & file)1171 reader_c::determine_start_source_packet_number(file_t &file) {
1172 mxdebug_if(m_debug_mpls, fmt::format("MPLS: start SPN: file {0} min timestamp restriction {1}\n", to_utf8(Q(file.m_in->get_file_name()).replace(QRegularExpression{".*[/\\\\]"}, {})), file.m_timestamp_restriction_min));
1173
1174 if (!file.m_clpi_parser || !file.m_timestamp_restriction_min.valid()) {
1175 mxdebug_if(m_debug_mpls, fmt::format("MPLS: start SPN: clip information not found or no minimum timestamp restriction\n"));
1176 return;
1177 }
1178
1179 std::vector<uint64_t> source_packet_numbers;
1180
1181 for (auto const &ep_map : file.m_clpi_parser->m_ep_map) {
1182 std::optional<uint64_t> source_packet_number;
1183
1184 for (auto const &point : ep_map.points) {
1185 if (point.pts <= file.m_timestamp_restriction_min)
1186 source_packet_number = point.spn;
1187 else
1188 break;
1189 }
1190
1191 if (source_packet_number) {
1192 mxdebug_if(m_debug_mpls, fmt::format("MPLS: start SPN: candidate SPN for PID {0} is {1}\n", ep_map.pid, *source_packet_number));
1193 source_packet_numbers.push_back(*source_packet_number);
1194 }
1195 }
1196
1197 if (!source_packet_numbers.empty())
1198 file.m_start_source_packet_number = *std::min_element(source_packet_numbers.begin(), source_packet_numbers.end());
1199
1200 mxdebug_if(m_debug_mpls, fmt::format("MPLS: start SPN: chosen start SPN is {0}\n", file.m_start_source_packet_number));
1201 }
1202
1203 void
read_headers()1204 reader_c::read_headers() {
1205 m_files.emplace_back(std::make_shared<file_t>(m_in));
1206
1207 m_files[0]->m_timestamp_restriction_min = m_restricted_timestamps_min;
1208 m_files[0]->m_timestamp_restriction_max = m_restricted_timestamps_max;
1209
1210 auto mpls_in = dynamic_cast<mm_mpls_multi_file_io_c *>(get_underlying_input());
1211 if (mpls_in) {
1212 m_is_reading_mpls = true;
1213 m_mpls_chapters = mpls_in->get_chapters();
1214
1215 add_external_files_from_mpls(*mpls_in);
1216 }
1217
1218 for (int idx = 0, num_files = m_files.size(); idx < num_files; ++idx)
1219 read_headers_for_file(idx);
1220
1221 m_tracks = std::move(m_all_probed_tracks);
1222
1223 for (int idx = 0, num_files = m_files.size(); idx < num_files; ++idx) {
1224 parse_clip_info_file(idx);
1225 determine_start_source_packet_number(*m_files[idx]);
1226 }
1227
1228 process_chapter_entries();
1229
1230 std::vector<track_ptr> identified_tracks;
1231
1232 auto track_id = uint64_t{};
1233 for (auto &track : m_tracks) {
1234 // For TrueHD tracks detection for embedded AC-3 frames is
1235 // done. However, "probed_ok" is only set on the TrueHD track if
1236 // both types have been found. If only TrueHD is found then
1237 // "probed_ok" must be set to true after detection has exhausted
1238 // the search space; otherwise a TrueHD-only track would never be
1239 // considered OK.
1240 if (track->codec.is(codec_c::type_e::A_TRUEHD) && track->m_truehd_found_truehd)
1241 track->probed_ok = true;
1242
1243 if (!track->probed_ok || !track->codec)
1244 continue;
1245
1246 track->clear_pes_payload();
1247 track->processed = false;
1248 track->m_id = track_id++;
1249 // track->timestamp_offset = -1;
1250
1251 for (auto const &coupled_track : track->m_coupled_tracks)
1252 if (!coupled_track->language.is_valid())
1253 coupled_track->language = track->language;
1254
1255 identified_tracks.push_back(track);
1256 }
1257
1258 m_tracks = std::move(identified_tracks);
1259
1260 show_demuxer_info();
1261 }
1262
1263 void
reset_processing_state(processing_state_e new_state)1264 reader_c::reset_processing_state(processing_state_e new_state) {
1265 for (auto const &file : m_files)
1266 file->reset_processing_state(new_state);
1267
1268 for (auto const &track : m_tracks)
1269 track->reset_processing_state();
1270
1271 m_packet_num = 0;
1272 }
1273
1274 void
determine_global_timestamp_offset()1275 reader_c::determine_global_timestamp_offset() {
1276 reset_processing_state(processing_state_e::determining_timestamp_offset);
1277
1278 auto &f = file();
1279
1280 auto probe_start_pos = f.get_start_source_packet_position();
1281 auto probe_end_pos = probe_start_pos + f.m_probe_range;
1282
1283 f.m_in->setFilePointer(probe_start_pos);
1284 f.m_in->clear_eof();
1285
1286 mxdebug_if(m_debug_timestamp_offset, fmt::format("determine_global_timestamp_offset: determining global timestamp offset from the first {0} bytes\n", f.m_probe_range));
1287
1288 try {
1289 unsigned char buf[TS_MAX_PACKET_SIZE]; // maximum TS packet size + 1
1290
1291 while (f.m_in->getFilePointer() < probe_end_pos) {
1292 if (f.m_in->read(buf, f.m_detected_packet_size) != static_cast<unsigned int>(f.m_detected_packet_size))
1293 break;
1294
1295 if (buf[0] != 0x47) {
1296 if (resync(f.m_in->getFilePointer() - f.m_detected_packet_size))
1297 continue;
1298 break;
1299 }
1300
1301 parse_packet(buf);
1302 }
1303 } catch (...) {
1304 mxdebug_if(m_debug_timestamp_offset, fmt::format("determine_global_timestamp_offset: caught exception\n"));
1305 }
1306
1307 mxdebug_if(m_debug_timestamp_offset, fmt::format("determine_global_timestamp_offset: detection done; global timestamp offset is {0}\n", f.m_global_timestamp_offset));
1308
1309 f.m_in->setFilePointer(f.get_start_source_packet_position());
1310 f.m_in->clear_eof();
1311
1312 reset_processing_state(processing_state_e::muxing);
1313
1314 if (debugging_c::requested("mpeg_ts_dont_offset_timestamps"))
1315 for (auto const &file : m_files)
1316 file->m_global_timestamp_offset = timestamp_c::ns(0);
1317 }
1318
1319 void
process_chapter_entries()1320 reader_c::process_chapter_entries() {
1321 if (m_mpls_chapters.empty() || m_ti.m_no_chapters)
1322 return;
1323
1324 auto language = m_ti.m_chapter_language.is_valid() ? m_ti.m_chapter_language
1325 : g_default_language.is_valid() ? g_default_language
1326 : mtx::bcp47::language_c::parse("eng");
1327
1328 m_chapters = mtx::chapters::convert_mpls_chapters_kax_chapters(m_mpls_chapters, language);
1329
1330 auto const &sync = mtx::includes(m_ti.m_timestamp_syncs, track_info_c::chapter_track_id) ? m_ti.m_timestamp_syncs[track_info_c::chapter_track_id]
1331 : mtx::includes(m_ti.m_timestamp_syncs, track_info_c::all_tracks_id) ? m_ti.m_timestamp_syncs[track_info_c::all_tracks_id]
1332 : timestamp_sync_t{};
1333 mtx::chapters::adjust_timestamps(*m_chapters, sync.displacement, sync.factor);
1334 }
1335
1336 uint32_t
calculate_crc(void const * buffer,size_t size) const1337 reader_c::calculate_crc(void const *buffer,
1338 size_t size)
1339 const {
1340 return mtx::bytes::swap_32(mtx::checksum::calculate_as_uint(mtx::checksum::algorithm_e::crc32_ieee, buffer, size, 0xffffffff));
1341 }
1342
1343 void
add_multiplexed_ids(std::vector<uint64_t> & multiplexed_ids,track_c & track)1344 reader_c::add_multiplexed_ids(std::vector<uint64_t> &multiplexed_ids,
1345 track_c &track) {
1346 multiplexed_ids.push_back(track.m_id);
1347 for (auto const &coupled_track : track.m_coupled_tracks)
1348 if (coupled_track->probed_ok)
1349 multiplexed_ids.push_back(coupled_track->m_id);
1350 }
1351
1352 void
add_programs_to_identification_info(mtx::id::info_c & info)1353 reader_c::add_programs_to_identification_info(mtx::id::info_c &info) {
1354 if (m_files[0]->m_programs.empty())
1355 return;
1356
1357 std::sort(m_files[0]->m_programs.begin(), m_files[0]->m_programs.end());
1358
1359 auto programs_json = nlohmann::json::array();
1360
1361 for (auto &program : m_files[0]->m_programs) {
1362 auto program_json = nlohmann::json{
1363 { mtx::id::program_number, program.program_number },
1364 { mtx::id::service_provider, program.service_provider },
1365 { mtx::id::service_name, program.service_name },
1366 };
1367
1368 programs_json.push_back(program_json);
1369 }
1370
1371 info.add(mtx::id::programs, programs_json);
1372 }
1373
1374 void
identify()1375 reader_c::identify() {
1376 auto info = mtx::id::info_c{};
1377 auto mpls_in = dynamic_cast<mm_mpls_multi_file_io_c *>(get_underlying_input());
1378 if (mpls_in)
1379 mpls_in->create_verbose_identification_info(info);
1380
1381 add_programs_to_identification_info(info);
1382
1383 id_result_container(info.get());
1384
1385 for (auto const &track : m_tracks) {
1386 info = mtx::id::info_c{};
1387 info.add(mtx::id::language, track->language.get_iso639_alpha_3_code());
1388 info.set(mtx::id::stream_id, track->pid);
1389 info.set(mtx::id::number, track->pid);
1390
1391 if (track->program_number)
1392 info.set(mtx::id::program_number, track->program_number.value());
1393
1394 if (pid_type_e::audio == track->type) {
1395 info.add(mtx::id::audio_channels, track->a_channels);
1396 info.add(mtx::id::audio_sampling_frequency, track->a_sample_rate);
1397 info.add(mtx::id::audio_bits_per_sample, track->a_bits_per_sample);
1398
1399 } else if (pid_type_e::video == track->type)
1400 info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->v_width, track->v_height));
1401
1402 else if (pid_type_e::subtitles == track->type) {
1403 info.set(mtx::id::text_subtitles, track->codec.is(codec_c::type_e::S_SRT));
1404 if (track->m_ttx_wanted_page)
1405 info.set(mtx::id::teletext_page, *track->m_ttx_wanted_page);
1406 }
1407
1408 auto multiplexed_track_ids = std::vector<uint64_t>{};
1409 if (!track->m_coupled_tracks.empty())
1410 add_multiplexed_ids(multiplexed_track_ids, *track);
1411
1412 else if (track->m_master)
1413 add_multiplexed_ids(multiplexed_track_ids, *track->m_master);
1414
1415 if (!multiplexed_track_ids.empty()) {
1416 std::sort(multiplexed_track_ids.begin(), multiplexed_track_ids.end());
1417 info.set(mtx::id::multiplexed_tracks, multiplexed_track_ids);
1418 }
1419
1420 std::string type = pid_type_e::audio == track->type ? ID_RESULT_TRACK_AUDIO
1421 : pid_type_e::video == track->type ? ID_RESULT_TRACK_VIDEO
1422 : ID_RESULT_TRACK_SUBTITLES;
1423
1424 id_result_track(track->m_id, type, track->codec.get_name(), info.get());
1425 }
1426
1427 if (!m_mpls_chapters.empty())
1428 id_result_chapters(m_mpls_chapters.size());
1429 }
1430
1431 bool
parse_pat(track_c & track)1432 reader_c::parse_pat(track_c &track) {
1433 if (track.pes_payload_read->get_size() < sizeof(pat_t)) {
1434 mxdebug_if(m_debug_pat_pmt, "Invalid parameters!\n");
1435 return false;
1436 }
1437
1438 auto pat = track.pes_payload_read->get_buffer();
1439 auto pat_header = reinterpret_cast<pat_t *>(pat);
1440
1441 if (pat_header->table_id != 0x00) {
1442 mxdebug_if(m_debug_pat_pmt, "Invalid PAT table_id!\n");
1443 return false;
1444 }
1445
1446 if (pat_header->get_section_syntax_indicator() != 1 || pat_header->get_current_next_indicator() == 0) {
1447 mxdebug_if(m_debug_pat_pmt, "Invalid PAT section_syntax_indicator/current_next_indicator!\n");
1448 return false;
1449 }
1450
1451 if (pat_header->section_number != 0 || pat_header->last_section_number != 0) {
1452 mxdebug_if(m_debug_pat_pmt, "Unsupported multiple section PAT!\n");
1453 return false;
1454 }
1455
1456 auto &f = file();
1457 unsigned short pat_section_length = pat_header->get_section_length();
1458 uint32_t elapsed_CRC = calculate_crc(pat, 3 + pat_section_length - 4/*CRC32*/);
1459 uint32_t read_CRC = get_uint32_be(pat + 3 + pat_section_length - 4);
1460
1461 if (elapsed_CRC != read_CRC) {
1462 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pat: Wrong PAT CRC !!! Elapsed = 0x{0:08x}, read 0x{1:08x}, validate PAT CRC? {2}\n", elapsed_CRC, read_CRC, f.m_validate_pat_crc));
1463 ++f.m_num_pat_crc_errors;
1464 if (f.m_validate_pat_crc)
1465 return false;
1466 }
1467
1468 if (pat_section_length < 13 || pat_section_length > 1021) {
1469 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pat: Wrong PAT section_length (= {0})\n", pat_section_length));
1470 return false;
1471 }
1472
1473 auto prog_count = static_cast<unsigned int>(pat_section_length - 5 - 4/*CRC32*/) / 4;
1474 auto pat_section = reinterpret_cast<pat_section_t *>(pat + sizeof(pat_t));
1475
1476 for (auto i = 0u; i < prog_count; i++, pat_section++) {
1477 unsigned short local_program_number = pat_section->get_program_number();
1478 uint16_t tmp_pid = pat_section->get_pid();
1479
1480 mxdebug_if(m_debug_pat_pmt,
1481 fmt::format("parse_pat: program_number: {0}; {1}_pid: {2}\n",
1482 local_program_number,
1483 0 == local_program_number ? "nit" : "pmt",
1484 tmp_pid));
1485
1486 if (!local_program_number || f.m_pmt_pid_seen[tmp_pid])
1487 continue;
1488
1489 auto pmt = std::make_shared<track_c>(*this, pid_type_e::pmt);
1490 f.m_es_to_process = 0;
1491 f.m_ignored_pids[tmp_pid] = true;
1492 f.m_pmt_pid_seen[tmp_pid] = true;
1493 f.m_pat_found = true;
1494 ++f.m_num_pmts_to_find;
1495
1496 pmt->set_pid(tmp_pid);
1497
1498 m_tracks.push_back(pmt);
1499 }
1500
1501 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pat: number of PMTs to find: {0}\n", f.m_num_pmts_to_find));
1502
1503 return true;
1504 }
1505
1506 memory_cptr
read_pmt_descriptor(mm_io_c & io)1507 reader_c::read_pmt_descriptor(mm_io_c &io) {
1508 auto buffer = io.read(sizeof(pmt_descriptor_t));
1509 auto length = buffer->get_buffer()[1];
1510
1511 buffer->resize(sizeof(pmt_descriptor_t) + length);
1512 if (io.read(buffer->get_buffer() + sizeof(pmt_descriptor_t), length) != length)
1513 throw mtx::mm_io::end_of_file_x{};
1514
1515 return buffer;
1516 }
1517
1518 bool
parse_pmt_pid_info(mm_mem_io_c & mem,uint16_t program_number)1519 reader_c::parse_pmt_pid_info(mm_mem_io_c &mem,
1520 uint16_t program_number) {
1521 auto &f = file();
1522 auto missing_tag = true;
1523
1524 auto pmt_pid_info_buffer = mem.read(sizeof(pmt_pid_info_t));
1525 auto pmt_pid_info = reinterpret_cast<pmt_pid_info_t *>(pmt_pid_info_buffer->get_buffer());
1526 auto es_info_length = pmt_pid_info->get_es_info_length();
1527
1528 auto track = std::make_shared<track_c>(*this);
1529 track->type = pid_type_e::unknown;
1530 track->program_number = program_number;
1531
1532 track->set_pid(pmt_pid_info->get_pid());
1533 track->determine_codec_from_stream_type(pmt_pid_info->stream_type);
1534
1535 while (es_info_length >= sizeof(pmt_descriptor_t)) {
1536 auto pmt_descriptor_buffer = read_pmt_descriptor(mem);
1537 auto pmt_descriptor = reinterpret_cast<pmt_descriptor_t *>(pmt_descriptor_buffer->get_buffer());
1538
1539 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pmt: PMT descriptor tag 0x{0:02x} length {1}\n", static_cast<unsigned int>(pmt_descriptor->tag), static_cast<unsigned int>(pmt_descriptor->length)));
1540
1541 if (pmt_descriptor_buffer->get_size() > es_info_length)
1542 break;
1543
1544 es_info_length -= pmt_descriptor_buffer->get_size();
1545
1546 if (0x0a != pmt_descriptor->tag)
1547 missing_tag = false;
1548
1549 switch (pmt_descriptor->tag) {
1550 case 0x05: // registration descriptor
1551 track->parse_registration_pmt_descriptor(*pmt_descriptor, *pmt_pid_info);
1552 break;
1553 case 0x0a: // ISO 639 language descriptor
1554 track->parse_iso639_language_from(pmt_descriptor + 1);
1555 break;
1556 case 0x56: // Teletext descriptor
1557 track->parse_srt_pmt_descriptor(*pmt_descriptor, *pmt_pid_info);
1558 break;
1559 case 0x59: // Subtitles descriptor
1560 track->parse_subtitling_pmt_descriptor(*pmt_descriptor, *pmt_pid_info);
1561 break;
1562 case 0x6A: // AC-3 descriptor
1563 case 0x7A: // E-AC-3 descriptor
1564 track->parse_ac3_pmt_descriptor(*pmt_descriptor, *pmt_pid_info);
1565 break;
1566 case 0x7b: // DTS descriptor
1567 track->parse_dts_pmt_descriptor(*pmt_descriptor, *pmt_pid_info);
1568 break;
1569 }
1570 }
1571
1572 // Default to AC-3 if it's a PES private stream type that's missing
1573 // a known/more concrete descriptor tag.
1574 if ((pmt_pid_info->stream_type == stream_type_e::iso_13818_pes_private) && missing_tag) {
1575 track->type = pid_type_e::audio;
1576 track->codec = codec_c::look_up(codec_c::type_e::A_AC3);
1577 }
1578
1579 if (track->type != pid_type_e::unknown) {
1580 track->processed = false;
1581 m_tracks.push_back(track);
1582 ++f.m_es_to_process;
1583
1584 std::copy(track->m_coupled_tracks.begin(), track->m_coupled_tracks.end(), std::back_inserter(m_tracks));
1585 f.m_es_to_process += track->m_coupled_tracks.size();
1586 }
1587
1588 mxdebug_if(m_debug_pat_pmt,
1589 fmt::format("parse_pmt: PID {0} stream type {1:02x} has type: {2}\n",
1590 track->pid,
1591 static_cast<unsigned int>(pmt_pid_info->stream_type),
1592 track->type != pid_type_e::unknown ? track->codec.get_name() : "<unknown>"));
1593
1594 return true;
1595 }
1596
1597 bool
parse_pmt(track_c & track)1598 reader_c::parse_pmt(track_c &track) {
1599 auto payload_size = track.pes_payload_read->get_size();
1600 auto pmt_start = track.pes_payload_read->get_buffer();
1601 auto pmt_end = pmt_start + payload_size;
1602
1603 if (payload_size < sizeof(pmt_t)) {
1604 mxdebug_if(m_debug_pat_pmt, fmt::format("Actual PMT size {0} less than PMT structure size {1}!\n", payload_size, sizeof(pmt_t)));
1605 return false;
1606 }
1607
1608 auto pmt_header = reinterpret_cast<pmt_t *>(pmt_start);
1609 auto program_number = get_uint16_be(&pmt_header->program_number);
1610
1611 if (pmt_header->table_id != 0x02) {
1612 mxdebug_if(m_debug_pat_pmt, "Invalid PMT table_id!\n");
1613 return false;
1614 }
1615
1616 if (pmt_header->get_section_syntax_indicator() != 1 || pmt_header->get_current_next_indicator() == 0) {
1617 mxdebug_if(m_debug_pat_pmt, "Invalid PMT section_syntax_indicator/current_next_indicator!\n");
1618 return false;
1619 }
1620
1621 if (pmt_header->section_number != 0 || pmt_header->last_section_number != 0) {
1622 mxdebug_if(m_debug_pat_pmt, "Unsupported multiple section PMT!\n");
1623 return false;
1624 }
1625
1626 auto &f = file();
1627 auto pmt_section_length = pmt_header->get_section_length();
1628 auto pmt_section_start = pmt_start + offsetof(pmt_t, program_number);
1629 auto pmt_section_end = pmt_section_start + pmt_section_length;
1630 auto program_info_length = pmt_header->get_program_info_length();
1631 auto program_info_start = pmt_start + sizeof(pmt_t);
1632 auto program_info_end = program_info_start + program_info_length;
1633
1634 if (program_info_end > pmt_end) {
1635 mxdebug_if(m_debug_pat_pmt, fmt::format("Actual PMT size {0} less than PMT program info size + program info offset {1}!\n", payload_size, pmt_end - pmt_start));
1636 return false;
1637 }
1638
1639 if (pmt_section_end > pmt_end) {
1640 mxdebug_if(m_debug_pat_pmt, fmt::format("Actual PMT size {0} less than PMT section size + section offset {1}!\n", payload_size, pmt_end - pmt_start));
1641 return false;
1642 }
1643
1644 if ((pmt_section_length < 13) || (pmt_section_length > 1021)) {
1645 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pmt: Wrong PMT section_length {0}\n", pmt_section_length));
1646 return false;
1647 }
1648
1649 uint32_t elapsed_CRC = calculate_crc(pmt_start, 3 + pmt_section_length - 4/*CRC32*/);
1650 uint32_t read_CRC = get_uint32_be(pmt_section_end - 4);
1651
1652 if (elapsed_CRC != read_CRC) {
1653 mxdebug_if(m_debug_pat_pmt, fmt::format("parse_pmt: Wrong PMT CRC !!! Elapsed = 0x{0:08x}, read 0x{1:08x}, validate PMT CRC? {2}\n", elapsed_CRC, read_CRC, f.m_validate_pmt_crc));
1654 ++f.m_num_pmt_crc_errors;
1655 if (f.m_validate_pmt_crc)
1656 return false;
1657 }
1658
1659 mxdebug_if(m_debug_pat_pmt,
1660 fmt::format("parse_pmt: program number: {0} PCR PID: {1} program info length: {2}\n",
1661 pmt_header->get_program_number(), pmt_header->get_pcr_pid(), program_info_length));
1662
1663 mm_mem_io_c mem{program_info_end, static_cast<uint64_t>(pmt_section_end - 4 - program_info_end)};
1664
1665 try {
1666 bool ok = true;
1667 while (ok)
1668 ok = parse_pmt_pid_info(mem, program_number);
1669
1670 } catch (mtx::mm_io::exception &) {
1671 }
1672
1673 f.m_ignored_pids[track.pid] = true;
1674
1675 ++f.m_num_pmts_found;
1676
1677 mxdebug_if(m_debug_pat_pmt,
1678 fmt::format("parse_pmt: {0} num PMTs found {1} vs. to find {2}\n",
1679 f.m_num_pmts_found < f.m_num_pmts_to_find ? "find_ongoing"
1680 : f.m_num_pmts_found == f.m_num_pmts_to_find ? "find_done"
1681 : "find_error",
1682 f.m_num_pmts_found, f.m_num_pmts_to_find));
1683
1684 return true;
1685 }
1686
1687 charset_converter_cptr
get_charset_converter_for_coding_type(unsigned int coding)1688 reader_c::get_charset_converter_for_coding_type(unsigned int coding) {
1689 static std::unordered_map<unsigned int, std::string> coding_names;
1690
1691 if (coding_names.empty()) {
1692 coding_names[0x00] = "ISO6937";
1693 coding_names[0x01] = "ISO8859-5";
1694 coding_names[0x02] = "ISO8859-6";
1695 coding_names[0x03] = "ISO8859-7";
1696 coding_names[0x04] = "ISO8859-8";
1697 coding_names[0x05] = "ISO8859-9";
1698 coding_names[0x06] = "ISO8859-10";
1699 coding_names[0x07] = "ISO8859-11";
1700 coding_names[0x09] = "ISO8859-13";
1701 coding_names[0x0a] = "ISO8859-14";
1702 coding_names[0x0b] = "ISO8859-15";
1703 coding_names[0x10] = "ISO8859";
1704 coding_names[0x13] = "GB2312";
1705 coding_names[0x14] = "BIG5";
1706 coding_names[0x100001] = "ISO8859-1";
1707 coding_names[0x100002] = "ISO8859-2";
1708 coding_names[0x100003] = "ISO8859-3";
1709 coding_names[0x100004] = "ISO8859-4";
1710 coding_names[0x100005] = "ISO8859-5";
1711 coding_names[0x100006] = "ISO8859-6";
1712 coding_names[0x100007] = "ISO8859-7";
1713 coding_names[0x100008] = "ISO8859-8";
1714 coding_names[0x100009] = "ISO8859-9";
1715 coding_names[0x10000a] = "ISO8859-10";
1716 coding_names[0x10000b] = "ISO8859-11";
1717 coding_names[0x10000d] = "ISO8859-13";
1718 coding_names[0x10000e] = "ISO8859-14";
1719 coding_names[0x10000f] = "ISO8859-15";
1720 }
1721
1722 auto coding_name = coding_names[coding];
1723 if (coding_name.empty())
1724 coding_name = "UTF-8";
1725
1726 auto converter = charset_converter_c::init(coding_name, true);
1727 return converter ? converter : charset_converter_c::init("UTF-8");
1728 }
1729
1730 std::string
read_descriptor_string(mtx::bits::reader_c & r)1731 reader_c::read_descriptor_string(mtx::bits::reader_c &r) {
1732 auto str_length = r.get_bits(8);
1733 if (!str_length)
1734 return {};
1735
1736 std::string content(str_length, ' ');
1737
1738 r.get_bytes(reinterpret_cast<unsigned char *>(&content[0]), str_length);
1739
1740 auto coding = static_cast<unsigned int>(content[0]);
1741
1742 if (coding >= 0x20)
1743 coding = 0x00;
1744
1745 else if (coding == 0x10) {
1746 if (str_length < 4)
1747 return {};
1748
1749 coding = 0x100000 | get_uint16_be(&content[1]);
1750 content.erase(0, 3);
1751
1752 } else if (coding == 0x1f) {
1753 if (str_length < 3)
1754 return {};
1755
1756 coding = 0x1f00 | static_cast<unsigned char>(content[1]);
1757 content.erase(0, 2);
1758
1759 } else
1760 content.erase(0, 1);
1761
1762 return get_charset_converter_for_coding_type(coding)->utf8(content);
1763 }
1764
1765 void
parse_sdt_service_desciptor(mtx::bits::reader_c & r,uint16_t program_number)1766 reader_c::parse_sdt_service_desciptor(mtx::bits::reader_c &r,
1767 uint16_t program_number) {
1768 r.skip_bits(8); // service_type
1769
1770 auto service_provider = read_descriptor_string(r);
1771 auto service_name = read_descriptor_string(r);
1772
1773 mxdebug_if(m_debug_sdt, fmt::format("parse_sdt: program_number {0} service_provider {1} service_name {2}\n", program_number, service_provider, service_name));
1774
1775 file().m_programs.push_back({ program_number, service_provider, service_name });
1776 }
1777
1778 bool
parse_sdt(track_c & track)1779 reader_c::parse_sdt(track_c &track) {
1780 if (!track.pes_payload_read->get_size())
1781 return false;
1782
1783 at_scope_exit_c finally{[&track]() { track.clear_pes_payload(); }};
1784
1785 try {
1786 mtx::bits::reader_c r{track.pes_payload_read->get_buffer(), track.pes_payload_read->get_size()};
1787
1788 if (r.get_bits(8) != TS_SDT_TID)
1789 return false;
1790
1791 r.skip_bits(1 + 1 + 2 // section_syntax_indicator, reserved_for_future_use, reserved
1792 + 12 + 16 // section_length, transport_stream_id
1793 + 2 + 5 + 1 // reserved, version_number, current_next_indicator
1794 + 8 + 8 // section_number, last_section_number
1795 + 16 + 8); // original_network_id, reserved_future_use
1796
1797 while (r.get_remaining_bits() > 32) { // only CRC_32
1798 auto program_number = r.get_bits(16);
1799
1800 r.skip_bits(6 + 1 + 1 // reserved_future_use, EIT_schedule_flag, EIT_Present_following_flag
1801 + 3 + 1); // running_status, free_CA_mode
1802
1803 auto descriptors_loop_end_bits = r.get_bit_position() + 12 + r.get_bits(12) * 8;
1804
1805 while ((r.get_bit_position() + 16u) < descriptors_loop_end_bits) {
1806 auto start = r.get_bit_position();
1807 auto tag = r.get_bits(8);
1808 auto length = r.get_bits(8);
1809
1810 if ((start + 8 * (2 + length)) > descriptors_loop_end_bits)
1811 break;
1812
1813 if (tag == 0x48)
1814 parse_sdt_service_desciptor(r, program_number);
1815
1816 r.set_bit_position(start + 8 * (2 + length));
1817 }
1818 }
1819
1820 } catch (mtx::mm_io::exception &) {
1821 mxdebug_if(m_debug_sdt, fmt::format("parse_sdt: exception during SDT parsing\n"));
1822 return false;
1823 }
1824
1825 return true;
1826 }
1827
1828 void
parse_pes(track_c & track)1829 reader_c::parse_pes(track_c &track) {
1830 at_scope_exit_c finally{[&track]() { track.clear_pes_payload(); }};
1831
1832 auto &f = file();
1833 auto pes = track.pes_payload_read->get_buffer();
1834 auto const pes_size = track.pes_payload_read->get_size();
1835 auto pes_header = reinterpret_cast<pes_header_t *>(pes);
1836
1837 if (pes_size < 6) {
1838 mxdebug_if(m_debug_packet, fmt::format("parse_pes: error: PES payload ({0}) too small even for the basic PES header (6)\n", pes_size));
1839 return;
1840 }
1841
1842 timestamp_c pts, dts;
1843 auto has_pts = false;
1844 auto has_dts = false;
1845 auto to_skip = 0u;
1846
1847 if (mtx::included_in(pes_header->stream_id, mtx::mpeg1_2::PRIVATE_STREAM_2)) {
1848 to_skip = 6;
1849 track.pes_payload_read->remove(to_skip);
1850
1851 pts = track.derive_pts_from_content();
1852 dts = pts;
1853
1854 } else {
1855 if (pes_size < sizeof(pes_header_t)) {
1856 mxdebug_if(m_debug_packet, fmt::format("parse_pes: error: PES payload ({0}) too small for PES header structure itself ({1})\n", pes_size, sizeof(pes_header_t)));
1857 return;
1858 }
1859
1860 has_pts = (pes_header->get_pts_dts_flags() & 0x02) == 0x02; // 10 and 11 mean PTS is present
1861 has_dts = (pes_header->get_pts_dts_flags() & 0x01) == 0x01; // 01 and 11 mean DTS is present
1862 to_skip = offsetof(pes_header_t, pes_header_data_length) + pes_header->pes_header_data_length + 1;
1863
1864 if (pes_size < to_skip) {
1865 mxdebug_if(m_debug_packet, fmt::format("parse_pes: error: PES payload ({0}) too small for PES header + header data including PTS/DTS ({1})\n", pes_size, to_skip));
1866 return;
1867 }
1868
1869 if (has_pts) {
1870 pts = read_timestamp(&pes_header->pts_dts);
1871 dts = pts;
1872 }
1873
1874 if (has_dts)
1875 dts = read_timestamp(&pes_header->pts_dts + (has_pts ? 5 : 0));
1876
1877 track.pes_payload_read->remove(to_skip);
1878 }
1879
1880 if (!track.m_use_dts)
1881 dts = pts;
1882
1883 auto orig_pts = pts;
1884 auto orig_dts = dts;
1885
1886 auto result = track.handle_bogus_subtitle_timestamps(pts, dts);
1887
1888 if (drop_decision_e::drop == result)
1889 return;
1890
1891 track.handle_timestamp_wrap(pts, dts);
1892
1893 auto set_global_timestamp_offset_from_pts
1894 = pts.valid()
1895 && (mtx::included_in(track.type, pid_type_e::audio, pid_type_e::video))
1896 && (!f.m_global_timestamp_offset.valid() || (pts < f.m_global_timestamp_offset))
1897 && (!f.m_timestamp_restriction_min.valid() || (pts >= f.m_timestamp_restriction_min));
1898
1899 if (set_global_timestamp_offset_from_pts) {
1900 mxdebug_if(m_debug_headers,
1901 fmt::format("determining_timestamp_offset: new global timestamp offset {0} prior {1} file position afterwards {2} min_restriction {3} DTS {4}\n",
1902 pts, f.m_global_timestamp_offset, f.m_in->getFilePointer(), f.m_timestamp_restriction_min, dts));
1903 f.m_global_timestamp_offset = pts;
1904 }
1905
1906 if (processing_state_e::determining_timestamp_offset == f.m_state)
1907 return;
1908
1909 if (f.m_timestamp_restriction_max.valid() && has_pts && (pts >= f.m_timestamp_restriction_max)) {
1910 mxdebug_if(m_debug_mpls, fmt::format("MPLS: stopping processing file as PTS {0} >= max. timestamp restriction {1}\n", pts, f.m_timestamp_restriction_max));
1911 f.m_in->setFilePointer(f.m_in->get_size());
1912 return;
1913 }
1914
1915 if (m_debug_packet) {
1916 mxdebug(fmt::format("parse_pes: PES info at file position {0} (file num {1}):\n", f.m_position, track.m_file_num));
1917 mxdebug(fmt::format("parse_pes: stream_id = {0} PID = {1}\n", static_cast<unsigned int>(pes_header->stream_id), track.pid));
1918 mxdebug(fmt::format("parse_pes: PES_packet_length = {0}, PES_header_data_length = {1}, data starts at {2}\n", pes_size, static_cast<unsigned int>(pes_header->pes_header_data_length), to_skip));
1919 mxdebug(fmt::format("parse_pes: PTS? {0} ({4} processed {5}) DTS? ({6} processed {7}) {1} ESCR = {2} ES_rate = {3}\n",
1920 has_pts, has_dts, static_cast<unsigned int>(pes_header->get_escr()), static_cast<unsigned int>(pes_header->get_es_rate()), orig_pts, pts, orig_dts, dts));
1921 mxdebug(fmt::format("parse_pes: DSM_trick_mode = {0}, add_copy = {1}, CRC = {2}, ext = {3}\n",
1922 static_cast<unsigned int>(pes_header->get_dsm_trick_mode()), static_cast<unsigned int>(pes_header->get_additional_copy_info()), static_cast<unsigned int>(pes_header->get_pes_crc()),
1923 static_cast<unsigned int>(pes_header->get_pes_extension())));
1924 }
1925
1926 if (pts.valid()) {
1927 track.m_previous_valid_timestamp = pts;
1928 f.m_stream_timestamp = pts;
1929 track.m_timestamp = dts;
1930
1931 mxdebug_if(m_debug_packet, fmt::format("parse_pes: PID {0} PTS found: {1} DTS: {2}\n", track.pid, pts, dts));
1932 }
1933
1934 if (processing_state_e::probing == f.m_state)
1935 probe_packet_complete(track);
1936
1937 else
1938 track.send_to_packetizer();
1939 }
1940
1941 timestamp_c
read_timestamp(unsigned char * p)1942 reader_c::read_timestamp(unsigned char *p) {
1943 int64_t mpeg_timestamp = static_cast<int64_t>( ( p[0] >> 1) & 0x07) << 30;
1944 mpeg_timestamp |= (static_cast<int64_t>(get_uint16_be(&p[1])) >> 1) << 15;
1945 mpeg_timestamp |= static_cast<int64_t>(get_uint16_be(&p[3])) >> 1;
1946
1947 return timestamp_c::mpeg(mpeg_timestamp);
1948 }
1949
1950 track_ptr
handle_packet_for_pid_not_listed_in_pmt(uint16_t pid)1951 reader_c::handle_packet_for_pid_not_listed_in_pmt(uint16_t pid) {
1952 auto &f = file();
1953
1954 if ( (f.m_state != processing_state_e::probing)
1955 || f.m_ignored_pids[pid]
1956 || !f.m_pat_found
1957 || !f.all_pmts_found())
1958 return {};
1959
1960 mxdebug_if(m_debug_pat_pmt, fmt::format("found packet for track PID {0} not listed in PMT, attempting type detection by content\n", pid));
1961
1962 auto track = std::make_shared<track_c>(*this);
1963 track->set_pid(pid);
1964
1965 m_tracks.push_back(track);
1966 ++f.m_es_to_process;
1967
1968 return track;
1969 }
1970
1971 void
parse_packet(unsigned char * buf)1972 reader_c::parse_packet(unsigned char *buf) {
1973 auto hdr = reinterpret_cast<packet_header_t *>(buf);
1974 auto track = find_track_for_pid(hdr->get_pid());
1975
1976 if (!track)
1977 track = handle_packet_for_pid_not_listed_in_pmt(hdr->get_pid());
1978
1979 if ( !track
1980 || !hdr->has_payload()) // no ts_payload
1981 return;
1982
1983 if (mtx::included_in(track->type, pid_type_e::video, pid_type_e::audio, pid_type_e::subtitles, pid_type_e::unknown))
1984 handle_transport_errors(*track, *hdr);
1985
1986 if ( hdr->has_transport_error() // corrupted packet
1987 || track->processed)
1988 return;
1989
1990 auto payload = determine_ts_payload_start(hdr);
1991
1992 if (payload.second)
1993 handle_ts_payload(*track, *hdr, payload.first, payload.second);
1994 }
1995
1996 void
handle_ts_payload(track_c & track,packet_header_t & ts_header,unsigned char * ts_payload,std::size_t ts_payload_size)1997 reader_c::handle_ts_payload(track_c &track,
1998 packet_header_t &ts_header,
1999 unsigned char *ts_payload,
2000 std::size_t ts_payload_size) {
2001 if (mtx::included_in(track.type, pid_type_e::pat, pid_type_e::pmt, pid_type_e::sdt))
2002 handle_pat_pmt_payload(track, ts_header, ts_payload, ts_payload_size);
2003
2004 else if (mtx::included_in(track.type, pid_type_e::video, pid_type_e::audio, pid_type_e::subtitles, pid_type_e::unknown))
2005 handle_pes_payload(track, ts_header, ts_payload, ts_payload_size);
2006
2007 else {
2008 mxdebug_if(m_debug_headers, fmt::format("handle_ts_payload: error: unknown track.type {0}\n", static_cast<unsigned int>(track.type)));
2009 }
2010 }
2011
2012 void
handle_pat_pmt_payload(track_c & track,packet_header_t & ts_header,unsigned char * ts_payload,std::size_t ts_payload_size)2013 reader_c::handle_pat_pmt_payload(track_c &track,
2014 packet_header_t &ts_header,
2015 unsigned char *ts_payload,
2016 std::size_t ts_payload_size) {
2017 auto &f = file();
2018
2019 if (processing_state_e::probing != f.m_state)
2020 return;
2021
2022 if (ts_header.is_payload_unit_start()) {
2023 auto to_skip = static_cast<std::size_t>(ts_payload[0]) + 1;
2024
2025 if (to_skip >= ts_payload_size) {
2026 mxdebug_if(m_debug_headers, fmt::format("handle_pat_pmt_payload: error: TS payload size {0} too small; needed to skip {1}\n", ts_payload_size, to_skip));
2027 track.pes_payload_size_to_read = 0;
2028 return;
2029 }
2030
2031 track.clear_pes_payload();
2032 auto pat_table = reinterpret_cast<pat_t *>(ts_payload + to_skip);
2033 ts_payload_size -= to_skip;
2034 ts_payload += to_skip;
2035 track.pes_payload_size_to_read = pat_table->get_section_length() + 3;
2036 }
2037
2038 track.add_pes_payload(ts_payload, ts_payload_size);
2039
2040 if (track.is_pes_payload_complete())
2041 probe_packet_complete(track);
2042 }
2043
2044 drop_decision_e
handle_transport_errors(track_c & track,packet_header_t & ts_header)2045 reader_c::handle_transport_errors(track_c &track,
2046 packet_header_t &ts_header) {
2047 auto decision = drop_decision_e::keep;
2048
2049 if (track.transport_error_detected(ts_header) && !track.m_skip_pes_payload) {
2050 mxdebug_if(m_debug_pes_headers,
2051 fmt::format("handle_transport_errors: error detected for track PID {0} (0x{0:04x}) at {1} packet num {7} ({2}, expected continuity_counter {3} actual {4}); dropping current PES packet (expected size {5} read {6})\n",
2052 track.pid,
2053 file().m_position,
2054 ts_header.has_transport_error() ? "transport_error flag" : "wrong continuity_counter",
2055 track.m_expected_next_continuity_counter ? fmt::to_string(static_cast<unsigned int>(track.m_expected_next_continuity_counter.value())) : "—"s,
2056 static_cast<unsigned int>(ts_header.continuity_counter()),
2057 track.pes_payload_size_to_read,
2058 track.pes_payload_read->get_size(),
2059 m_packet_num));
2060
2061 track.clear_pes_payload();
2062 track.m_skip_pes_payload = true;
2063 decision = drop_decision_e::drop;
2064 }
2065
2066 track.m_expected_next_continuity_counter = (ts_header.continuity_counter() + (ts_header.has_payload() ? 1 : 0)) % 16;
2067
2068 return decision;
2069 }
2070
2071 void
handle_pes_payload(track_c & track,packet_header_t & ts_header,unsigned char * ts_payload,std::size_t ts_payload_size)2072 reader_c::handle_pes_payload(track_c &track,
2073 packet_header_t &ts_header,
2074 unsigned char *ts_payload,
2075 std::size_t ts_payload_size) {
2076 if (ts_header.is_payload_unit_start()) {
2077 if (track.is_pes_payload_size_unbounded() && track.pes_payload_read->get_size())
2078 parse_pes(track);
2079
2080 if (track.pes_payload_size_to_read && track.pes_payload_read->get_size() && m_debug_pes_headers)
2081 mxdebug(fmt::format("handle_pes_payload: error: dropping incomplete PES payload; target size {0} already read {1}\n", track.pes_payload_size_to_read, track.pes_payload_read->get_size()));
2082
2083 track.clear_pes_payload();
2084
2085 if (ts_payload_size < sizeof(pes_header_t)) {
2086 mxdebug_if(m_debug_pes_headers, fmt::format("handle_pes_payload: error: TS payload size {0} too small for PES header {1}\n", ts_payload_size, sizeof(pes_header_t)));
2087 track.m_skip_pes_payload = true;
2088 return;
2089 }
2090
2091 auto const start_code = get_uint24_be(ts_payload);
2092 if (start_code != 0x000001) {
2093 mxdebug_if(m_debug_pes_headers, fmt::format("handle_pes_payload: error: PES header in TS payload does not start with proper start code; actual: {0:06x}\n", start_code));
2094 track.m_skip_pes_payload = true;
2095 return;
2096 }
2097
2098 auto pes_header = reinterpret_cast<pes_header_t *>(ts_payload);
2099 track.pes_payload_size_to_read = pes_header->get_pes_packet_length() + offsetof(pes_header_t, flags1);
2100 track.m_skip_pes_payload = false;
2101 }
2102
2103 if (track.m_skip_pes_payload)
2104 return;
2105
2106 track.add_pes_payload(ts_payload, ts_payload_size);
2107
2108 if (track.is_pes_payload_complete())
2109 parse_pes(track);
2110 }
2111
2112 void
determine_track_type_by_pes_content(track_c & track)2113 reader_c::determine_track_type_by_pes_content(track_c &track) {
2114 auto buffer = track.pes_payload_read->get_buffer();
2115 auto size = track.pes_payload_read->get_size();
2116
2117 if (!size)
2118 return;
2119
2120 if (m_debug_pat_pmt) {
2121 auto data = mtx::string::to_hex(buffer, std::min<unsigned int>(size, 4));
2122 mxdebug(fmt::format("PID {0}: attempting type detection from content for with size {1}; first four bytes: {2}\n", track.pid, size, data));
2123 }
2124
2125 if ((size >= 3) && ((get_uint24_be(buffer) & mtx::aac::ADTS_SYNC_WORD_MASK) == mtx::aac::ADTS_SYNC_WORD)) {
2126 track.type = pid_type_e::audio;
2127 track.codec = codec_c::look_up(codec_c::type_e::A_AAC);
2128
2129 } else if ((size >= 2) && (get_uint16_be(buffer) == mtx::ac3::SYNC_WORD)) {
2130 track.type = pid_type_e::audio;
2131 track.codec = codec_c::look_up(codec_c::type_e::A_AC3);
2132 }
2133
2134 mxdebug_if(m_debug_pat_pmt, fmt::format("Detected type: {0} codec: {1}\n", static_cast<unsigned int>(track.type), track.codec));
2135 }
2136
2137 int
determine_track_parameters(track_c & track,bool end_of_detection)2138 reader_c::determine_track_parameters(track_c &track,
2139 bool end_of_detection) {
2140 if (track.type == pid_type_e::pat)
2141 return parse_pat(track) ? 0 : -1;
2142
2143 else if (track.type == pid_type_e::pmt)
2144 return parse_pmt(track) ? 0 : -1;
2145
2146 else if (track.type == pid_type_e::sdt)
2147 return parse_sdt(track) ? 0 : -1;
2148
2149 else if (track.type == pid_type_e::unknown)
2150 determine_track_type_by_pes_content(track);
2151
2152 if (track.type == pid_type_e::video) {
2153 if (track.codec.is(codec_c::type_e::V_MPEG12))
2154 return track.new_stream_v_mpeg_1_2(end_of_detection);
2155 else if (track.codec.is(codec_c::type_e::V_MPEG4_P10))
2156 return track.new_stream_v_avc(end_of_detection);
2157 else if (track.codec.is(codec_c::type_e::V_MPEGH_P2))
2158 return track.new_stream_v_hevc(end_of_detection);
2159 else if (track.codec.is(codec_c::type_e::V_VC1))
2160 return track.new_stream_v_vc1();
2161
2162 track.pes_payload_read->set_chunk_size(512 * 1024);
2163
2164 } else if (track.type == pid_type_e::subtitles) {
2165 if (track.codec.is(codec_c::type_e::S_HDMV_TEXTST))
2166 return track.new_stream_s_hdmv_textst();
2167
2168 else if (track.codec.is(codec_c::type_e::S_DVBSUB))
2169 return track.new_stream_s_dvbsub();
2170
2171 } else if (track.type != pid_type_e::audio)
2172 return -1;
2173
2174 if (track.codec.is(codec_c::type_e::A_MP3))
2175 return track.new_stream_a_mpeg();
2176 else if (track.codec.is(codec_c::type_e::A_AAC))
2177 return track.new_stream_a_aac();
2178 else if (track.codec.is(codec_c::type_e::A_AC3))
2179 return track.new_stream_a_ac3();
2180 else if (track.codec.is(codec_c::type_e::A_DTS))
2181 return track.new_stream_a_dts();
2182 else if (track.codec.is(codec_c::type_e::A_PCM))
2183 return track.new_stream_a_pcm();
2184 else if (track.codec.is(codec_c::type_e::A_TRUEHD))
2185 return track.new_stream_a_truehd();
2186
2187 return -1;
2188 }
2189
2190 void
probe_packet_complete(track_c & track,bool end_of_detection)2191 reader_c::probe_packet_complete(track_c &track,
2192 bool end_of_detection) {
2193 if (track.probed_ok) {
2194 track.clear_pes_payload();
2195 return;
2196 }
2197
2198 int result = -1;
2199
2200 try {
2201 result = determine_track_parameters(track, end_of_detection);
2202 } catch (...) {
2203 }
2204
2205 track.clear_pes_payload();
2206
2207 if (result != 0) {
2208 mxdebug_if(m_debug_headers, (result == FILE_STATUS_MOREDATA) ? "probe_packet_complete: Need more data to probe ES\n" : "probe_packet_complete: Failed to parse packet. Reset and retry\n");
2209 track.processed = false;
2210
2211 return;
2212 }
2213
2214 if (mtx::included_in(track.type, pid_type_e::pat, pid_type_e::pmt)) {
2215 auto it = std::find_if(m_tracks.begin(), m_tracks.end(), [&track](track_ptr const &candidate) { return candidate.get() == &track; });
2216 if (m_tracks.end() != it)
2217 m_tracks.erase(it);
2218
2219 } else {
2220 auto &f = file();
2221 track.processed = true;
2222 track.probed_ok = true;
2223 --f.m_es_to_process;
2224
2225 if (mtx::included_in(track.type, pid_type_e::audio, pid_type_e::video))
2226 f.m_has_audio_or_video_track = true;
2227
2228 mxdebug_if(m_debug_headers, fmt::format("probe_packet_complete: ES to process: {0}\n", f.m_es_to_process));
2229 }
2230 }
2231
2232 void
create_packetizer(int64_t id)2233 reader_c::create_packetizer(int64_t id) {
2234 if ((0 > id) || (m_tracks.size() <= static_cast<size_t>(id)))
2235 return;
2236
2237 auto &track = m_tracks[id];
2238 auto type = track->type == pid_type_e::audio ? 'a'
2239 : track->type == pid_type_e::video ? 'v'
2240 : 's';
2241
2242 if (!track->probed_ok || (0 == track->ptzr) || !demuxing_requested(type, id, track->language))
2243 return;
2244
2245 m_ti.m_id = id;
2246 m_ti.m_language = track->language;
2247
2248 if (pid_type_e::audio == track->type) {
2249 if (track->codec.is(codec_c::type_e::A_MP3))
2250 track->ptzr = add_packetizer(new mp3_packetizer_c(this, m_ti, track->a_sample_rate, track->a_channels, (0 != track->a_sample_rate) && (0 != track->a_channels)));
2251
2252 else if (track->codec.is(codec_c::type_e::A_AAC))
2253 create_aac_audio_packetizer(track);
2254
2255 else if (track->codec.is(codec_c::type_e::A_AC3))
2256 create_ac3_audio_packetizer(track);
2257
2258 else if (track->codec.is(codec_c::type_e::A_DTS))
2259 track->ptzr = add_packetizer(new dts_packetizer_c(this, m_ti, track->a_dts_header));
2260
2261 else if (track->codec.is(codec_c::type_e::A_PCM))
2262 create_pcm_audio_packetizer(track);
2263
2264 else if (track->codec.is(codec_c::type_e::A_TRUEHD))
2265 create_truehd_audio_packetizer(track);
2266
2267 } else if (pid_type_e::video == track->type) {
2268 if (track->codec.is(codec_c::type_e::V_MPEG12))
2269 create_mpeg1_2_video_packetizer(track);
2270
2271 else if (track->codec.is(codec_c::type_e::V_MPEG4_P10))
2272 create_mpeg4_p10_es_video_packetizer(track);
2273
2274 else if (track->codec.is(codec_c::type_e::V_MPEGH_P2))
2275 create_mpegh_p2_es_video_packetizer(track);
2276
2277 else if (track->codec.is(codec_c::type_e::V_VC1))
2278 create_vc1_video_packetizer(track);
2279
2280 } else if (track->codec.is(codec_c::type_e::S_HDMV_PGS))
2281 create_hdmv_pgs_subtitles_packetizer(track);
2282
2283 else if (track->codec.is(codec_c::type_e::S_HDMV_TEXTST))
2284 create_hdmv_textst_subtitles_packetizer(track);
2285
2286 else if (track->codec.is(codec_c::type_e::S_SRT))
2287 create_srt_subtitles_packetizer(track);
2288
2289 else if (track->codec.is(codec_c::type_e::S_DVBSUB))
2290 create_dvbsub_subtitles_packetizer(track);
2291
2292 if (-1 != track->ptzr) {
2293 auto &packetizer = ptzr(track->ptzr);
2294 m_ptzr_to_track_map[&packetizer] = track;
2295
2296 m_files[track->m_file_num]->m_packetizers.push_back(&packetizer);
2297
2298 track->set_packetizer_source_id();
2299
2300 show_packetizer_info(id, packetizer);
2301 }
2302 }
2303
2304 void
create_aac_audio_packetizer(track_ptr const & track)2305 reader_c::create_aac_audio_packetizer(track_ptr const &track) {
2306 auto aac_packetizer = new aac_packetizer_c(this, m_ti, track->m_aac_frame.m_header.config, aac_packetizer_c::headerless);
2307 track->ptzr = add_packetizer(aac_packetizer);
2308 track->converter = std::make_shared<aac_framing_packet_converter_c>(&ptzr(track->ptzr), track->m_aac_multiplex_type);
2309
2310 if (mtx::aac::PROFILE_SBR == track->m_aac_frame.m_header.config.profile)
2311 aac_packetizer->set_audio_output_sampling_freq(track->m_aac_frame.m_header.config.sample_rate * 2);
2312 }
2313
2314 void
create_ac3_audio_packetizer(track_ptr const & track)2315 reader_c::create_ac3_audio_packetizer(track_ptr const &track) {
2316 track->ptzr = add_packetizer(new ac3_packetizer_c(this, m_ti, track->a_sample_rate, track->a_channels, track->a_bsid));
2317
2318 if (track->converter)
2319 dynamic_cast<truehd_ac3_splitting_packet_converter_c &>(*track->converter).set_ac3_packetizer(&ptzr(track->ptzr));
2320 }
2321
2322 void
create_pcm_audio_packetizer(track_ptr const & track)2323 reader_c::create_pcm_audio_packetizer(track_ptr const &track) {
2324 track->ptzr = add_packetizer(new pcm_packetizer_c(this, m_ti, track->a_sample_rate, track->a_channels, track->a_bits_per_sample, pcm_packetizer_c::big_endian_integer));
2325
2326 if (track->converter)
2327 track->converter->set_packetizer(&ptzr(track->ptzr));
2328 }
2329
2330 void
create_truehd_audio_packetizer(track_ptr const & track)2331 reader_c::create_truehd_audio_packetizer(track_ptr const &track) {
2332 track->ptzr = add_packetizer(new truehd_packetizer_c(this, m_ti, mtx::truehd::frame_t::truehd, track->a_sample_rate, track->a_channels));
2333
2334 if (track->converter)
2335 dynamic_cast<truehd_ac3_splitting_packet_converter_c &>(*track->converter).set_packetizer(&ptzr(track->ptzr));
2336 }
2337
2338 void
create_mpeg1_2_video_packetizer(track_ptr & track)2339 reader_c::create_mpeg1_2_video_packetizer(track_ptr &track) {
2340 m_ti.m_private_data = track->m_codec_private_data;
2341 auto m2vpacketizer = new mpeg1_2_video_packetizer_c(this, m_ti, track->v_version, mtx::to_int(track->m_default_duration), track->v_width, track->v_height, track->v_dwidth, track->v_dheight, false);
2342 track->ptzr = add_packetizer(m2vpacketizer);
2343
2344 m2vpacketizer->set_video_interlaced_flag(track->v_interlaced);
2345 }
2346
2347 void
create_mpeg4_p10_es_video_packetizer(track_ptr & track)2348 reader_c::create_mpeg4_p10_es_video_packetizer(track_ptr &track) {
2349 auto ptzr = new avc_es_video_packetizer_c(this, m_ti);
2350 track->ptzr = add_packetizer(ptzr);
2351 ptzr->set_video_pixel_dimensions(track->v_width, track->v_height);
2352 }
2353
2354 void
create_mpegh_p2_es_video_packetizer(track_ptr & track)2355 reader_c::create_mpegh_p2_es_video_packetizer(track_ptr &track) {
2356 auto ptzr = new hevc_es_video_packetizer_c(this, m_ti);
2357 track->ptzr = add_packetizer(ptzr);
2358 ptzr->set_video_pixel_dimensions(track->v_width, track->v_height);
2359 }
2360
2361 void
create_vc1_video_packetizer(track_ptr & track)2362 reader_c::create_vc1_video_packetizer(track_ptr &track) {
2363 track->m_use_dts = true;
2364 track->ptzr = add_packetizer(new vc1_video_packetizer_c(this, m_ti));
2365 }
2366
2367 void
create_hdmv_pgs_subtitles_packetizer(track_ptr & track)2368 reader_c::create_hdmv_pgs_subtitles_packetizer(track_ptr &track) {
2369 auto ptzr = new hdmv_pgs_packetizer_c(this, m_ti);
2370 ptzr->set_aggregate_packets(true);
2371 track->ptzr = add_packetizer(ptzr);
2372 }
2373
2374 void
create_hdmv_textst_subtitles_packetizer(track_ptr const & track)2375 reader_c::create_hdmv_textst_subtitles_packetizer(track_ptr const &track) {
2376 track->ptzr = add_packetizer(new hdmv_textst_packetizer_c(this, m_ti, track->m_codec_private_data));
2377 }
2378
2379 void
create_srt_subtitles_packetizer(track_ptr const & track)2380 reader_c::create_srt_subtitles_packetizer(track_ptr const &track) {
2381 auto recoding_requested = mtx::includes(m_ti.m_sub_charsets, track->m_id) || mtx::includes(m_ti.m_sub_charsets, track->m_id);
2382 track->ptzr = add_packetizer(new textsubs_packetizer_c(this, m_ti, MKV_S_TEXTUTF8, recoding_requested));
2383
2384 auto &converter = dynamic_cast<teletext_to_srt_packet_converter_c &>(*track->converter);
2385
2386 converter.demux_page(*track->m_ttx_wanted_page, &ptzr(track->ptzr));
2387 converter.override_encoding(*track->m_ttx_wanted_page, track->language.get_iso639_alpha_3_code());
2388 }
2389
2390 void
create_dvbsub_subtitles_packetizer(track_ptr const & track)2391 reader_c::create_dvbsub_subtitles_packetizer(track_ptr const &track) {
2392 track->ptzr = add_packetizer(new dvbsub_packetizer_c{this, m_ti, track->m_codec_private_data});
2393 track->converter.reset(new dvbsub_pes_framing_removal_packet_converter_c{&ptzr(track->ptzr)});
2394 }
2395
2396 void
create_packetizers()2397 reader_c::create_packetizers() {
2398 determine_global_timestamp_offset();
2399
2400 mxdebug_if(m_debug_headers, fmt::format("create_packetizers: create packetizers...\n"));
2401 for (int i = 0, end = m_tracks.size(); i < end; ++i)
2402 create_packetizer(i);
2403 }
2404
2405 void
add_available_track_ids()2406 reader_c::add_available_track_ids() {
2407 add_available_track_id_range(0, m_tracks.size() - 1);
2408
2409 if (m_chapters)
2410 add_available_track_id(track_info_c::chapter_track_id);
2411 }
2412
2413 bool
all_files_done() const2414 reader_c::all_files_done()
2415 const {
2416 for (auto const &file : m_files)
2417 if (!file->m_file_done)
2418 return false;
2419
2420 return true;
2421 }
2422
2423 file_status_e
finish()2424 reader_c::finish() {
2425 if (all_files_done()) {
2426 m_bytes_processed = m_bytes_to_process;
2427 return flush_packetizers();
2428 }
2429
2430 for (auto &track : m_tracks) {
2431 if (track->m_file_num != m_current_file)
2432 continue;
2433
2434 if ((-1 != track->ptzr) && (0 < track->pes_payload_read->get_size()))
2435 parse_pes(*track);
2436
2437 if (track->converter)
2438 track->converter->flush();
2439
2440 if (-1 != track->ptzr)
2441 ptzr(track->ptzr).flush();
2442 }
2443
2444 file().m_file_done = true;
2445
2446 return FILE_STATUS_DONE;
2447 }
2448
2449 file_status_e
read(generic_packetizer_c * requested_ptzr,bool force)2450 reader_c::read(generic_packetizer_c *requested_ptzr,
2451 bool force) {
2452 if (all_files_done())
2453 return flush_packetizers();
2454
2455 auto &requested_ptzr_track = m_ptzr_to_track_map[requested_ptzr];
2456 if (!requested_ptzr_track)
2457 return flush_packetizers();
2458
2459 m_current_file = requested_ptzr_track->m_file_num;
2460 auto &f = file();
2461 auto num_queued_bytes = f.get_queued_bytes();
2462
2463 if (!force && (20 * 1024 * 1024 < num_queued_bytes)) {
2464 if ( !requested_ptzr_track
2465 || !mtx::included_in(requested_ptzr_track->type, pid_type_e::audio, pid_type_e::video)
2466 || (512 * 1024 * 1024 < num_queued_bytes))
2467 return FILE_STATUS_HOLDING;
2468 }
2469
2470 f.m_packet_sent_to_packetizer = false;
2471 auto prior_position = f.m_in->getFilePointer();
2472
2473 unsigned char buf[TS_MAX_PACKET_SIZE + 1];
2474
2475 while (!f.m_packet_sent_to_packetizer) {
2476 f.m_position = f.m_in->getFilePointer();
2477
2478 if (f.m_in->read(buf, f.m_detected_packet_size) != static_cast<unsigned int>(f.m_detected_packet_size))
2479 return finish();
2480
2481 if (buf[0] != 0x47) {
2482 if (resync(f.m_position))
2483 continue;
2484 return finish();
2485 }
2486
2487 ++m_packet_num;
2488
2489 parse_packet(buf);
2490 }
2491
2492 m_bytes_processed += f.m_in->getFilePointer() - prior_position;
2493
2494 return FILE_STATUS_MOREDATA;
2495 }
2496
2497 void
parse_clip_info_file(std::size_t file_idx)2498 reader_c::parse_clip_info_file(std::size_t file_idx) {
2499 auto &file = *m_files[file_idx];
2500 auto mpls_multi_in = dynamic_cast<mm_mpls_multi_file_io_c *>(get_underlying_input(file.m_in.get()));
2501 auto source_file = mpls_multi_in ? mpls_multi_in->get_file_names()[0] : mtx::fs::to_path(file.m_in->get_file_name());
2502
2503 mxdebug_if(m_debug_clpi, fmt::format("find_clip_info_file: Searching for CLPI corresponding to {0}\n", source_file.u8string()));
2504
2505 auto clpi_file = mtx::bluray::find_other_file(source_file, mtx::fs::to_path("CLIPINF") / mtx::fs::to_path(fmt::format("{0}.clpi", source_file.stem().u8string())));
2506
2507 mxdebug_if(m_debug_clpi, fmt::format("reader_c::find_clip_info_file: CLPI file: {0}\n", !clpi_file.empty() ? clpi_file.u8string() : "not found"));
2508
2509 if (clpi_file.empty())
2510 return;
2511
2512 file.m_clpi_parser.reset(new mtx::bluray::clpi::parser_c{clpi_file.u8string()});
2513 if (!file.m_clpi_parser->parse()) {
2514 file.m_clpi_parser.reset();
2515 return;
2516 }
2517
2518 for (auto &track : m_tracks) {
2519 if (track->m_file_num != file_idx)
2520 continue;
2521
2522 bool found = false;
2523
2524 for (auto &program : file.m_clpi_parser->m_programs) {
2525 for (auto &stream : program->program_streams) {
2526 if ((stream->pid != track->pid) || !stream->language.is_valid())
2527 continue;
2528
2529 track->language = stream->language;
2530 found = true;
2531 break;
2532 }
2533
2534 if (found)
2535 break;
2536 }
2537 }
2538 }
2539
2540 bool
resync(int64_t start_at)2541 reader_c::resync(int64_t start_at) {
2542 auto &f = file();
2543
2544 try {
2545 mxdebug_if(m_debug_resync, fmt::format("resync: Start resync for data from {0}\n", start_at));
2546 f.m_in->setFilePointer(start_at);
2547
2548 unsigned char buf[TS_MAX_PACKET_SIZE + 1];
2549
2550 while (!f.m_in->eof()) {
2551 auto curr_pos = f.m_in->getFilePointer();
2552 buf[0] = f.m_in->read_uint8();
2553
2554 if (0x47 != buf[0])
2555 continue;
2556
2557 if (f.m_in->read(&buf[1], f.m_detected_packet_size) != static_cast<unsigned int>(f.m_detected_packet_size))
2558 return false;
2559
2560 if (0x47 != buf[f.m_detected_packet_size]) {
2561 f.m_in->setFilePointer(curr_pos + 1);
2562 continue;
2563 }
2564
2565 mxdebug_if(m_debug_resync, fmt::format("resync: Re-established at {0}\n", curr_pos));
2566
2567 f.m_in->setFilePointer(curr_pos);
2568 return true;
2569 }
2570
2571 } catch (...) {
2572 return false;
2573 }
2574
2575 return false;
2576 }
2577
2578 track_ptr
find_track_for_pid(uint16_t pid) const2579 reader_c::find_track_for_pid(uint16_t pid)
2580 const {
2581 auto &f = *m_files[m_current_file];
2582
2583 for (auto const &track : m_tracks) {
2584 if ( (track->m_file_num != m_current_file)
2585 || (track->pid != pid))
2586 continue;
2587
2588 if (track->has_packetizer() || mtx::included_in(f.m_state, processing_state_e::probing, processing_state_e::determining_timestamp_offset))
2589 return track;
2590
2591 for (auto const &coupled_track : track->m_coupled_tracks)
2592 if (coupled_track->has_packetizer())
2593 return coupled_track;
2594
2595 return track;
2596 }
2597
2598 return {};
2599 }
2600
2601 std::pair<unsigned char *, std::size_t>
determine_ts_payload_start(packet_header_t * hdr) const2602 reader_c::determine_ts_payload_start(packet_header_t *hdr)
2603 const {
2604 auto ts_header_start = reinterpret_cast<unsigned char *>(hdr);
2605 auto ts_payload_start = ts_header_start + sizeof(packet_header_t);
2606
2607 if (hdr->has_adaptation_field())
2608 // Adaptation field's first byte is its length - 1.
2609 ts_payload_start += ts_payload_start[0] + 1;
2610
2611 // Make sure not to overflow the TS packet buffer.
2612 ts_payload_start = std::min(ts_payload_start, ts_header_start + TS_PACKET_SIZE);
2613
2614 return { ts_payload_start, static_cast<std::size_t>(ts_header_start + TS_PACKET_SIZE - ts_payload_start) };
2615 }
2616
2617 file_t &
file()2618 reader_c::file() {
2619 return *m_files[m_current_file];
2620 }
2621
2622 void
add_external_files_from_mpls(mm_mpls_multi_file_io_c & mpls_in)2623 reader_c::add_external_files_from_mpls(mm_mpls_multi_file_io_c &mpls_in) {
2624 auto source_file = mpls_in.get_file_names()[0];
2625 auto parser = mpls_in.get_mpls_parser();
2626 auto &playlist = parser.get_playlist();
2627 auto sub_path_idx = 0u;
2628
2629 if (!playlist.items.empty()) {
2630 auto &item = playlist.items.front();
2631 auto &file = m_files.front();
2632
2633 file->m_timestamp_restriction_min = item.in_time;
2634 file->m_timestamp_restriction_max = item.out_time;
2635
2636 mxdebug_if(m_debug_mpls, fmt::format("add_external_files_from_mpls: main restrictions for {0} min {1} max {2}\n", mpls_in.get_file_name(), item.in_time, item.out_time));
2637 }
2638
2639 if (playlist.sub_paths.empty())
2640 return;
2641
2642 for (auto const &sub_path : playlist.sub_paths) {
2643 ++sub_path_idx;
2644
2645 if ((mtx::bluray::mpls::sub_path_type_e::text_subtitle_presentation != sub_path.type) || sub_path.items.empty())
2646 continue;
2647
2648 auto &item = sub_path.items.front();
2649 auto m2ts = mtx::bluray::find_other_file(mtx::fs::to_path(source_file), mtx::fs::to_path("STREAM") / mtx::fs::to_path(fmt::format("{0}.m2ts", mtx::fs::to_path(item.clpi_file_name).stem().u8string())));
2650
2651 mxdebug_if(m_debug_mpls, fmt::format("add_external_files_from_mpls: M2TS for sub_path {0}: {1}\n", sub_path_idx - 1, !m2ts.empty() ? m2ts.u8string() : "not found"));
2652
2653 if (m2ts.empty())
2654 continue;
2655
2656 try {
2657 auto in = std::make_shared<mm_file_io_c>(m2ts.u8string(), MODE_READ);
2658 auto file = std::make_shared<file_t>(std::static_pointer_cast<mm_io_c>(in));
2659
2660 file->m_timestamp_restriction_min = item.in_time;
2661 file->m_timestamp_restriction_max = item.out_time;
2662 file->m_timestamp_mpls_sync = item.sync_start_pts_of_playitem;
2663
2664 m_files.push_back(file);
2665
2666 mxdebug_if(m_debug_mpls, fmt::format("add_external_files_from_mpls: sub_path file num {0} name {1} ts_rec_min {2} ts_rec_max {3} ts_mpls_sync {4}\n",
2667 m_files.size() - 1, m2ts.u8string(), file->m_timestamp_restriction_min, file->m_timestamp_restriction_max, file->m_timestamp_mpls_sync));
2668
2669 } catch (mtx::mm_io::exception &ex) {
2670 mxdebug_if(m_debug_mpls, fmt::format("add_external_files_from_mpls: could not open {0}: {1}\n", m2ts.u8string(), ex.error()));
2671 }
2672 }
2673 }
2674
2675 int64_t
get_progress()2676 reader_c::get_progress() {
2677 return m_bytes_processed;
2678 }
2679
2680 int64_t
get_maximum_progress()2681 reader_c::get_maximum_progress() {
2682 return m_bytes_to_process;
2683 }
2684
2685 }
2686