1 /** VC-1 video helper functions
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 #pragma once
16
17 #include "common/common_pch.h"
18
19 #include <deque>
20
21 #include "common/vc1_fwd.h"
22
23 namespace mtx::vc1 {
24
25 constexpr auto PROFILE_SIMPLE = 0x00000000;
26 constexpr auto PROFILE_MAIN = 0x00000001;
27 constexpr auto PROFILE_COMPLEX = 0x00000002;
28 constexpr auto PROFILE_ADVANCED = 0x00000003;
29
30 constexpr auto MARKER_ENDOFSEQ = 0x0000010a;
31 constexpr auto MARKER_SLICE = 0x0000010b;
32 constexpr auto MARKER_FIELD = 0x0000010c;
33 constexpr auto MARKER_FRAME = 0x0000010d;
34 constexpr auto MARKER_ENTRYPOINT = 0x0000010e;
35 constexpr auto MARKER_SEQHDR = 0x0000010f;
36
37 enum frame_type_e {
38 FRAME_TYPE_I,
39 FRAME_TYPE_P,
40 FRAME_TYPE_B,
41 FRAME_TYPE_BI,
42 FRAME_TYPE_P_SKIPPED,
43 };
44
45 enum frame_coding_mode_e {
46 FCM_PROGRESSIVE = 0,
47 FCM_ILACE_FRAME,
48 FCM_ILACE_FIELD,
49 };
50
51 struct sequence_header_t {
52 int profile;
53 int level;
54 int chroma_format;
55 int frame_rtq_postproc;
56 int bit_rtq_postproc;
57 bool postproc_flag;
58 int pixel_width;
59 int pixel_height;
60 bool pulldown_flag;
61 bool interlace_flag;
62 bool tf_counter_flag;
63 bool f_inter_p_flag;
64 bool psf_mode_flag;
65 bool display_info_flag;
66 int display_width;
67 int display_height;
68 bool aspect_ratio_flag;
69 int aspect_ratio_width;
70 int aspect_ratio_height;
71 bool framerate_flag;
72 int framerate_num;
73 int framerate_den;
74 int color_prim;
75 int transfer_char;
76 int matrix_coef;
77 bool hrd_param_flag;
78 int hrd_num_leaky_buckets;
79
80 sequence_header_t();
81 };
82
83 struct entrypoint_t {
84 bool broken_link_flag;
85 bool closed_entry_flag;
86 bool pan_scan_flag;
87 bool refdist_flag;
88 bool loop_filter_flag;
89 bool fast_uvmc_flag;
90 bool extended_mv_flag;
91 int dquant;
92 bool vs_transform_flag;
93 bool overlap_flag;
94 int quantizer_mode;
95 bool coded_dimensions_flag;
96 int coded_width;
97 int coded_height;
98 bool extended_dmv_flag;
99 bool luma_scaling_flag;
100 int luma_scaling;
101 bool chroma_scaling_flag;
102 int chroma_scaling;
103
104 entrypoint_t();
105 };
106
107 struct frame_header_t {
108 int fcm;
109 frame_type_e frame_type;
110 int tf_counter;
111 int repeat_frame;
112 bool top_field_first_flag;
113 bool repeat_first_field_flag;
114
115 frame_header_t();
116 void init();
117 };
118
119 struct frame_t {
120 frame_header_t header;
121 memory_cptr data;
122 int64_t timestamp;
123 int64_t duration;
124 bool contains_field, contains_entry_point;
125
126 frame_t(frame_header_t const &p_header);
127 void init();
128 bool is_key() const;
129 };
130
is_marker(uint32_t value)131 inline bool is_marker(uint32_t value) {
132 return (value & 0xffffff00) == 0x00000100;
133 }
134
is_fourcc(uint32_t value)135 inline bool is_fourcc(uint32_t value) {
136 return mtx::calc_fourcc('W', 'V', 'C', '1') == value;
137 }
138
is_fourcc(const char * value)139 inline bool is_fourcc(const char *value) {
140 return !strncasecmp(value, "WVC1", 4);
141 }
142
143 bool parse_sequence_header(const unsigned char *buf, int size, sequence_header_t &seqhdr);
144 bool parse_entrypoint(const unsigned char *buf, int size, entrypoint_t &entrypoint, sequence_header_t &seqhdr);
145 bool parse_frame_header(const unsigned char *buf, int size, frame_header_t &frame_header, sequence_header_t &seqhdr);
146
147 class es_parser_c {
148 protected:
149 int64_t m_stream_pos;
150
151 bool m_seqhdr_found;
152 bool m_seqhdr_changed;
153 sequence_header_t m_seqhdr;
154 memory_cptr m_raw_seqhdr;
155 memory_cptr m_raw_entrypoint;
156
157 memory_cptr m_unparsed_buffer;
158
159 std::deque<memory_cptr> m_pre_frame_extra_data;
160 std::deque<memory_cptr> m_post_frame_extra_data;
161
162 std::deque<frame_cptr> m_frames;
163 frame_cptr m_current_frame;
164
165 std::deque<memory_cptr> m_unparsed_packets;
166
167 std::deque<int64_t> m_timestamps;
168 std::deque<int64_t> m_timestamp_positions;
169 int64_t m_previous_timestamp;
170 int64_t m_num_timestamps;
171 int64_t m_num_repeated_fields;
172
173 bool m_default_duration_forced;
174 int64_t m_default_duration;
175
176 public:
177 es_parser_c();
178 virtual ~es_parser_c() = default;
179
180 virtual void add_bytes(unsigned char *buf, int size);
add_bytes(memory_cptr & buf)181 virtual void add_bytes(memory_cptr &buf) {
182 add_bytes(buf->get_buffer(), buf->get_size());
183 };
184
185 virtual void flush();
186
is_sequence_header_available()187 virtual bool is_sequence_header_available() const {
188 return m_seqhdr_found;
189 }
190
has_sequence_header_changed()191 virtual bool has_sequence_header_changed() const {
192 return m_seqhdr_changed;
193 }
194
are_headers_available()195 virtual bool are_headers_available() const {
196 return m_seqhdr_found && m_raw_entrypoint;
197 }
198
get_sequence_header(sequence_header_t & seqhdr)199 virtual void get_sequence_header(sequence_header_t &seqhdr) const {
200 if (m_seqhdr_found)
201 memcpy(&seqhdr, &m_seqhdr, sizeof(sequence_header_t));
202 }
203
get_raw_sequence_header()204 virtual memory_cptr get_raw_sequence_header() const {
205 return m_seqhdr_found ? memory_cptr{m_raw_seqhdr->clone()} : memory_cptr{};
206 }
207
get_raw_entrypoint()208 virtual memory_cptr get_raw_entrypoint() const {
209 return m_raw_entrypoint ? m_raw_entrypoint->clone() : memory_cptr{};
210 }
211
212 virtual void handle_packet(memory_cptr packet);
213
is_frame_available()214 virtual bool is_frame_available() const {
215 return !m_frames.empty();
216 }
217
get_frame()218 virtual frame_cptr get_frame() {
219 frame_cptr frame;
220
221 if (!m_frames.empty()) {
222 frame = m_frames.front();
223 m_frames.pop_front();
224 }
225
226 return frame;
227 }
228
229 virtual void add_timestamp(int64_t timestamp, int64_t position);
230
set_default_duration(int64_t default_duration)231 virtual void set_default_duration(int64_t default_duration) {
232 m_default_duration = default_duration;
233 m_default_duration_forced = true;
234 }
235
get_default_duration()236 virtual int64_t get_default_duration() const {
237 return m_default_duration;
238 }
239
240 protected:
241 virtual void handle_end_of_sequence_packet(memory_cptr packet);
242 virtual void handle_entrypoint_packet(memory_cptr packet);
243 virtual void handle_field_packet(memory_cptr packet);
244 virtual void handle_frame_packet(memory_cptr packet);
245 virtual void handle_sequence_header_packet(memory_cptr packet);
246 virtual void handle_slice_packet(memory_cptr packet);
247 virtual void handle_unknown_packet(uint32_t marker, memory_cptr packet);
248
249 virtual int64_t get_next_timestamp();
250 virtual int64_t peek_next_calculated_timestamp() const;
251
252 virtual void add_pre_frame_extra_data(memory_cptr packet);
253 virtual void add_post_frame_extra_data(memory_cptr packet);
254 virtual void combine_extra_data_with_packet();
255
256 virtual bool postpone_processing(memory_cptr &packet);
257 virtual void process_unparsed_packets();
258
259 virtual void flush_frame();
260
261 virtual bool is_timestamp_available() const;
262
263 protected:
264 static void add_extra_data_if_not_present(std::deque<memory_cptr> &extra_data, memory_cptr const &packet);
265 };
266
267 }
268