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 PS (program stream) demultiplexer module
10
11 Written by Moritz Bunkus <moritz@bunkus.org>.
12 */
13
14 #include "common/common_pch.h"
15
16 #include <QRegularExpression>
17
18 #include "common/ac3.h"
19 #include "common/bit_reader.h"
20 #include "common/debugging.h"
21 #include "common/endian.h"
22 #include "common/error.h"
23 #include "common/id_info.h"
24 #include "common/mp3.h"
25 #include "common/mpeg.h"
26 #include "common/mpeg1_2.h"
27 #include "common/path.h"
28 #include "common/qt.h"
29 #include "common/strings/formatting.h"
30 #include "common/truehd.h"
31 #include "input/r_mpeg_ps.h"
32 #include "merge/file_status.h"
33 #include "mpegparser/M2VParser.h"
34 #include "output/p_ac3.h"
35 #include "output/p_avc_es.h"
36 #include "output/p_dts.h"
37 #include "output/p_mp3.h"
38 #include "output/p_mpeg1_2.h"
39 #include "output/p_pcm.h"
40 #include "output/p_truehd.h"
41 #include "output/p_vc1.h"
42
43 bool
probe_file()44 mpeg_ps_reader_c::probe_file() {
45 unsigned char buf[4];
46
47 if (m_in->read(buf, 4) != 4)
48 return false;
49
50 if (get_uint32_be(buf) == mtx::mpeg1_2::PACKET_START_CODE)
51 return true;
52
53 m_in->setFilePointer(0);
54
55 auto mem = memory_c::alloc(32 * 1024);
56 auto num_read = m_in->read(mem, mem->get_size());
57
58 if (num_read < 4)
59 return false;
60
61 auto base = mem->get_buffer();
62 auto code = get_uint32_be(base);
63 auto offset = 2u;
64 auto system_header_start_code_found = false;
65 auto packet_start_code_found = false;
66
67 while( ((offset + 4) < num_read)
68 && (!system_header_start_code_found || !packet_start_code_found)) {
69 ++offset;
70 code = (code << 8) | base[offset];
71
72 if (code == mtx::mpeg1_2::SYSTEM_HEADER_START_CODE)
73 system_header_start_code_found = true;
74
75 else if (code == mtx::mpeg1_2::PACKET_START_CODE)
76 packet_start_code_found = true;
77 }
78
79 return system_header_start_code_found && packet_start_code_found;
80 }
81
82 void
read_headers()83 mpeg_ps_reader_c::read_headers() {
84 try {
85 uint8_t byte;
86
87 if (!m_ti.m_disable_multi_file && Q(mtx::fs::to_path(m_ti.m_fname).filename()).contains(QRegularExpression{"^vts_\\d+_\\d+", QRegularExpression::CaseInsensitiveOption})) {
88 m_in.reset(); // Close the source file first before opening it a second time.
89 m_in = mm_multi_file_io_c::open_multi(m_ti.m_fname, false);
90 }
91
92 m_size = m_in->get_size();
93 m_probe_range = calculate_probe_range(m_size, 10 * 1024 * 1024);
94 uint32_t header = m_in->read_uint32_be();
95 bool done = m_in->eof();
96 version = -1;
97
98 while (!done) {
99 uint8_t stream_id;
100 uint16_t pes_packet_length;
101
102 switch (header) {
103 case mtx::mpeg1_2::PACKET_START_CODE:
104 mxdebug_if(m_debug_headers, fmt::format("mpeg_ps: packet start at {0}\n", m_in->getFilePointer() - 4));
105
106 if (-1 == version) {
107 byte = m_in->read_uint8();
108 if ((byte & 0xc0) != 0)
109 version = 2; // MPEG-2 PS
110 else
111 version = 1;
112 m_in->skip(-1);
113 }
114
115 m_in->skip(2 * 4); // pack header
116 if (2 == version) {
117 m_in->skip(1);
118 byte = m_in->read_uint8() & 0x07;
119 m_in->skip(byte); // stuffing bytes
120 }
121 header = m_in->read_uint32_be();
122 break;
123
124 case mtx::mpeg1_2::SYSTEM_HEADER_START_CODE:
125 mxdebug_if(m_debug_headers, fmt::format("mpeg_ps: system header start code at {0}\n", m_in->getFilePointer() - 4));
126
127 m_in->skip(2 * 4); // system header
128 byte = m_in->read_uint8();
129 while ((byte & 0x80) == 0x80) {
130 m_in->skip(2); // P-STD info
131 byte = m_in->read_uint8();
132 }
133 m_in->skip(-1);
134 header = m_in->read_uint32_be();
135 break;
136
137 case mtx::mpeg1_2::MPEG_PROGRAM_END_CODE:
138 done = !resync_stream(header);
139 break;
140
141 case mtx::mpeg1_2::PROGRAM_STREAM_MAP_START_CODE:
142 parse_program_stream_map();
143 done = !resync_stream(header);
144 break;
145
146 default:
147 if (!mtx::mpeg::is_start_code(header)) {
148 mxdebug_if(m_debug_headers, fmt::format("mpeg_ps: unknown header 0x{0:08x} at {1}\n", header, m_in->getFilePointer() - 4));
149 done = !resync_stream(header);
150 break;
151 }
152
153 stream_id = header & 0xff;
154 m_in->save_pos();
155 found_new_stream(stream_id);
156 m_in->restore_pos();
157 pes_packet_length = m_in->read_uint16_be();
158
159 mxdebug_if(m_debug_headers, fmt::format("mpeg_ps: id 0x{0:02x} len {1} at {2}\n", static_cast<unsigned int>(stream_id), pes_packet_length, m_in->getFilePointer() - 4 - 2));
160
161 m_in->skip(pes_packet_length);
162
163 header = m_in->read_uint32_be();
164
165 break;
166 }
167
168 done |= m_in->eof() || (m_in->getFilePointer() >= m_probe_range);
169 } // while (!done)
170
171 } catch (...) {
172 }
173
174 sort_tracks();
175 calculate_global_timestamp_offset();
176
177 m_in->setFilePointer(0);
178
179 if (verbose) {
180 show_demuxer_info();
181 auto multi_in = dynamic_cast<mm_multi_file_io_c *>(get_underlying_input());
182 if (multi_in)
183 multi_in->display_other_file_info();
184 }
185 }
186
187 void
sort_tracks()188 mpeg_ps_reader_c::sort_tracks() {
189 size_t i;
190
191 for (i = 0; tracks.size() > i; ++i)
192 tracks[i]->sort_key = ( 'v' == tracks[i]->type ? 0x00000
193 : 'a' == tracks[i]->type ? 0x10000
194 : 's' == tracks[i]->type ? 0x20000
195 : 0x30000)
196 + tracks[i]->id.idx();
197
198 std::sort(tracks.begin(), tracks.end());
199
200 for (i = 0; tracks.size() > i; ++i)
201 id2idx[tracks[i]->id.idx()] = i;
202
203 if (!m_debug_headers)
204 return;
205
206 auto info = "mpeg_ps: Supported streams, sorted by ID: "s;
207 for (i = 0; tracks.size() > i; ++i)
208 info += fmt::format("0x{0:02x}(0x{1:02x}) ", tracks[i]->id.id, tracks[i]->id.sub_id);
209
210 mxdebug(info + "\n");
211 }
212
213 void
calculate_global_timestamp_offset()214 mpeg_ps_reader_c::calculate_global_timestamp_offset() {
215 // Calculate by how much the timestamps have to be offset
216 if (tracks.empty())
217 return;
218
219 for (auto &track : tracks)
220 track->timestamp_offset -= track->timestamp_b_frame_offset;
221
222 auto const &track_min_offset = *std::min_element(tracks.begin(), tracks.end(), [](mpeg_ps_track_ptr const &a, mpeg_ps_track_ptr const &b) { return a->timestamp_offset < b->timestamp_offset; });
223 global_timestamp_offset = std::numeric_limits<int64_t>::max() == track_min_offset->timestamp_offset ? 0 : track_min_offset->timestamp_offset;
224
225 for (auto &track : tracks)
226 track->timestamp_offset = std::numeric_limits<int64_t>::max() == track->timestamp_offset ? global_timestamp_offset : track->timestamp_offset - global_timestamp_offset;
227
228 if (!m_debug_timestamps)
229 return;
230
231 std::string output = fmt::format("mpeg_ps: Timestamp offset: min was {0} ", global_timestamp_offset);
232 for (auto const &track : tracks)
233 output += fmt::format("{0}={1} ", track->id, track->timestamp_offset);
234 mxdebug(output + "\n");
235 }
236
237 bool
read_timestamp(int c,int64_t & timestamp)238 mpeg_ps_reader_c::read_timestamp(int c,
239 int64_t ×tamp) {
240 int d = m_in->read_uint16_be();
241 int e = m_in->read_uint16_be();
242
243 if (((c & 1) != 1) || ((d & 1) != 1) || ((e & 1) != 1))
244 return false;
245
246 timestamp = (int64_t)((((c >> 1) & 7) << 30) | ((d >> 1) << 15) | (e >> 1)) * 100000ll / 9;
247
248 return true;
249 }
250
251 bool
read_timestamp(mtx::bits::reader_c & bc,int64_t & timestamp)252 mpeg_ps_reader_c::read_timestamp(mtx::bits::reader_c &bc,
253 int64_t ×tamp) {
254 bc.skip_bits(4);
255 int64_t temp_timestamp = bc.get_bits(3);
256 if (1 != bc.get_bit())
257 return false;
258 temp_timestamp = (temp_timestamp << 15) | bc.get_bits(15);
259 if (1 != bc.get_bit())
260 return false;
261 temp_timestamp = (temp_timestamp << 15) | bc.get_bits(15);
262 if (1 != bc.get_bit())
263 return false;
264
265 timestamp = temp_timestamp * 100000ll / 9;
266
267 return true;
268 }
269
270 void
parse_program_stream_map()271 mpeg_ps_reader_c::parse_program_stream_map() {
272 int len = 0;
273 int64_t pos = m_in->getFilePointer();
274
275 try {
276 len = m_in->read_uint16_be();
277
278 if (!len || (1018 < len))
279 throw false;
280
281 m_in->skip(2);
282
283 int prog_len = m_in->read_uint16_be();
284 m_in->skip(prog_len);
285
286 int es_map_len = m_in->read_uint16_be();
287 es_map_len = std::min(es_map_len, len - prog_len - 8);
288
289 while (4 <= es_map_len) {
290 int type = m_in->read_uint8();
291 int id = m_in->read_uint8();
292 es_map[id] = type;
293
294 int plen = m_in->read_uint16_be();
295 plen = std::min(plen, es_map_len);
296 m_in->skip(plen);
297 es_map_len -= 4 + plen;
298 }
299
300 } catch (...) {
301 }
302
303 m_in->setFilePointer(pos + len);
304 }
305
306 mpeg_ps_packet_c
parse_packet(mpeg_ps_id_t id,bool read_data)307 mpeg_ps_reader_c::parse_packet(mpeg_ps_id_t id,
308 bool read_data) {
309 mpeg_ps_packet_c packet{id};
310
311 packet.m_id.sub_id = 0;
312 packet.m_length = m_in->read_uint16_be();
313 packet.m_full_length = packet.m_length;
314
315 if ( (0xbc > packet.m_id.id)
316 || ((0xf0 <= packet.m_id.id) && (0xfd != packet.m_id.id))
317 || (0xbf == packet.m_id.id)) { // private 2 stream
318 m_in->skip(packet.m_length);
319 return packet;
320 }
321
322 if (0xbe == packet.m_id.id) { // padding stream
323 int64_t pos = m_in->getFilePointer();
324 m_in->skip(packet.m_length);
325 uint32_t header = m_in->read_uint32_be();
326 if (mtx::mpeg::is_start_code(header))
327 m_in->setFilePointer(pos + packet.m_length);
328
329 else {
330 mxdebug_if(m_debug_packets, fmt::format("mpeg_ps: [begin] padding stream length incorrect at {0}, find next header...\n", pos - 6));
331 m_in->setFilePointer(pos);
332 header = 0xffffffff;
333 if (resync_stream(header)) {
334 packet.m_full_length = m_in->getFilePointer() - pos - 4;
335 mxdebug_if(m_debug_packets, fmt::format("mpeg_ps: [end] padding stream length adjusted from {0} to {1}\n", packet.m_length, packet.m_full_length));
336 m_in->setFilePointer(pos + packet.m_full_length);
337 }
338 }
339
340 return packet;
341 }
342
343 if (0 == packet.m_length)
344 return packet;
345
346 uint8_t c = 0;
347 // Skip stuFFing bytes
348 while (0 < packet.m_length) {
349 c = m_in->read_uint8();
350 packet.m_length--;
351 if (c != 0xff)
352 break;
353 }
354
355 // Skip STD buffer size
356 if ((c & 0xc0) == 0x40) {
357 if (2 > packet.m_length)
358 return packet;
359 packet.m_length -= 2;
360 m_in->skip(1);
361 c = m_in->read_uint8();
362 }
363
364 // Presentation time stamp
365 if ((c & 0xf0) == 0x20) {
366 if ((4 > packet.m_length) || !read_timestamp(c, packet.m_pts))
367 return packet;
368 packet.m_length -= 4;
369
370 } else if ((c & 0xf0) == 0x30) {
371 if ((9 > packet.m_length) || !read_timestamp(c, packet.m_pts) || !read_timestamp(m_in->read_uint8(), packet.m_dts))
372 return packet;
373 packet.m_length -= 4 + 5;
374
375 } else if ((c & 0xc0) == 0x80) {
376 if ((c & 0x30) != 0x00)
377 mxerror_fn(m_ti.m_fname, Y("Reading encrypted VOBs is not supported.\n"));
378
379 if (2 > packet.m_length)
380 return packet;
381
382 unsigned int flags = m_in->read_uint8();
383 unsigned int hdrlen = m_in->read_uint8();
384 packet.m_length -= 2;
385
386 if (hdrlen > packet.m_length)
387 return packet;
388
389 packet.m_length -= hdrlen;
390
391 auto af_header = memory_c::alloc(hdrlen);
392 if (m_in->read(af_header->get_buffer(), hdrlen) != hdrlen)
393 return packet;
394
395 mtx::bits::reader_c bc(af_header->get_buffer(), hdrlen);
396
397 try {
398 // PTS
399 if (0x80 == (flags & 0x80))
400 read_timestamp(bc, packet.m_pts);
401
402 // DTS
403 if (0x40 == (flags & 0x40))
404 read_timestamp(bc, packet.m_dts);
405
406 // PES extension?
407 if ((0xfd == packet.m_id.id) && (0x01 == (flags & 0x01))) {
408 int pes_ext_flags = bc.get_bits(8);
409
410 if (0x80 == (pes_ext_flags & 0x80)) {
411 // PES private data
412 bc.skip_bits(128);
413 }
414
415 if (0x40 == (pes_ext_flags & 0x40)) {
416 // pack header field
417 int pack_header_field_len = bc.get_bits(8);
418 bc.skip_bits(8 * pack_header_field_len);
419 }
420
421 if (0x20 == (pes_ext_flags & 0x20)) {
422 // program packet sequence counter
423 bc.skip_bits(16);
424 }
425
426 if (0x10 == (pes_ext_flags & 0x10)) {
427 // P-STD buffer
428 bc.skip_bits(16);
429 }
430
431 if (0x01 == (pes_ext_flags & 0x01)) {
432 bc.skip_bits(1);
433 int pes_ext2_len = bc.get_bits(7);
434
435 if (0 < pes_ext2_len)
436 packet.m_id.sub_id = bc.get_bits(8);
437 }
438 }
439 } catch (...) {
440 }
441
442 if (0xbd == packet.m_id.id) { // DVD audio substream
443 if (4 > packet.m_length)
444 return packet;
445 packet.m_id.sub_id = m_in->read_uint8();
446 packet.m_length--;
447
448 if ((packet.m_id.sub_id & 0xe0) == 0x20)
449 // Subtitles, not supported yet.
450 return packet;
451
452 else if ( ((0x80 <= packet.m_id.sub_id) && (0x8f >= packet.m_id.sub_id))
453 || ((0x98 <= packet.m_id.sub_id) && (0xcf >= packet.m_id.sub_id))) {
454 // Number of frames, startpos. MLP/TrueHD audio has a 4 byte header.
455 auto audio_header_len = (0xb0 <= packet.m_id.sub_id) && (0xbf >= packet.m_id.sub_id) ? 4u : 3u;
456 if (audio_header_len > packet.m_length)
457 return packet;
458
459 m_in->skip(audio_header_len);
460 packet.m_length -= audio_header_len;
461 }
462 }
463
464 } else if (0x0f != c)
465 return packet;
466
467 if (!read_data)
468 packet.m_valid = true;
469
470 else if (0 != packet.m_length)
471 try {
472 packet.m_buffer = memory_c::alloc(packet.m_length);
473 packet.m_valid = m_in->read(packet.m_buffer, packet.m_length) == packet.m_length;
474
475 } catch (mtx::mm_io::exception &ex) {
476 packet.m_valid = false;
477 }
478
479 return packet;
480 }
481
482 void
new_stream_v_avc_or_mpeg_1_2(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)483 mpeg_ps_reader_c::new_stream_v_avc_or_mpeg_1_2(mpeg_ps_id_t id,
484 unsigned char *buf,
485 unsigned int length,
486 mpeg_ps_track_ptr &track) {
487 try {
488 m_in->save_pos();
489
490 mtx::bytes::buffer_c buffer;
491 buffer.add(buf, length);
492
493 bool mpeg_12_seqhdr_found = false;
494 bool mpeg_12_picture_found = false;
495
496 bool avc_seq_param_found = false;
497 bool avc_pic_param_found = false;
498 bool avc_slice_found = false;
499 bool avc_access_unit_found = false;
500
501 uint64_t marker = 0;
502 int pos = 0;
503
504 while (4 > buffer.get_size()) {
505 if (!find_next_packet_for_id(id, m_probe_range))
506 throw false;
507
508 auto packet = parse_packet(id);
509 if (!packet)
510 continue;
511
512 buffer.add(packet.m_buffer->get_buffer(), packet.m_length);
513 }
514
515 marker = get_uint32_be(buffer.get_buffer());
516 if (mtx::avc_hevc::NALU_START_CODE == marker) {
517 m_in->restore_pos();
518 new_stream_v_avc(id, buf, length, track);
519 return;
520 }
521
522 while (1) {
523 unsigned char *ptr = buffer.get_buffer();
524 int buffer_size = buffer.get_size();
525
526 while (buffer_size > pos) {
527 marker <<= 8;
528 marker |= ptr[pos];
529 ++pos;
530
531 if (((marker >> 8) & 0xffffffff) == 0x00000001) {
532 // AVC
533 int type = marker & 0x1f;
534
535 switch (type) {
536 case mtx::avc::NALU_TYPE_SEQ_PARAM:
537 avc_seq_param_found = true;
538 break;
539
540 case mtx::avc::NALU_TYPE_PIC_PARAM:
541 avc_pic_param_found = true;
542 break;
543
544 case mtx::avc::NALU_TYPE_NON_IDR_SLICE:
545 case mtx::avc::NALU_TYPE_DP_A_SLICE:
546 case mtx::avc::NALU_TYPE_DP_B_SLICE:
547 case mtx::avc::NALU_TYPE_DP_C_SLICE:
548 case mtx::avc::NALU_TYPE_IDR_SLICE:
549 avc_slice_found = true;
550 break;
551
552 case mtx::avc::NALU_TYPE_ACCESS_UNIT:
553 avc_access_unit_found = true;
554 break;
555 }
556 }
557
558 if (mtx::mpeg::is_start_code(marker)) {
559 // MPEG-1 or -2
560 switch (marker & 0xffffffff) {
561 case mtx::mpeg1_2::SEQUENCE_HEADER_START_CODE:
562 mpeg_12_seqhdr_found = true;
563 break;
564
565 case mtx::mpeg1_2::PICTURE_START_CODE:
566 mpeg_12_picture_found = true;
567 break;
568 }
569
570 if (mpeg_12_seqhdr_found && mpeg_12_picture_found) {
571 m_in->restore_pos();
572 new_stream_v_mpeg_1_2(id, buf, length, track);
573 return;
574 }
575 }
576 }
577
578 if (!find_next_packet_for_id(id, m_probe_range))
579 break;
580
581 auto packet = parse_packet(id);
582 if (!packet)
583 continue;
584
585 buffer.add(packet.m_buffer->get_buffer(), packet.m_length);
586 }
587
588 if (avc_seq_param_found && avc_pic_param_found && (avc_access_unit_found || avc_slice_found)) {
589 m_in->restore_pos();
590 new_stream_v_avc(id, buf, length, track);
591 return;
592 }
593
594 } catch (...) {
595 }
596
597 m_in->restore_pos();
598 throw false;
599 }
600
601 void
new_stream_v_mpeg_1_2(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)602 mpeg_ps_reader_c::new_stream_v_mpeg_1_2(mpeg_ps_id_t id,
603 unsigned char *buf,
604 unsigned int length,
605 mpeg_ps_track_ptr &track) {
606 std::shared_ptr<M2VParser> m2v_parser(new M2VParser);
607
608 m2v_parser->SetProbeMode();
609 m2v_parser->WriteData(buf, length);
610
611 int num_leading_b_fields = 0;
612 int state = m2v_parser->GetState();
613
614 bool found_i_frame = false;
615 bool found_non_b_frame = false;
616 bool flushed = false;
617 MPEG2SequenceHeader seq_hdr;
618
619 while ( (MPV_PARSER_STATE_EOS != state)
620 && (MPV_PARSER_STATE_ERROR != state)
621 && (m_probe_range >= m_in->getFilePointer())) {
622 if (find_next_packet_for_id(id, m_probe_range)) {
623 auto packet = parse_packet(id);
624 if (!packet)
625 break;
626
627 m2v_parser->WriteData(packet.m_buffer->get_buffer(), packet.m_length);
628
629 } else if (flushed)
630 break;
631
632 else {
633 m2v_parser->SetEOS();
634 flushed = true;
635 }
636
637 state = m2v_parser->GetState();
638
639 while (true) {
640 std::shared_ptr<MPEGFrame> frame(m2v_parser->ReadFrame());
641 if (!frame)
642 break;
643
644 if (!found_i_frame) {
645 if ('I' != frame->frameType)
646 continue;
647
648 found_i_frame = true;
649 seq_hdr = m2v_parser->GetSequenceHeader();
650
651 continue;
652 }
653
654 if ('B' != frame->frameType) {
655 found_non_b_frame = true;
656 break;
657 }
658
659 num_leading_b_fields += MPEG2_PICTURE_TYPE_FRAME == frame->pictureStructure ? 2 : 1;
660 }
661
662 if (found_i_frame && found_non_b_frame)
663 break;
664 }
665
666 if ((MPV_PARSER_STATE_FRAME != state) || !found_i_frame || !m2v_parser->GetMPEGVersion() || !seq_hdr.width || !seq_hdr.height) {
667 mxdebug_if(m_debug_headers, fmt::format("MPEG PS: blocking id 0x{0:02x}({1:02x}) for supposed type MPEG1/2\n", id.id, id.sub_id));
668 m_blocked_ids[id.idx()] = true;
669 throw false;
670 }
671
672 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG12);
673 track->v_interlaced = !seq_hdr.progressiveSequence;
674 track->v_version = m2v_parser->GetMPEGVersion();
675 track->v_width = seq_hdr.width;
676 track->v_height = seq_hdr.height;
677 track->v_field_duration = mtx::rational(1'000'000'000, seq_hdr.frameRate * 2);
678 track->v_aspect_ratio = seq_hdr.aspectRatio;
679 track->timestamp_b_frame_offset = mtx::to_int(track->v_field_duration * num_leading_b_fields);
680
681 mxdebug_if(m_debug_timestamps,
682 fmt::format("Leading B fields {0} rate {1} progressive? {2} calculated_offset {3} found_i? {4} found_non_b? {5}\n",
683 num_leading_b_fields, seq_hdr.frameRate, !!seq_hdr.progressiveSequence, track->timestamp_b_frame_offset, found_i_frame, found_non_b_frame));
684
685 if ((0 >= track->v_aspect_ratio) || (1 == track->v_aspect_ratio))
686 track->v_dwidth = track->v_width;
687 else
688 track->v_dwidth = mtx::to_int_rounded(track->v_height * track->v_aspect_ratio);
689 track->v_dheight = track->v_height;
690
691 track->use_buffer(128000);
692 }
693
694 void
new_stream_v_avc(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)695 mpeg_ps_reader_c::new_stream_v_avc(mpeg_ps_id_t id,
696 unsigned char *buf,
697 unsigned int length,
698 mpeg_ps_track_ptr &track) {
699 mtx::avc::es_parser_c parser;
700
701 parser.add_bytes(buf, length);
702
703 while (!parser.headers_parsed() && (m_probe_range >= m_in->getFilePointer())) {
704 if (!find_next_packet_for_id(id, m_probe_range))
705 break;
706
707 auto packet = parse_packet(id);
708 if (!packet)
709 break;
710
711 parser.add_bytes(packet.m_buffer->get_buffer(), packet.m_length);
712 }
713
714 if (!parser.headers_parsed())
715 throw false;
716
717 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P10);
718 track->v_width = parser.get_width();
719 track->v_height = parser.get_height();
720
721 if (parser.has_par_been_found()) {
722 auto dimensions = parser.get_display_dimensions();
723 track->v_dwidth = dimensions.first;
724 track->v_dheight = dimensions.second;
725 }
726 }
727
728 void
new_stream_v_vc1(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)729 mpeg_ps_reader_c::new_stream_v_vc1(mpeg_ps_id_t id,
730 unsigned char *buf,
731 unsigned int length,
732 mpeg_ps_track_ptr &track) {
733 mtx::vc1::es_parser_c parser;
734
735 parser.add_bytes(buf, length);
736
737 while (!parser.is_sequence_header_available() && (m_probe_range >= m_in->getFilePointer())) {
738 if (!find_next_packet_for_id(id, m_probe_range))
739 break;
740
741 auto packet = parse_packet(id);
742 if (!packet)
743 break;
744
745 parser.add_bytes(packet.m_buffer->get_buffer(), packet.m_length);
746 }
747
748 if (!parser.is_sequence_header_available())
749 throw false;
750
751 mtx::vc1::sequence_header_t seqhdr;
752 parser.get_sequence_header(seqhdr);
753
754 track->codec = codec_c::look_up(codec_c::type_e::V_VC1);
755 track->v_width = seqhdr.pixel_width;
756 track->v_height = seqhdr.pixel_height;
757 track->provide_timestamps = true;
758
759 track->use_buffer(512000);
760 }
761
762 void
new_stream_a_mpeg(mpeg_ps_id_t,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)763 mpeg_ps_reader_c::new_stream_a_mpeg(mpeg_ps_id_t,
764 unsigned char *buf,
765 unsigned int length,
766 mpeg_ps_track_ptr &track) {
767 mp3_header_t header;
768
769 if (-1 == find_consecutive_mp3_headers(buf, length, 1, &header))
770 throw false;
771
772 track->a_channels = header.channels;
773 track->a_sample_rate = header.sampling_frequency;
774 track->codec = header.get_codec();
775 }
776
777 void
new_stream_a_ac3(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)778 mpeg_ps_reader_c::new_stream_a_ac3(mpeg_ps_id_t id,
779 unsigned char *buf,
780 unsigned int length,
781 mpeg_ps_track_ptr &track) {
782 mxdebug_if(m_debug_headers, fmt::format("new_stream_a_ac3 for ID {0} buf len {1}\n", id, length));
783
784 mtx::bytes::buffer_c buffer;
785
786 buffer.add(buf, length);
787
788 while (m_probe_range >= m_in->getFilePointer()) {
789 mtx::ac3::frame_c header;
790
791 if (-1 != header.find_in(buffer.get_buffer(), buffer.get_size())) {
792 mxdebug_if(m_debug_headers,
793 fmt::format("new_stream_a_ac3 first AC-3 header bsid {0} channels {1} sample_rate {2} bytes {3} samples {4}\n",
794 header.m_bs_id, header.m_channels, header.m_sample_rate, header.m_bytes, header.m_samples));
795
796 track->a_channels = header.m_channels;
797 track->a_sample_rate = header.m_sample_rate;
798 track->a_bsid = header.m_bs_id;
799 track->codec = header.get_codec();
800
801 return;
802 }
803
804 if (!find_next_packet_for_id(id, m_probe_range))
805 throw false;
806
807 auto packet = parse_packet(id);
808 if (!packet || (id.sub_id != packet.m_id.sub_id))
809 continue;
810
811 buffer.add(packet.m_buffer->get_buffer(), packet.m_length);
812 }
813
814 throw false;
815 }
816
817 void
new_stream_a_dts(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)818 mpeg_ps_reader_c::new_stream_a_dts(mpeg_ps_id_t id,
819 unsigned char *buf,
820 unsigned int length,
821 mpeg_ps_track_ptr &track) {
822 mtx::bytes::buffer_c buffer;
823
824 buffer.add(buf, length);
825
826 while ((-1 == mtx::dts::find_header(buffer.get_buffer(), buffer.get_size(), track->dts_header, false)) && (m_probe_range >= m_in->getFilePointer())) {
827 if (!find_next_packet_for_id(id, m_probe_range))
828 throw false;
829
830 auto packet = parse_packet(id);
831 if (!packet || (id.sub_id != packet.m_id.sub_id))
832 continue;
833
834 buffer.add(packet.m_buffer->get_buffer(), packet.m_length);
835 }
836
837 track->a_channels = track->dts_header.get_total_num_audio_channels();
838 track->a_sample_rate = track->dts_header.get_effective_sampling_frequency();
839
840 track->codec.set_specialization(track->dts_header.get_codec_specialization());
841 }
842
843 void
new_stream_a_truehd(mpeg_ps_id_t id,unsigned char * buf,unsigned int length,mpeg_ps_track_ptr & track)844 mpeg_ps_reader_c::new_stream_a_truehd(mpeg_ps_id_t id,
845 unsigned char *buf,
846 unsigned int length,
847 mpeg_ps_track_ptr &track) {
848 mtx::truehd::parser_c parser;
849
850 parser.add_data(buf, length);
851
852 while (1) {
853 while (parser.frame_available()) {
854 mtx::truehd::frame_cptr frame = parser.get_next_frame();
855 if (mtx::truehd::frame_t::sync != frame->m_type)
856 continue;
857
858 mxdebug_if(m_debug_headers,
859 fmt::format("first TrueHD header channels {0} sampling_rate {1} samples_per_frame {2}\n",
860 frame->m_channels, frame->m_sampling_rate, frame->m_samples_per_frame));
861
862 track->codec = frame->codec();
863 track->a_channels = frame->m_channels;
864 track->a_sample_rate = frame->m_sampling_rate;
865
866 return;
867 }
868
869 if (m_probe_range < m_in->getFilePointer())
870 throw false;
871
872 if (!find_next_packet_for_id(id, m_probe_range))
873 throw false;
874
875 auto packet = parse_packet(id);
876 if (!packet || (id.sub_id != packet.m_id.sub_id))
877 continue;
878
879 parser.add_data(packet.m_buffer->get_buffer(), packet.m_length);
880 }
881 }
882
883 void
new_stream_a_pcm(mpeg_ps_id_t,unsigned char * buffer,unsigned int length,mpeg_ps_track_ptr & track)884 mpeg_ps_reader_c::new_stream_a_pcm(mpeg_ps_id_t,
885 unsigned char *buffer,
886 unsigned int length,
887 mpeg_ps_track_ptr &track) {
888 static int const s_lpcm_frequency_table[4] = { 48000, 96000, 44100, 32000 };
889
890 try {
891 auto bc = mtx::bits::reader_c{buffer, length};
892 bc.skip_bits(8); // emphasis (1), muse(1), reserved(1), frame number(5)
893 track->a_bits_per_sample = 16 + bc.get_bits(2) * 4;
894 track->a_sample_rate = s_lpcm_frequency_table[ bc.get_bits(2) ];
895 bc.skip_bit(); // reserved
896 track->a_channels = bc.get_bits(3) + 1;
897 bc.skip_bits(8); // dynamic range control(8)
898
899 } catch (...) {
900 throw false;
901 }
902
903 if (28 == track->a_bits_per_sample)
904 throw false;
905
906 track->skip_packet_data_bytes = 3;
907 }
908
909 /*
910 MPEG PS ids and their meaning:
911
912 0xbd audio substream; type determined by audio id in packet
913 . 0x20..0x3f VobSub subtitles
914 . 0x80..0x87 (E-)AC-3
915 . 0x88..0x8f DTS
916 . 0x98..0x9f DTS
917 . 0xa0..0xaf PCM
918 . 0xb0..0xbf TrueHD
919 . 0xc0..0xc7 (E-)AC-3
920 0xc0..0xdf MP2 audio
921 0xe0..0xef MPEG-1/-2 video
922 0xfd VC-1 video
923
924 */
925
926 void
found_new_stream(mpeg_ps_id_t id)927 mpeg_ps_reader_c::found_new_stream(mpeg_ps_id_t id) {
928 mxdebug_if(m_debug_headers, fmt::format("MPEG PS: new stream id 0x{0:02x}\n", id.id));
929
930 if (((0xc0 > id.id) || (0xef < id.id)) && (0xbd != id.id) && (0xfd != id.id))
931 return;
932
933 try {
934 auto packet = parse_packet(id);
935 if (!packet)
936 throw false;
937
938 id = packet.m_id;
939
940 if (0xbd == id.id) { // DVD audio substream
941 mxdebug_if(m_debug_headers, fmt::format("MPEG PS: audio substream id 0x{0:02x}\n", id.sub_id));
942 if (0 == id.sub_id)
943 return;
944 }
945
946 mxdebug_if(m_debug_timestamps && packet.has_pts(),
947 fmt::format("Timestamp for track {0}: {1} [{2}] (DTS: {3})\n",
948 id, mtx::string::format_timestamp(packet.pts()), packet.pts() * 90 / 1000000ll,
949 packet.has_dts() ? fmt::format("{0} [{1}]", mtx::string::format_timestamp(packet.dts()), packet.dts() * 90 / 1000000ll) : "none"s));
950
951 if (mtx::includes(m_blocked_ids, id.idx()))
952 return;
953
954 int64_t timestamp_for_offset = packet.pts();
955 if (std::numeric_limits<int64_t>::max() == timestamp_for_offset)
956 timestamp_for_offset = -1;
957
958 if (mtx::includes(id2idx, id.idx())) {
959 mpeg_ps_track_ptr &track = tracks[id2idx[id.idx()]];
960 if ((-1 != timestamp_for_offset) && (-1 == track->timestamp_offset))
961 track->timestamp_offset = timestamp_for_offset;
962 return;
963 }
964
965 mpeg_ps_track_ptr track(new mpeg_ps_track_t);
966 track->timestamp_offset = timestamp_for_offset;
967 track->type = '?';
968
969 int es_type = es_map[id.id];
970 if (0 != es_type) {
971 switch (es_type) {
972 case 0x01:
973 case 0x02:
974 track->type = 'v';
975 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG12);
976 break;
977 break;
978 case 0x03:
979 case 0x04:
980 track->type = 'a';
981 track->codec = codec_c::look_up(codec_c::type_e::A_MP3);
982 break;
983 case 0x0f:
984 case 0x11:
985 track->type = 'a';
986 track->codec = codec_c::look_up(codec_c::type_e::A_AAC);
987 break;
988 case 0x10:
989 track->type = 'v';
990 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P2);
991 break;
992 case 0x1b:
993 track->type = 'v';
994 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG4_P10);
995 break;
996 case 0x80:
997 track->type = 'a';
998 track->codec = codec_c::look_up(codec_c::type_e::A_PCM);
999 break;
1000 case 0x81:
1001 track->type = 'a';
1002 track->codec = codec_c::look_up(codec_c::type_e::A_AC3);
1003 break;
1004 }
1005
1006 } else if (0xbd == id.id) {
1007 track->type = 'a';
1008
1009 if ((0x20 <= id.sub_id) && (0x3f >= id.sub_id)) {
1010 track->type = 's';
1011 track->codec = codec_c::look_up(codec_c::type_e::S_VOBSUB);
1012
1013 } else if (((0x80 <= id.sub_id) && (0x87 >= id.sub_id)) || ((0xc0 <= id.sub_id) && (0xc7 >= id.sub_id)))
1014 track->codec = codec_c::look_up(codec_c::type_e::A_AC3);
1015
1016 else if ((0x88 <= id.sub_id) && (0x9f >= id.sub_id))
1017 track->codec = codec_c::look_up(codec_c::type_e::A_DTS);
1018
1019 else if ((0xa0 <= id.sub_id) && (0xa7 >= id.sub_id))
1020 track->codec = codec_c::look_up(codec_c::type_e::A_PCM);
1021
1022 else if ((0xb0 <= id.sub_id) && (0xbf >= id.sub_id))
1023 track->codec = codec_c::look_up(codec_c::type_e::A_TRUEHD);
1024
1025 else if ((0x80 <= id.sub_id) && (0x8f >= id.sub_id))
1026 track->codec = codec_c::look_up(codec_c::type_e::A_PCM);
1027
1028 else
1029 track->type = '?';
1030
1031 } else if ((0xc0 <= id.id) && (0xdf >= id.id)) {
1032 track->type = 'a';
1033 track->codec = codec_c::look_up(codec_c::type_e::A_MP3);
1034
1035 } else if ((0xe0 <= id.id) && (0xef >= id.id)) {
1036 track->type = 'v';
1037 track->codec = codec_c::look_up(codec_c::type_e::V_MPEG12);
1038
1039 } else if (0xfd == id.id) {
1040 track->type = 'v';
1041 track->codec = codec_c::look_up(codec_c::type_e::V_VC1);
1042 }
1043
1044 if ('?' == track->type)
1045 return;
1046
1047 if (track->codec.is(codec_c::type_e::V_MPEG12))
1048 new_stream_v_avc_or_mpeg_1_2(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1049
1050 else if (track->codec.is(codec_c::type_e::A_MP3))
1051 new_stream_a_mpeg(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1052
1053 else if (track->codec.is(codec_c::type_e::A_AC3))
1054 new_stream_a_ac3(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1055
1056 else if (track->codec.is(codec_c::type_e::A_DTS))
1057 new_stream_a_dts(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1058
1059 else if (track->codec.is(codec_c::type_e::V_VC1))
1060 new_stream_v_vc1(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1061
1062 else if (track->codec.is(codec_c::type_e::A_TRUEHD))
1063 new_stream_a_truehd(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1064
1065 else if (track->codec.is(codec_c::type_e::A_PCM))
1066 new_stream_a_pcm(id, packet.m_buffer->get_buffer(), packet.m_length, track);
1067
1068 else
1069 // Unsupported track type
1070 throw false;
1071
1072 track->id = id;
1073 id2idx[id.idx()] = tracks.size();
1074 tracks.push_back(track);
1075
1076 } catch (bool) {
1077 m_blocked_ids[id.idx()] = true;
1078
1079 } catch (...) {
1080 mxerror_fn(m_ti.m_fname, Y("Error parsing a MPEG PS packet during the header reading phase. This stream seems to be badly damaged.\n"));
1081 }
1082 }
1083
1084 bool
find_next_packet(mpeg_ps_id_t & id,int64_t max_file_pos)1085 mpeg_ps_reader_c::find_next_packet(mpeg_ps_id_t &id,
1086 int64_t max_file_pos) {
1087 try {
1088 uint32_t header;
1089
1090 header = m_in->read_uint32_be();
1091 while (1) {
1092 uint8_t byte;
1093
1094 if ((-1 != max_file_pos) && (m_in->getFilePointer() > static_cast<size_t>(max_file_pos)))
1095 return false;
1096
1097 switch (header) {
1098 case mtx::mpeg1_2::PACKET_START_CODE:
1099 if (-1 == version) {
1100 byte = m_in->read_uint8();
1101 if ((byte & 0xc0) != 0)
1102 version = 2; // MPEG-2 PS
1103 else
1104 version = 1;
1105 m_in->skip(-1);
1106 }
1107
1108 m_in->skip(2 * 4); // pack header
1109 if (2 == version) {
1110 m_in->skip(1);
1111 byte = m_in->read_uint8() & 0x07;
1112 m_in->skip(byte); // stuffing bytes
1113 }
1114 header = m_in->read_uint32_be();
1115 break;
1116
1117 case mtx::mpeg1_2::SYSTEM_HEADER_START_CODE:
1118 m_in->skip(2 * 4); // system header
1119 byte = m_in->read_uint8();
1120 while ((byte & 0x80) == 0x80) {
1121 m_in->skip(2); // P-STD info
1122 byte = m_in->read_uint8();
1123 }
1124 m_in->skip(-1);
1125 header = m_in->read_uint32_be();
1126 break;
1127
1128 case mtx::mpeg1_2::MPEG_PROGRAM_END_CODE:
1129 if (!resync_stream(header))
1130 return false;
1131 break;
1132
1133 case mtx::mpeg1_2::PROGRAM_STREAM_MAP_START_CODE:
1134 parse_program_stream_map();
1135 if (!resync_stream(header))
1136 return false;
1137 break;
1138
1139 default:
1140 if (!mtx::mpeg::is_start_code(header)) {
1141 if (!resync_stream(header))
1142 return false;
1143 continue;
1144 }
1145
1146 id.id = header & 0xff;
1147 return true;
1148
1149 break;
1150 }
1151 }
1152 } catch(...) {
1153 return false;
1154 }
1155 }
1156
1157 bool
find_next_packet_for_id(mpeg_ps_id_t id,int64_t max_file_pos)1158 mpeg_ps_reader_c::find_next_packet_for_id(mpeg_ps_id_t id,
1159 int64_t max_file_pos) {
1160 try {
1161 mpeg_ps_id_t new_id;
1162 while (find_next_packet(new_id, max_file_pos)) {
1163 if (id.id == new_id.id)
1164 return true;
1165 m_in->skip(m_in->read_uint16_be());
1166 }
1167 } catch(...) {
1168 }
1169 return false;
1170 }
1171
1172 bool
resync_stream(uint32_t & header)1173 mpeg_ps_reader_c::resync_stream(uint32_t &header) {
1174 mxdebug_if(m_debug_resync, fmt::format("MPEG PS: synchronisation lost at {0}; looking for start code\n", m_in->getFilePointer()));
1175
1176 try {
1177 while (1) {
1178 header <<= 8;
1179 header |= m_in->read_uint8();
1180 if (mtx::mpeg::is_start_code(header))
1181 break;
1182 }
1183
1184 mxdebug_if(m_debug_resync, fmt::format("resync succeeded at {0}, header 0x{1:08x}\n", m_in->getFilePointer() - 4, header));
1185
1186 return true;
1187
1188 } catch (...) {
1189 mxdebug_if(m_debug_resync, "resync failed: exception caught\n");
1190 return false;
1191 }
1192 }
1193
1194 void
create_packetizer(int64_t id)1195 mpeg_ps_reader_c::create_packetizer(int64_t id) {
1196 if ((0 > id) || (tracks.size() <= static_cast<size_t>(id)))
1197 return;
1198 if (0 == tracks[id]->ptzr)
1199 return;
1200 if (!demuxing_requested(tracks[id]->type, id))
1201 return;
1202
1203 m_ti.m_private_data.reset();
1204 m_ti.m_id = id;
1205
1206 auto &track = tracks[id];
1207
1208 if ('a' == track->type) {
1209 if (track->codec.is(codec_c::type_e::A_MP3)) {
1210 track->ptzr = add_packetizer(new mp3_packetizer_c(this, m_ti, track->a_sample_rate, track->a_channels, true));
1211 show_packetizer_info(id, ptzr(track->ptzr));
1212
1213 } else if (track->codec.is(codec_c::type_e::A_AC3)) {
1214 track->ptzr = add_packetizer(new ac3_packetizer_c(this, m_ti, track->a_sample_rate, track->a_channels, track->a_bsid));
1215 show_packetizer_info(id, ptzr(track->ptzr));
1216
1217 } else if (track->codec.is(codec_c::type_e::A_DTS)) {
1218 track->ptzr = add_packetizer(new dts_packetizer_c(this, m_ti, track->dts_header));
1219 show_packetizer_info(id, ptzr(track->ptzr));
1220
1221 } else if (track->codec.is(codec_c::type_e::A_TRUEHD)) {
1222 track->ptzr = add_packetizer(new truehd_packetizer_c(this, m_ti, mtx::truehd::frame_t::truehd, track->a_sample_rate, track->a_channels));
1223 show_packetizer_info(id, ptzr(track->ptzr));
1224
1225 } else if (track->codec.is(codec_c::type_e::A_PCM)) {
1226 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));
1227 show_packetizer_info(id, ptzr(track->ptzr));
1228
1229 } else
1230 mxerror(fmt::format(Y("mpeg_ps_reader: Should not have happened #1. {0}"), BUGMSG));
1231
1232 } else { // if (track->type == 'a')
1233 if (track->codec.is(codec_c::type_e::V_MPEG12)) {
1234 generic_packetizer_c *m2vpacketizer;
1235
1236 m2vpacketizer = new mpeg1_2_video_packetizer_c(this, m_ti, track->v_version, mtx::to_int(track->v_field_duration * 2), track->v_width, track->v_height,
1237 track->v_dwidth, track->v_dheight, false);
1238 track->ptzr = add_packetizer(m2vpacketizer);
1239 show_packetizer_info(id, ptzr(track->ptzr));
1240 m2vpacketizer->set_video_interlaced_flag(track->v_interlaced);
1241
1242 } else if (track->codec.is(codec_c::type_e::V_MPEG4_P10)) {
1243 track->ptzr = add_packetizer(new avc_es_video_packetizer_c(this, m_ti));
1244 ptzr(track->ptzr).set_video_pixel_dimensions(track->v_width, track->v_height);
1245 show_packetizer_info(id, ptzr(track->ptzr));
1246
1247 } else if (track->codec.is(codec_c::type_e::V_VC1)) {
1248 track->ptzr = add_packetizer(new vc1_video_packetizer_c(this, m_ti));
1249 show_packetizer_info(id, ptzr(track->ptzr));
1250
1251 } else
1252 mxerror(fmt::format(Y("mpeg_ps_reader: Should not have happened #2. {0}"), BUGMSG));
1253 }
1254
1255 if (-1 != track->timestamp_offset)
1256 ptzr(track->ptzr).m_ti.m_tcsync.displacement += track->timestamp_offset;
1257
1258 m_ptzr_to_track_map[ &ptzr(track->ptzr) ] = track;
1259 }
1260
1261 void
create_packetizers()1262 mpeg_ps_reader_c::create_packetizers() {
1263 size_t i;
1264
1265 for (i = 0; i < tracks.size(); i++)
1266 create_packetizer(i);
1267 }
1268
1269 void
add_available_track_ids()1270 mpeg_ps_reader_c::add_available_track_ids() {
1271 add_available_track_id_range(tracks.size());
1272 }
1273
1274 file_status_e
read(generic_packetizer_c * requested_ptzr,bool force)1275 mpeg_ps_reader_c::read(generic_packetizer_c *requested_ptzr,
1276 bool force) {
1277 if (file_done)
1278 return flush_packetizers();
1279
1280 auto num_queued_bytes = get_queued_bytes();
1281 if (!force && (20 * 1024 * 1024 < num_queued_bytes)) {
1282 mpeg_ps_track_ptr requested_ptzr_track = m_ptzr_to_track_map[requested_ptzr];
1283 if (!requested_ptzr_track || (('a' != requested_ptzr_track->type) && ('v' != requested_ptzr_track->type)) || (64 * 1024 * 1024 < num_queued_bytes))
1284 return FILE_STATUS_HOLDING;
1285 }
1286
1287 try {
1288 mpeg_ps_id_t new_id;
1289 while (find_next_packet(new_id)) {
1290 auto packet_pos = m_in->getFilePointer() - 4;
1291 auto packet = parse_packet(new_id, false);
1292 new_id = packet.m_id;
1293
1294 if (!packet) {
1295 if ( (0xbe != new_id.id) // padding stream
1296 && (0xbf != new_id.id)) // private 2 stream (navigation data)
1297 mxdebug_if(m_debug_packets, fmt::format("mpeg_ps: parse_packet failed at {0}, skipping {1}\n", packet_pos, packet.m_full_length));
1298 m_in->setFilePointer(packet_pos + 4 + 2 + packet.m_full_length);
1299 continue;
1300 }
1301
1302 if (!mtx::includes(id2idx, new_id.idx()) || (-1 == tracks[id2idx[new_id.idx()]]->ptzr)) {
1303 m_in->setFilePointer(packet_pos + 4 + 2 + packet.m_full_length);
1304 continue;
1305 }
1306
1307 mxdebug_if(m_debug_packets, fmt::format("mpeg_ps: packet at {0}: {1}\n", packet_pos, packet));
1308
1309 auto track = tracks[id2idx[new_id.idx()]];
1310
1311 int64_t timestamp = packet.has_pts() ? packet.pts() : -1;
1312 if ((-1 != timestamp) && track->provide_timestamps)
1313 timestamp = std::max<int64_t>(timestamp - global_timestamp_offset, -1);
1314
1315 else
1316 timestamp = -1;
1317
1318 if (track->skip_packet_data_bytes) {
1319 auto bytes_to_skip = std::min(packet.m_length, track->skip_packet_data_bytes);
1320 packet.m_length -= bytes_to_skip;
1321 m_in->skip(bytes_to_skip);
1322 }
1323
1324 if (0 < track->buffer_size) {
1325 if (((track->buffer_usage + packet.m_length) > track->buffer_size)) {
1326 auto new_packet = std::make_shared<packet_t>(memory_c::borrow(track->buffer, track->buffer_usage));
1327
1328 if (!track->multiple_timestamps_packet_extension->empty()) {
1329 new_packet->extensions.push_back(packet_extension_cptr(track->multiple_timestamps_packet_extension));
1330 track->multiple_timestamps_packet_extension = new multiple_timestamps_packet_extension_c;
1331 }
1332
1333 ptzr(track->ptzr).process(new_packet);
1334 track->buffer_usage = 0;
1335 }
1336
1337 track->assert_buffer_size(packet.m_length);
1338
1339 if (m_in->read(&track->buffer[track->buffer_usage], packet.m_length) != packet.m_length) {
1340 mxdebug_if(m_debug_packets, "mpeg_ps: file_done: m_in->read\n");
1341 return finish();
1342 }
1343
1344 if (-1 != timestamp)
1345 track->multiple_timestamps_packet_extension->add(timestamp, track->buffer_usage);
1346
1347 track->buffer_usage += packet.m_length;
1348
1349 } else {
1350 auto buf = memory_c::alloc(packet.m_length);
1351
1352 if (m_in->read(buf, packet.m_length) != packet.m_length) {
1353 mxdebug_if(m_debug_packets, "mpeg_ps: file_done: m_in->read\n");
1354 return finish();
1355 }
1356
1357 ptzr(track->ptzr).process(std::make_shared<packet_t>(buf, timestamp));
1358 }
1359
1360 return FILE_STATUS_MOREDATA;
1361 }
1362 mxdebug_if(m_debug_packets, "mpeg_ps: file_done: !find_next_packet\n");
1363
1364 } catch(...) {
1365 mxdebug_if(m_debug_packets, "mpeg_ps: file_done: exception\n");
1366 }
1367
1368 return finish();
1369 }
1370
1371 file_status_e
finish()1372 mpeg_ps_reader_c::finish() {
1373 if (file_done)
1374 return flush_packetizers();
1375
1376 for (auto &track : tracks)
1377 if (0 < track->buffer_usage)
1378 ptzr(track->ptzr).process(std::make_shared<packet_t>(memory_c::clone(track->buffer, track->buffer_usage)));
1379
1380 file_done = true;
1381
1382 return flush_packetizers();
1383 }
1384
1385 void
identify()1386 mpeg_ps_reader_c::identify() {
1387 auto info = mtx::id::info_c{};
1388
1389 auto multi_in = dynamic_cast<mm_multi_file_io_c *>(get_underlying_input());
1390 if (multi_in)
1391 multi_in->create_verbose_identification_info(info);
1392
1393 id_result_container(info.get());
1394
1395 size_t i;
1396 for (i = 0; i < tracks.size(); i++) {
1397 mpeg_ps_track_ptr &track = tracks[i];
1398
1399 info = mtx::id::info_c{};
1400
1401 if (track->codec.is(codec_c::type_e::V_MPEG4_P10))
1402 info.add(mtx::id::packetizer, mtx::id::mpeg4_p10_es_video);
1403
1404 info.set(mtx::id::number, (static_cast<uint64_t>(track->id.sub_id) << 32) | static_cast<uint64_t>(track->id.id));
1405 info.add(mtx::id::stream_id, track->id.id);
1406 info.add(mtx::id::sub_stream_id, track->id.sub_id);
1407
1408 if ((0 != track->v_dwidth) && (0 != track->v_dheight))
1409 info.add(mtx::id::display_dimensions, fmt::format("{0}x{1}", track->v_dwidth, track->v_dheight));
1410
1411 if ('a' == track->type) {
1412 info.add(mtx::id::audio_channels, track->a_channels);
1413 info.add(mtx::id::audio_sampling_frequency, track->a_sample_rate);
1414 info.add(mtx::id::audio_bits_per_sample, track->a_bits_per_sample);
1415
1416 } else if ('v' == track->type)
1417 info.add(mtx::id::pixel_dimensions, fmt::format("{0}x{1}", track->v_width, track->v_height));
1418
1419 id_result_track(i, 'a' == track->type ? ID_RESULT_TRACK_AUDIO : ID_RESULT_TRACK_VIDEO, track->codec.get_name(), info.get());
1420 }
1421 }
1422