Scanner C++ API
h264.h
1 /* Copyright 2016 Carnegie Mellon University
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include "scanner/util/common.h"
19 
20 namespace scanner {
21 
22 struct GetBitsState {
23  const u8* buffer;
24  i64 offset;
25  i64 size;
26 };
27 
28 inline u32 get_bit(GetBitsState& gb) {
29  u8 v =
30  ((*(gb.buffer + (gb.offset >> 0x3))) >> (0x7 - (gb.offset & 0x7))) & 0x1;
31  gb.offset++;
32  return v;
33 }
34 
35 inline u32 get_bits(GetBitsState& gb, i32 bits) {
36  u32 v = 0;
37  for (i32 i = bits - 1; i >= 0; i--) {
38  v |= get_bit(gb) << i;
39  }
40  return v;
41 }
42 
43 inline u32 get_ue_golomb(GetBitsState& gb) {
44  // calculate zero bits. Will be optimized.
45  i32 zeros = 0;
46  while (0 == get_bit(gb)) {
47  zeros++;
48  }
49 
50  // insert first 1 bit
51  u32 info = 1 << zeros;
52 
53  for (i32 i = zeros - 1; i >= 0; i--) {
54  info |= get_bit(gb) << i;
55  }
56 
57  return (info - 1);
58 }
59 
60 inline u32 get_se_golomb(GetBitsState& gb) {
61  // calculate zero bits. Will be optimized.
62  i32 zeros = 0;
63  while (0 == get_bit(gb)) {
64  zeros++;
65  }
66 
67  // insert first 1 bit
68  u32 info = 1 << zeros;
69 
70  for (i32 i = zeros - 1; i >= 0; i--) {
71  info |= get_bit(gb) << i;
72  }
73 
74  return (info - 1);
75 }
76 
77 inline void next_nal(const u8*& buffer, i32& buffer_size_left,
78  const u8*& nal_start, i32& nal_size) {
79  bool found = false;
80  while (buffer_size_left > 2) {
81  if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x01) {
82  found = true;
83  break;
84  }
85  buffer++;
86  buffer_size_left--;
87  }
88 
89  buffer += 3;
90  buffer_size_left -= 3;
91 
92  nal_start = buffer;
93  nal_size = 0;
94 
95  if (!found) {
96  return;
97  }
98  while (buffer_size_left > 2 &&
99  !(buffer[0] == 0x00 && buffer[1] == 0x00 &&
100  (buffer[2] == 0x00 || buffer[2] == 0x01))) {
101  buffer++;
102  buffer_size_left--;
103  nal_size++;
104  }
105  if (!(buffer_size_left > 3)) {
106  nal_size += buffer_size_left;
107  // Not sure if this is needed or not...
108  // buffer += buffer_size_left;
109  // buffer_size_left = 0;
110  }
111 }
112 
113 inline i32 get_nal_unit_type(const u8* nal_start) {
114  return (*nal_start) & 0x1F;
115 }
116 
117 inline i32 get_nal_ref_idc(const u8* nal_start) { return (*nal_start >> 5); }
118 
119 inline bool is_vcl_nal(i32 nal_type) { return nal_type >= 1 && nal_type <= 5; }
120 
121 inline bool is_first_vcl_nal(i32 nal_type) {
122  return nal_type >= 1 && nal_type <= 5;
123 }
124 
125 struct SPS {
126  i32 profile_idc;
127  u32 sps_id;
128  u32 log2_max_frame_num;
129  u32 poc_type;
130  u32 log2_max_pic_order_cnt_lsb;
131  bool delta_pic_order_always_zero_flag;
132  bool frame_mbs_only_flag;
133 };
134 
135 inline bool parse_sps(GetBitsState& gb, SPS& info) {
136  // profile_idc
137  info.profile_idc = get_bits(gb, 8);
138  // constraint_set0_flag
139  get_bit(gb);
140  // constraint_set1_flag
141  get_bit(gb);
142  // constraint_set2_flag
143  get_bit(gb);
144  // reserved_zero_5bits /* equal to 0 */
145  get_bits(gb, 5);
146  // level_idc
147  get_bits(gb, 8);
148  // seq_parameter_set_id
149  info.sps_id = get_ue_golomb(gb);
150  if (info.profile_idc == 100 || // High profile
151  info.profile_idc == 110 || // High10 profile
152  info.profile_idc == 122 || // High422 profile
153  info.profile_idc == 244 || // High444 Predictive profile
154  info.profile_idc == 44 || // Cavlc444 profile
155  info.profile_idc == 83 || // Scalable Constrained High profile (SVC)
156  info.profile_idc == 86 || // Scalable High Intra profile (SVC)
157  info.profile_idc == 118 || // Stereo High profile (MVC)
158  info.profile_idc == 128 || // Multiview High profile (MVC)
159  info.profile_idc == 138 || // Multiview Depth High profile (MVCD)
160  info.profile_idc == 139 || info.profile_idc == 134 ||
161  info.profile_idc == 135 || info.profile_idc == 144) {
162  // chroma_format_idc
163  u32 chroma_format_idc = get_ue_golomb(gb);
164  if (chroma_format_idc > 3U) {
165  LOG(WARNING) << "invalid chroma format idc " << chroma_format_idc;
166  return false;
167  } else if (chroma_format_idc == 3) {
168  // residual
169  bool residual_color_transform_flag = get_bit(gb);
170  if (residual_color_transform_flag) {
171  LOG(WARNING) << "separate color planes not supported";
172  return false;
173  }
174  }
175  // bit_depth_luma
176  u32 bit_depth_luma = get_ue_golomb(gb) + 8;
177  u32 bit_depth_chroma = get_ue_golomb(gb) + 8;
178  if (bit_depth_chroma != bit_depth_luma) {
179  LOG(WARNING) << "separate color planes not supported";
180  return false;
181  }
182  if (bit_depth_luma < 8 || bit_depth_luma > 14 || bit_depth_chroma < 8 ||
183  bit_depth_chroma > 14) {
184  LOG(WARNING) << "illegal bit depth value: " << bit_depth_luma << ", "
185  << bit_depth_chroma;
186  return false;
187  }
188  // transform_bypass
189  get_bit(gb);
190  // scaling_matrix
191  if (get_bit(gb)) {
192  LOG(WARNING) << "scaling matrix not supported";
193  return false;
194  }
195  }
196  VLOG(2) << "profile idc " << (i32)info.profile_idc;
197  // log2_max_frame_num_minus4
198  info.log2_max_frame_num = get_ue_golomb(gb) + 4;
199  // pic_order_cnt_type
200  info.poc_type = get_ue_golomb(gb);
201  switch (info.poc_type) {
202  case 0: {
203  // log2_max_pic_order_cnt_lsb_minus4
204  info.log2_max_pic_order_cnt_lsb = get_ue_golomb(gb) + 4;
205  } break;
206  case 1: {
207  // delta_pic_order_always_zero_flag
208  info.delta_pic_order_always_zero_flag = get_bit(gb);
209  // offset_for_non_ref_pic
210  get_se_golomb(gb);
211  // offset_for_top_to_bottom_field
212  get_se_golomb(gb);
213  // num_ref_frames_in_pic_order_cnt_cycle
214  u32 num_ref_frames = get_ue_golomb(gb);
215  for (u32 i = 0; i < num_ref_frames; i++) {
216  // offset_for_ref_frame[ i ];
217  get_se_golomb(gb);
218  }
219  } break;
220  case 2: {
221  // NOTE(apoms): Nothing to do here
222  } break;
223  default: {
224  LOG(WARNING) << "Illegal picture_order_count type: " << info.poc_type;
225  return false;
226  } break;
227  }
228  // num_ref_frames
229  get_ue_golomb(gb);
230  // gaps_in_frame_num_value_allowed_flag
231  get_bit(gb);
232  // pic_width_in_mbs_minus1
233  get_ue_golomb(gb);
234  // pic_height_in_map_units_minus1
235  get_ue_golomb(gb);
236  // frame_mbs_only_flag
237  info.frame_mbs_only_flag = get_bit(gb);
238  // TODO(apoms): parse rest of it
239  return true;
240 }
241 
242 struct PPS {
243  u32 pps_id;
244  u32 sps_id;
245  bool pic_order_present_flag;
246  bool redundant_pic_cnt_present_flag;
247  u32 num_ref_idx_l0_default_active;
248  u32 num_ref_idx_l1_default_active;
249  bool weighted_pred_flag;
250  u8 weighted_bipred_idc;
251 };
252 
253 inline bool parse_pps(GetBitsState& gb, PPS& info) {
254  // pic_parameter_set_id
255  info.pps_id = get_ue_golomb(gb);
256  // seq_parameter_set_id
257  info.sps_id = get_ue_golomb(gb);
258  // entropy_coding_mode_flag
259  bool entropy_coding_mode_flag = get_bit(gb);
260  // pic_order_present_flag
261  info.pic_order_present_flag = get_bit(gb);
262  // num_slice_groups_minus1
263  u32 num_slice_groups_minus1 = get_ue_golomb(gb);
264  if (num_slice_groups_minus1 > 0) {
265  // slice_group_map_type
266  u32 slice_group_map_type = get_ue_golomb(gb);
267  // FMO not supported
268  LOG(WARNING) << "FMO encoded video not supported";
269  return false;
270  }
271  // num_ref_idx_l0_active_minus1
272  info.num_ref_idx_l0_default_active = get_ue_golomb(gb) + 1;
273  // num_ref_idx_l1_active_minus1
274  info.num_ref_idx_l1_default_active = get_ue_golomb(gb) + 1;
275  // weighted_pred_flag
276  info.weighted_pred_flag = get_bit(gb);
277  // weighted_bipred_idc
278  info.weighted_bipred_idc = get_bits(gb, 2);
279  // pic_init_qp_minus26 /* relative to 26 */
280  u32 pic_init_qp_minus26 = get_se_golomb(gb);
281  // pic_init_qs_minus26 /* relative to 26 */
282  u32 pic_init_qs_minus26 = get_se_golomb(gb);
283  // chroma_qp_index_offset
284  u32 chroma_qp_index_offset = get_se_golomb(gb);
285  // deblocking_filter_control_present_flag
286  (void)get_bit(gb);
287  // constrained_intra_pred_flag
288  (void)get_bit(gb);
289  // redundant_pic_cnt_present_flag
290  info.redundant_pic_cnt_present_flag = get_bit(gb);
291  // rbsp_trailing_bits()
292 
293  return true;
294 }
295 
296 struct SliceHeader {
297  u32 nal_unit_type;
298  u32 nal_ref_idc;
299  u32 slice_type;
300  u32 sps_id; // Added for convenience
301  u32 pps_id;
302  u32 frame_num;
303  bool field_pic_flag;
304  bool bottom_field_flag;
305  u32 idr_pic_id;
306  u32 pic_order_cnt_lsb;
307  i32 delta_pic_order_cnt_bottom;
308  u32 delta_pic_order_cnt[2];
309  u32 redundant_pic_cnt;
310  u32 num_ref_idx_l0_active;
311  u32 num_ref_idx_l1_active;
312 };
313 
314 inline bool parse_slice_header(GetBitsState& gb, SPS& sps,
315  std::map<u32, PPS>& pps_map, u32 nal_unit_type,
316  u32 nal_ref_idc, SliceHeader& info) {
317  info.nal_unit_type = nal_unit_type;
318  info.nal_ref_idc = nal_ref_idc;
319  // first_mb_in_slice
320  get_ue_golomb(gb);
321  // slice_type
322  info.slice_type = get_ue_golomb(gb);
323  if (info.slice_type > 9) {
324  LOG(WARNING) << "Slice type too long";
325  return false;
326  }
327  info.sps_id = sps.sps_id;
328  // pic_parameter_set_id
329  info.pps_id = get_ue_golomb(gb);
330  PPS& pps = pps_map.at(info.pps_id);
331  // frame_num
332  info.frame_num = get_bits(gb, sps.log2_max_frame_num);
333  if (!sps.frame_mbs_only_flag) {
334  // field_pic_flag
335  info.field_pic_flag = get_bit(gb);
336  // bottom_field_flag
337  info.bottom_field_flag = info.field_pic_flag ? get_bit(gb) : 0;
338  } else {
339  info.field_pic_flag = 0;
340  info.bottom_field_flag = -1;
341  }
342  if (nal_unit_type == 5) {
343  // idr_pic_id
344  info.idr_pic_id = get_ue_golomb(gb);
345  }
346  info.delta_pic_order_cnt_bottom = 0;
347  if (sps.poc_type == 0) {
348  // pic_order_cnt_lsb
349  info.pic_order_cnt_lsb = get_bits(gb, sps.log2_max_pic_order_cnt_lsb);
350 
351  if (pps.pic_order_present_flag == 1 && !info.field_pic_flag) {
352  info.delta_pic_order_cnt_bottom = get_se_golomb(gb);
353  }
354  }
355  info.delta_pic_order_cnt[0] = 0;
356  info.delta_pic_order_cnt[1] = 0;
357  if (sps.delta_pic_order_always_zero_flag) {
358  info.delta_pic_order_cnt[0] = 0;
359  info.delta_pic_order_cnt[1] = 0;
360  } else if (sps.poc_type == 1) {
361  info.delta_pic_order_cnt[0] = get_se_golomb(gb);
362  if ((pps.pic_order_present_flag == 1) && !info.field_pic_flag) {
363  info.delta_pic_order_cnt[1] = get_se_golomb(gb);
364  } else {
365  info.delta_pic_order_cnt[1] = 0;
366  }
367  }
368  info.redundant_pic_cnt =
369  pps.redundant_pic_cnt_present_flag ? get_ue_golomb(gb) : 0;
370  if (info.slice_type == 1 || info.slice_type == 6) {
371  bool direct_spatial_mv_pred_flag = get_bit(gb);
372  }
373  if (info.slice_type == 0 || info.slice_type == 5 || // P
374  info.slice_type == 1 || info.slice_type == 6 || // B
375  info.slice_type == 3 || info.slice_type == 8 // SP
376  ) {
377  bool num_ref_idx_active_override_flag = get_bit(gb);
378  if (num_ref_idx_active_override_flag) {
379  info.num_ref_idx_l0_active = get_ue_golomb(gb);
380  if (info.slice_type == 1 || info.slice_type == 6) {
381  info.num_ref_idx_l1_active = get_ue_golomb(gb);
382  }
383  } else {
384  info.num_ref_idx_l0_active = pps.num_ref_idx_l0_default_active;
385  info.num_ref_idx_l1_active = pps.num_ref_idx_l1_default_active;
386  ;
387  }
388  }
389  return true;
390 }
391 
392 inline bool is_new_access_unit(std::map<u32, SPS>& sps_map,
393  std::map<u32, PPS>& pps_map, SliceHeader& prev,
394  SliceHeader& curr) {
395  SPS& prev_sps = sps_map.at(prev.sps_id);
396  SPS& curr_sps = sps_map.at(curr.sps_id);
397  PPS& curr_pps = pps_map.at(curr.pps_id);
398  if (curr.nal_unit_type != 5 && curr.frame_num != prev.frame_num) {
399  VLOG(2) << "frame num";
400  return true;
401  } else if (prev.pps_id != curr.pps_id) {
402  VLOG(2) << "pps";
403  return true;
404  } else if (prev.field_pic_flag != curr.field_pic_flag) {
405  VLOG(2) << "field pic";
406  return true;
407  } else if ((prev.bottom_field_flag != -1 && curr.bottom_field_flag != -1) &&
408  prev.bottom_field_flag != curr.bottom_field_flag) {
409  VLOG(2) << "bottom field";
410  return true;
411  } else if ((prev.nal_ref_idc == 0 || curr.nal_ref_idc == 0) &&
412  prev.nal_ref_idc != curr.nal_ref_idc) {
413  VLOG(2) << "nal ref";
414  return true;
415  } else if ((prev_sps.poc_type == 0 && curr_sps.poc_type == 0) &&
416  (prev.pic_order_cnt_lsb != curr.pic_order_cnt_lsb ||
417  prev.delta_pic_order_cnt_bottom !=
418  curr.delta_pic_order_cnt_bottom)) {
419  VLOG(2) << "poc type 0: " << prev.pic_order_cnt_lsb << " vs. "
420  << curr.pic_order_cnt_lsb << ", " << prev.delta_pic_order_cnt_bottom
421  << " vs. " << curr.delta_pic_order_cnt_bottom;
422  return true;
423  } else if ((prev_sps.poc_type == 1 && curr_sps.poc_type == 1) &&
424  (prev.delta_pic_order_cnt[0] != curr.delta_pic_order_cnt[0] ||
425  prev.delta_pic_order_cnt[1] != curr.delta_pic_order_cnt[1])) {
426  VLOG(2) << "poc type 1";
427  return true;
428  } else if ((prev.nal_unit_type == 5 || curr.nal_unit_type == 5) &&
429  prev.nal_unit_type != curr.nal_unit_type) {
430  VLOG(2) << "nal unit type";
431  return true;
432  } else if ((prev.nal_unit_type == 5 && curr.nal_unit_type == 5) &&
433  prev.idr_pic_id != curr.idr_pic_id) {
434  VLOG(2) << "idr";
435  return true;
436  }
437  return false;
438 }
439 }
Definition: h264.h:22
Definition: h264.h:242
Definition: h264.h:125
Definition: database.cpp:36
Definition: h264.h:296