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 &timestamp) {
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 &timestamp) {
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