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
10 #include "common/common_pch.h"
11
12 #include "common/bit_reader.h"
13 #include "common/mm_io_x.h"
14 #include "common/vp9.h"
15
16 namespace mtx::vp9 {
17
18 namespace {
19 bool
parse_color_config(mtx::bits::reader_c & r,header_data_t & h)20 parse_color_config(mtx::bits::reader_c &r,
21 header_data_t &h) {
22 if (h.profile >= 2)
23 h.bit_depth = r.get_bit() ? 12 : 10;
24 else
25 h.bit_depth = 8;
26
27 auto color_space = r.get_bits(3);
28 h.subsampling_x = false;
29 h.subsampling_y = false;
30
31 if (color_space == CS_RGB) {
32 r.skip_bit(); // color_range
33 if ((h.profile == 1) || (h.profile == 3)) {
34 h.subsampling_x = r.get_bit();
35 h.subsampling_y = r.get_bit();
36 } else {
37 h.subsampling_x = true;
38 h.subsampling_y = true;
39 }
40 }
41
42 return true;
43 }
44
45 bool
parse_uncompressed_header(mtx::bits::reader_c & r,header_data_t & h)46 parse_uncompressed_header(mtx::bits::reader_c &r,
47 header_data_t &h) {
48 if (r.get_bits(2) != 2) // frame_marker
49 return false;
50
51 h.profile = r.get_bit() + (r.get_bit() << 1);
52
53 if (h.profile == 3)
54 r.skip_bit(); // reserved_zero
55
56 if (r.get_bit()) // show_existing_frame
57 return false;
58
59 if (r.get_bit()) // frame_type, 0 == KEY_FRAME, 1 == NON_KEY_FRAME
60 return false;
61
62 r.skip_bits(2); // show_frame, error_resilient_mode
63
64 auto frame_sync_marker = r.get_bits(24);
65 if (frame_sync_marker != 0x498342)
66 return false;
67
68 if (!parse_color_config(r, h))
69 return false;
70
71 return true;
72 }
73 }
74
75 std::optional<header_data_t>
parse_header_data(memory_c const & mem)76 parse_header_data(memory_c const &mem) {
77 header_data_t h;
78
79 try {
80 mtx::bits::reader_c r{mem.get_buffer(), mem.get_size()};
81
82 if (!parse_uncompressed_header(r, h))
83 return std::nullopt;
84
85 } catch (mtx::mm_io::end_of_file_x &) {
86 return std::nullopt;
87 }
88
89 return h;
90 }
91
92 }
93