1 /** MPEG video helper functions (MPEG 1, 2 and 4)
2 
3    mkvmerge -- utility for splicing together matroska files
4    from component media subtypes
5 
6    Distributed under the GPL v2
7    see the file COPYING for details
8    or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
9 
10    \file
11 
12    \author Written by Moritz Bunkus <moritz@bunkus.org>.
13 */
14 
15 #include "common/common_pch.h"
16 
17 #include "common/bit_reader.h"
18 #include "common/debugging.h"
19 #include "common/endian.h"
20 #include "common/memory_slice_cursor.h"
21 #include "common/strings/formatting.h"
22 #include "common/vc1.h"
23 
24 namespace mtx::vc1 {
25 
26 namespace {
27 debugging_option_c s_debug{"vc1"};
28 }
29 
sequence_header_t()30 sequence_header_t::sequence_header_t() {
31   memset(this, 0, sizeof(sequence_header_t));
32 }
33 
entrypoint_t()34 entrypoint_t::entrypoint_t() {
35   memset(this, 0, sizeof(entrypoint_t));
36 }
37 
frame_header_t()38 frame_header_t::frame_header_t() {
39   init();
40 }
41 
42 void
init()43 frame_header_t::init() {
44   memset(this, 0, sizeof(frame_header_t));
45 }
46 
frame_t(frame_header_t const & p_header)47 frame_t::frame_t(frame_header_t const &p_header)
48   : header{p_header}
49 {
50   init();
51 }
52 
53 void
init()54 frame_t::init() {
55   data.reset();
56   timestamp             = -1;
57   duration             = 0;
58   contains_field       = false;
59   contains_entry_point = false;
60 }
61 
62 bool
is_key() const63 frame_t::is_key()
64   const {
65   return contains_entry_point || (header.frame_type == FRAME_TYPE_I);
66 }
67 
68 bool
parse_sequence_header(const unsigned char * buf,int size,sequence_header_t & seqhdr)69 parse_sequence_header(const unsigned char *buf,
70                       int size,
71                       sequence_header_t &seqhdr) {
72   try {
73     static const struct { int n, d; } s_aspect_ratios[13] = {
74       {   1,  1 },
75       {  12, 11 },
76       {  10, 11 },
77       {  16, 11 },
78       {  40, 33 },
79       {  24, 11 },
80       {  20, 11 },
81       {  32, 11 },
82       {  80, 33 },
83       {  18, 11 },
84       {  15, 11 },
85       {  64, 33 },
86       { 160, 99 }
87     };
88 
89     static const int s_framerate_nr[5] = { 24, 25, 30, 50, 60 };
90     static const int s_framerate_dr[2] = { 1000, 1001 };
91 
92     mtx::bits::reader_c bc(buf, size);
93     sequence_header_t hdr;
94 
95     bc.skip_bits(32);           // Marker
96     hdr.profile = bc.get_bits(2);
97 
98     if (PROFILE_ADVANCED != hdr.profile)
99       return false;
100 
101     hdr.level              = bc.get_bits(3);
102     hdr.chroma_format      = bc.get_bits(2);
103     hdr.frame_rtq_postproc = bc.get_bits(3);
104     hdr.bit_rtq_postproc   = bc.get_bits(5);
105     hdr.postproc_flag      = bc.get_bit();
106     hdr.pixel_width        = (bc.get_bits(12) + 1) << 1;
107     hdr.pixel_height       = (bc.get_bits(12) + 1) << 1;
108     hdr.pulldown_flag      = bc.get_bit();
109     hdr.interlace_flag     = bc.get_bit();
110     hdr.tf_counter_flag    = bc.get_bit();
111     hdr.f_inter_p_flag     = bc.get_bit();
112     bc.skip_bits(1);            // reserved
113     hdr.psf_mode_flag      = bc.get_bit();
114     hdr.display_info_flag  = bc.get_bit();
115 
116     if (hdr.display_info_flag) {
117       hdr.display_width     = bc.get_bits(14) + 1;
118       hdr.display_height    = bc.get_bits(14) + 1;
119       hdr.aspect_ratio_flag = bc.get_bit();
120 
121       if (hdr.aspect_ratio_flag) {
122         int aspect_ratio_idx      = bc.get_bits(4);
123 
124         if ((0 < aspect_ratio_idx) && (14 > aspect_ratio_idx)) {
125           hdr.aspect_ratio_width  = s_aspect_ratios[aspect_ratio_idx - 1].n;
126           hdr.aspect_ratio_height = s_aspect_ratios[aspect_ratio_idx - 1].d;
127 
128         } else if (15 == aspect_ratio_idx) {
129           hdr.aspect_ratio_width  = bc.get_bits(8);
130           hdr.aspect_ratio_height = bc.get_bits(8);
131 
132           if ((0 == hdr.aspect_ratio_width) || (0 == hdr.aspect_ratio_height))
133             hdr.aspect_ratio_flag = false;
134 
135         } else
136           hdr.aspect_ratio_flag   = false;
137       }
138 
139       hdr.framerate_flag = bc.get_bit();
140       if (hdr.framerate_flag) {
141         if (bc.get_bit()) {
142           hdr.framerate_num = 32;
143           hdr.framerate_den = bc.get_bits(16) + 1;
144 
145         } else {
146           int nr = bc.get_bits(8);
147           int dr = bc.get_bits(4);
148 
149           if ((0 != nr) && (8 > nr) && (0 != dr) && (3 > dr)) {
150             hdr.framerate_num = s_framerate_dr[dr - 1];
151             hdr.framerate_den = s_framerate_nr[nr - 1] * 1000;
152 
153           } else
154             hdr.framerate_flag = false;
155         }
156       }
157 
158       if (bc.get_bit()) {
159         hdr.color_prim    = bc.get_bits(8);
160         hdr.transfer_char = bc.get_bits(8);
161         hdr.matrix_coef   = bc.get_bits(8);
162       }
163     }
164 
165     hdr.hrd_param_flag = bc.get_bit();
166     if (hdr.hrd_param_flag) {
167       hdr.hrd_num_leaky_buckets = bc.get_bits(5);
168       bc.skip_bits(4 + 4);       // bitrate exponent, buffer size exponent
169       bc.skip_bits(hdr.hrd_num_leaky_buckets * (16 + 16)); // hrd_rate, hrd_buffer
170     }
171 
172     memcpy(&seqhdr, &hdr, sizeof(sequence_header_t));
173 
174     return true;
175   } catch (...) {
176     return false;
177   }
178 }
179 
180 bool
parse_entrypoint(const unsigned char * buf,int size,entrypoint_t & entrypoint,sequence_header_t & seqhdr)181 parse_entrypoint(const unsigned char *buf,
182                  int size,
183                  entrypoint_t &entrypoint,
184                  sequence_header_t &seqhdr) {
185   try {
186     mtx::bits::reader_c bc(buf, size);
187     entrypoint_t ep;
188 
189     bc.skip_bits(32);           // marker
190     ep.broken_link_flag  = bc.get_bit();
191     ep.closed_entry_flag = bc.get_bit();
192     ep.pan_scan_flag     = bc.get_bit();
193     ep.refdist_flag      = bc.get_bit();
194     ep.loop_filter_flag  = bc.get_bit();
195     ep.fast_uvmc_flag    = bc.get_bit();
196     ep.extended_mv_flag  = bc.get_bit();
197     ep.dquant            = bc.get_bits(2);
198     ep.vs_transform_flag = bc.get_bit();
199     ep.overlap_flag      = bc.get_bit();
200     ep.quantizer_mode    = bc.get_bits(2);
201 
202     if (seqhdr.hrd_param_flag)
203       bc.skip_bits(seqhdr.hrd_num_leaky_buckets * 8);
204 
205     ep.coded_dimensions_flag = bc.get_bit();
206     if (ep.coded_dimensions_flag) {
207       ep.coded_width  = (bc.get_bits(12) + 1) << 1;
208       ep.coded_height = (bc.get_bits(12) + 1) << 1;
209     }
210 
211     if (ep.extended_mv_flag)
212       ep.extended_dmv_flag = bc.get_bit();
213 
214     ep.luma_scaling_flag = bc.get_bit();
215     if (ep.luma_scaling_flag)
216       ep.luma_scaling = bc.get_bits(3);
217 
218     ep.chroma_scaling_flag = bc.get_bit();
219     if (ep.chroma_scaling_flag)
220       ep.chroma_scaling = bc.get_bits(3);
221 
222     memcpy(&entrypoint, &ep, sizeof(entrypoint_t));
223 
224     return true;
225   } catch (...) {
226     return false;
227   }
228 }
229 
230 bool
parse_frame_header(const unsigned char * buf,int size,frame_header_t & frame_header,sequence_header_t & seqhdr)231 parse_frame_header(const unsigned char *buf,
232                    int size,
233                    frame_header_t &frame_header,
234                    sequence_header_t &seqhdr) {
235   try {
236     mtx::bits::reader_c bc(buf, size);
237     frame_header_t fh;
238 
239     bc.skip_bits(32);           // marker
240 
241     auto field_mode = false;
242 
243     if (seqhdr.interlace_flag) {
244       fh.fcm     = bc.get_012();
245       field_mode = fh.fcm == FCM_ILACE_FIELD;
246     }
247 
248     if (field_mode) {
249       // Only set frame type to I for actual I/I fields. This is only
250       // used for key frame determination, so gloss over the actual
251       // field type differences.
252       auto type     = bc.get_bits(3);
253       fh.frame_type = 0 == type ? FRAME_TYPE_I : FRAME_TYPE_P;
254 
255     } else {
256       auto type = bc.get_unary(false, 4);
257       if (type >= 4) {
258         fh.frame_type = FRAME_TYPE_P_SKIPPED;
259         memcpy(&frame_header, &fh, sizeof(frame_header_t));
260 
261         return true;
262       }
263 
264       static frame_type_e s_type_map[4] = { FRAME_TYPE_P, FRAME_TYPE_B, FRAME_TYPE_I, FRAME_TYPE_BI };
265       fh.frame_type = s_type_map[type];
266     }
267 
268     if (seqhdr.tf_counter_flag)
269       fh.tf_counter = bc.get_bits(8);
270 
271     if (seqhdr.pulldown_flag) {
272       if (!seqhdr.interlace_flag || seqhdr.psf_mode_flag)
273         fh.repeat_frame            = bc.get_bits(2);
274       else {
275         fh.top_field_first_flag    = bc.get_bit();
276         fh.repeat_first_field_flag = bc.get_bit();
277       }
278     }
279 
280     memcpy(&frame_header, &fh, sizeof(frame_header_t));
281 
282     return true;
283   } catch (...) {
284     return false;
285   }
286 }
287 
288 //
289 //  -------------------------------------------------
290 //
291 
es_parser_c()292 es_parser_c::es_parser_c()
293   : m_stream_pos(0)
294   , m_seqhdr_found(false)
295   , m_seqhdr_changed{false}
296   , m_previous_timestamp(0)
297   , m_num_timestamps(0)
298   , m_num_repeated_fields(0)
299   , m_default_duration_forced(false)
300   , m_default_duration(1000000000ll / 25)
301 {
302 }
303 
304 void
add_bytes(unsigned char * buffer,int size)305 es_parser_c::add_bytes(unsigned char *buffer,
306                        int size) {
307   mtx::mem::slice_cursor_c cursor;
308 
309   int previous_pos            = -1;
310   int64_t previous_stream_pos = m_stream_pos;
311 
312   if (m_unparsed_buffer && (0 != m_unparsed_buffer->get_size()))
313     cursor.add_slice(m_unparsed_buffer);
314   cursor.add_slice(buffer, size);
315 
316   if (3 <= cursor.get_remaining_size()) {
317     uint32_t marker = (1 << 24) | ((unsigned int)cursor.get_char() << 16) | ((unsigned int)cursor.get_char() << 8) | (unsigned int)cursor.get_char();
318 
319     while (true) {
320       if (is_marker(marker)) {
321         if (-1 != previous_pos) {
322           int new_size = cursor.get_position() - 4 - previous_pos;
323 
324           memory_cptr packet(memory_c::alloc(new_size));
325           cursor.copy(packet->get_buffer(), previous_pos, new_size);
326 
327           handle_packet(packet);
328         }
329 
330         previous_pos = cursor.get_position() - 4;
331         m_stream_pos = previous_stream_pos + previous_pos;
332       }
333 
334       if (!cursor.char_available())
335         break;
336 
337       marker <<= 8;
338       marker  |= (unsigned int)cursor.get_char();
339     }
340   }
341 
342   if (-1 == previous_pos)
343     previous_pos = 0;
344 
345   int new_size = cursor.get_size() - previous_pos;
346   if (0 != new_size) {
347     memory_cptr new_unparsed_buffer = memory_c::alloc(new_size);
348     cursor.copy(new_unparsed_buffer->get_buffer(), previous_pos, new_size);
349     m_unparsed_buffer = new_unparsed_buffer;
350 
351   } else
352     m_unparsed_buffer.reset();
353 }
354 
355 void
flush()356 es_parser_c::flush() {
357   if (m_unparsed_buffer && (4 <= m_unparsed_buffer->get_size())) {
358     uint32_t marker = get_uint32_be(m_unparsed_buffer->get_buffer());
359     if (is_marker(marker))
360       handle_packet(memory_c::clone(m_unparsed_buffer->get_buffer(), m_unparsed_buffer->get_size()));
361   }
362 
363   m_unparsed_buffer.reset();
364 
365   flush_frame();
366 }
367 
368 void
handle_packet(memory_cptr packet)369 es_parser_c::handle_packet(memory_cptr packet) {
370   uint32_t marker = get_uint32_be(packet->get_buffer());
371 
372   switch (marker) {
373     case MARKER_SEQHDR:
374       handle_sequence_header_packet(packet);
375       break;
376 
377     case MARKER_ENTRYPOINT:
378       handle_entrypoint_packet(packet);
379       break;
380 
381     case MARKER_FRAME:
382       handle_frame_packet(packet);
383       break;
384 
385     case MARKER_SLICE:
386       handle_slice_packet(packet);
387       break;
388 
389     case MARKER_FIELD:
390       handle_field_packet(packet);
391       break;
392 
393     case MARKER_ENDOFSEQ:
394       handle_end_of_sequence_packet(packet);
395       break;
396 
397     default:
398       handle_unknown_packet(marker, packet);
399       break;
400   }
401 }
402 
403 void
handle_end_of_sequence_packet(memory_cptr)404 es_parser_c::handle_end_of_sequence_packet(memory_cptr) {
405 }
406 
407 void
handle_entrypoint_packet(memory_cptr packet)408 es_parser_c::handle_entrypoint_packet(memory_cptr packet) {
409   if (!postpone_processing(packet))
410     add_pre_frame_extra_data(packet);
411 
412   if (!m_raw_entrypoint)
413     m_raw_entrypoint = memory_cptr(packet->clone());
414 }
415 
416 void
handle_field_packet(memory_cptr packet)417 es_parser_c::handle_field_packet(memory_cptr packet) {
418   if (postpone_processing(packet))
419     return;
420 
421   add_post_frame_extra_data(packet);
422 }
423 
424 void
handle_frame_packet(memory_cptr packet)425 es_parser_c::handle_frame_packet(memory_cptr packet) {
426   if (postpone_processing(packet))
427     return;
428 
429   flush_frame();
430 
431   frame_header_t frame_header;
432   if (!parse_frame_header(packet->get_buffer(), packet->get_size(), frame_header, m_seqhdr))
433     return;
434 
435   m_current_frame        = std::make_shared<frame_t>(frame_header);
436   m_current_frame->data  = packet;
437   m_current_frame->data->take_ownership();
438 
439   if (!m_timestamps.empty())
440     mxdebug_if(s_debug, fmt::format("es_parser_c::handle_frame_packet: next provided timestamp {0} next calculated timestamp {1}\n", mtx::string::format_timestamp(m_timestamps.front()), mtx::string::format_timestamp(peek_next_calculated_timestamp())));
441 
442 }
443 
444 void
handle_sequence_header_packet(memory_cptr packet)445 es_parser_c::handle_sequence_header_packet(memory_cptr packet) {
446   flush_frame();
447 
448   add_pre_frame_extra_data(packet);
449 
450   sequence_header_t seqhdr;
451   if (!parse_sequence_header(packet->get_buffer(), packet->get_size(), seqhdr))
452     return;
453 
454   m_seqhdr_changed = !m_seqhdr_found || (packet->get_size() != m_raw_seqhdr->get_size()) || memcmp(packet->get_buffer(), m_raw_seqhdr->get_buffer(), packet->get_size());
455 
456   memcpy(&m_seqhdr, &seqhdr, sizeof(sequence_header_t));
457   m_raw_seqhdr   = memory_cptr(packet->clone());
458   m_seqhdr_found = true;
459 
460   if (!m_default_duration_forced && m_seqhdr.framerate_flag && (0 != m_seqhdr.framerate_num) && (0 != m_seqhdr.framerate_den))
461     m_default_duration = 1000000000ll * m_seqhdr.framerate_num / m_seqhdr.framerate_den;
462 
463   process_unparsed_packets();
464 }
465 
466 void
handle_slice_packet(memory_cptr packet)467 es_parser_c::handle_slice_packet(memory_cptr packet) {
468   if (postpone_processing(packet))
469     return;
470 
471   add_post_frame_extra_data(packet);
472 }
473 
474 void
handle_unknown_packet(uint32_t,memory_cptr packet)475 es_parser_c::handle_unknown_packet(uint32_t,
476                                    memory_cptr packet) {
477   if (postpone_processing(packet))
478     return;
479 
480   add_post_frame_extra_data(packet);
481 }
482 
483 void
flush_frame()484 es_parser_c::flush_frame() {
485   if (!m_current_frame)
486     return;
487 
488   if (!m_pre_frame_extra_data.empty() || !m_post_frame_extra_data.empty())
489     combine_extra_data_with_packet();
490 
491   m_current_frame->timestamp = get_next_timestamp();
492   m_current_frame->duration = get_default_duration();
493 
494   m_frames.push_back(m_current_frame);
495 
496   m_current_frame.reset();
497 }
498 
499 bool
postpone_processing(memory_cptr & packet)500 es_parser_c::postpone_processing(memory_cptr &packet) {
501   if (m_seqhdr_found)
502     return false;
503 
504   packet->take_ownership();
505   m_unparsed_packets.push_back(packet);
506   return true;
507 }
508 
509 void
process_unparsed_packets()510 es_parser_c::process_unparsed_packets() {
511   for (auto &packet : m_unparsed_packets)
512     handle_frame_packet(packet);
513 
514   m_unparsed_packets.clear();
515 }
516 
517 void
combine_extra_data_with_packet()518 es_parser_c::combine_extra_data_with_packet() {
519   auto sum_fn     = [](size_t size, const memory_cptr &buffer) { return size + buffer->get_size(); };
520   auto extra_size = std::accumulate(m_pre_frame_extra_data.begin(), m_pre_frame_extra_data.end(), 0, sum_fn) + std::accumulate(m_post_frame_extra_data.begin(), m_post_frame_extra_data.end(), 0, sum_fn);
521 
522   auto new_packet = memory_c::alloc(extra_size + m_current_frame->data->get_size());
523   auto ptr        = new_packet->get_buffer();
524 
525   for (const auto &mem : m_pre_frame_extra_data) {
526     memcpy(ptr, mem->get_buffer(), mem->get_size());
527     ptr += mem->get_size();
528 
529     if (get_uint32_be(mem->get_buffer()) == MARKER_ENTRYPOINT)
530       m_current_frame->contains_entry_point = true;
531   }
532 
533   memcpy(ptr, m_current_frame->data->get_buffer(), m_current_frame->data->get_size());
534   ptr += m_current_frame->data->get_size();
535 
536   for (const auto &mem : m_post_frame_extra_data) {
537     memcpy(ptr, mem->get_buffer(), mem->get_size());
538     ptr += mem->get_size();
539 
540     if (MARKER_FIELD == get_uint32_be(mem->get_buffer()))
541       m_current_frame->contains_field = true;
542   }
543 
544   m_pre_frame_extra_data.clear();
545   m_post_frame_extra_data.clear();
546 
547   m_current_frame->data = new_packet;
548 }
549 
550 int64_t
get_next_timestamp()551 es_parser_c::get_next_timestamp() {
552   int64_t next_timestamp = m_previous_timestamp
553                         + (m_num_timestamps + m_num_repeated_fields) * m_default_duration
554                         - m_num_repeated_fields                     * m_default_duration / 2;
555 
556   if (is_timestamp_available()) {
557     mxdebug_if(s_debug, fmt::format("\nes_parser_c::get_next_timestamp(): provided timestamp available; original next {0}, provided {1}\n", mtx::string::format_timestamp(next_timestamp), mtx::string::format_timestamp(m_timestamps.front())));
558 
559     next_timestamp         = m_timestamps.front();
560     m_previous_timestamp   = m_timestamps.front();
561     m_num_timestamps       = 0;
562     m_num_repeated_fields = 0;
563 
564     m_timestamps.pop_front();
565     m_timestamp_positions.pop_front();
566   }
567 
568   m_num_timestamps += 1 + m_current_frame->header.repeat_frame;
569   if (m_seqhdr.interlace_flag && m_current_frame->header.repeat_first_field_flag && !m_current_frame->contains_field)
570     ++m_num_repeated_fields;
571 
572   return next_timestamp;
573 }
574 
575 int64_t
peek_next_calculated_timestamp() const576 es_parser_c::peek_next_calculated_timestamp()
577   const {
578   return m_previous_timestamp
579     + (m_num_timestamps + m_num_repeated_fields) * m_default_duration
580     - m_num_repeated_fields                     * m_default_duration / 2;
581 }
582 
583 void
add_pre_frame_extra_data(memory_cptr packet)584 es_parser_c::add_pre_frame_extra_data(memory_cptr packet) {
585   add_extra_data_if_not_present(m_pre_frame_extra_data, packet);
586 }
587 
588 void
add_post_frame_extra_data(memory_cptr packet)589 es_parser_c::add_post_frame_extra_data(memory_cptr packet) {
590   add_extra_data_if_not_present(m_post_frame_extra_data, packet);
591 }
592 
593 void
add_extra_data_if_not_present(std::deque<memory_cptr> & extra_data,memory_cptr const & packet)594 es_parser_c::add_extra_data_if_not_present(std::deque<memory_cptr> &extra_data,
595                                            memory_cptr const &packet) {
596   for (auto const &existing_packet : extra_data)
597     if (*existing_packet == *packet)
598       return;
599 
600   extra_data.push_back(packet->clone());
601 }
602 
603 void
add_timestamp(int64_t timestamp,int64_t position)604 es_parser_c::add_timestamp(int64_t timestamp,
605                           int64_t position) {
606   position += m_stream_pos;
607   if (m_unparsed_buffer)
608     position += m_unparsed_buffer->get_size();
609 
610   m_timestamps.push_back(timestamp);
611   m_timestamp_positions.push_back(position);
612 }
613 
614 bool
is_timestamp_available() const615 es_parser_c::is_timestamp_available()
616   const {
617   return !m_timestamps.empty() && (m_timestamp_positions.front() <= m_stream_pos);
618 }
619 
620 }
621