OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/common/gpu/media/h264_parser.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/stl_util.h" | |
10 | |
11 namespace content { | |
12 | |
13 bool H264SliceHeader::IsPSlice() const { | |
14 return (slice_type % 5 == kPSlice); | |
15 } | |
16 | |
17 bool H264SliceHeader::IsBSlice() const { | |
18 return (slice_type % 5 == kBSlice); | |
19 } | |
20 | |
21 bool H264SliceHeader::IsISlice() const { | |
22 return (slice_type % 5 == kISlice); | |
23 } | |
24 | |
25 bool H264SliceHeader::IsSPSlice() const { | |
26 return (slice_type % 5 == kSPSlice); | |
27 } | |
28 | |
29 bool H264SliceHeader::IsSISlice() const { | |
30 return (slice_type % 5 == kSISlice); | |
31 } | |
32 | |
33 H264NALU::H264NALU() { | |
34 memset(this, 0, sizeof(*this)); | |
35 } | |
36 | |
37 H264SPS::H264SPS() { | |
38 memset(this, 0, sizeof(*this)); | |
39 } | |
40 | |
41 H264PPS::H264PPS() { | |
42 memset(this, 0, sizeof(*this)); | |
43 } | |
44 | |
45 H264SliceHeader::H264SliceHeader() { | |
46 memset(this, 0, sizeof(*this)); | |
47 } | |
48 | |
49 H264SEIMessage::H264SEIMessage() { | |
50 memset(this, 0, sizeof(*this)); | |
51 } | |
52 | |
53 #define READ_BITS_OR_RETURN(num_bits, out) \ | |
54 do { \ | |
55 int _out; \ | |
56 if (!br_.ReadBits(num_bits, &_out)) { \ | |
57 DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ | |
58 return kInvalidStream; \ | |
59 } \ | |
60 *out = _out; \ | |
61 } while (0) | |
62 | |
63 #define READ_BOOL_OR_RETURN(out) \ | |
64 do { \ | |
65 int _out; \ | |
66 if (!br_.ReadBits(1, &_out)) { \ | |
67 DVLOG(1) << "Error in stream: unexpected EOS while trying to read " #out; \ | |
68 return kInvalidStream; \ | |
69 } \ | |
70 *out = _out != 0; \ | |
71 } while (0) | |
72 | |
73 #define READ_UE_OR_RETURN(out) \ | |
74 do { \ | |
75 if (ReadUE(out) != kOk) { \ | |
76 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ | |
77 return kInvalidStream; \ | |
78 } \ | |
79 } while (0) | |
80 | |
81 #define READ_SE_OR_RETURN(out) \ | |
82 do { \ | |
83 if (ReadSE(out) != kOk) { \ | |
84 DVLOG(1) << "Error in stream: invalid value while trying to read " #out; \ | |
85 return kInvalidStream; \ | |
86 } \ | |
87 } while (0) | |
88 | |
89 #define IN_RANGE_OR_RETURN(val, min, max) \ | |
90 do { \ | |
91 if ((val) < (min) || (val) > (max)) { \ | |
92 DVLOG(1) << "Error in stream: invalid value, expected " #val " to be" \ | |
93 << " in range [" << (min) << ":" << (max) << "]" \ | |
94 << " found " << (val) << " instead"; \ | |
95 return kInvalidStream; \ | |
96 } \ | |
97 } while (0) | |
98 | |
99 #define TRUE_OR_RETURN(a) \ | |
100 do { \ | |
101 if (!(a)) { \ | |
102 DVLOG(1) << "Error in stream: invalid value, expected " << #a; \ | |
103 return kInvalidStream; \ | |
104 } \ | |
105 } while (0) | |
106 | |
107 H264Parser::H264Parser() { | |
108 Reset(); | |
109 } | |
110 | |
111 H264Parser::~H264Parser() { | |
112 STLDeleteValues(&active_SPSes_); | |
113 STLDeleteValues(&active_PPSes_); | |
114 } | |
115 | |
116 void H264Parser::Reset() { | |
117 stream_ = NULL; | |
118 bytes_left_ = 0; | |
119 } | |
120 | |
121 void H264Parser::SetStream(const uint8* stream, off_t stream_size) { | |
122 DCHECK(stream); | |
123 DCHECK_GT(stream_size, 0); | |
124 | |
125 stream_ = stream; | |
126 bytes_left_ = stream_size; | |
127 } | |
128 | |
129 const H264PPS* H264Parser::GetPPS(int pps_id) { | |
130 return active_PPSes_[pps_id]; | |
131 } | |
132 | |
133 const H264SPS* H264Parser::GetSPS(int sps_id) { | |
134 return active_SPSes_[sps_id]; | |
135 } | |
136 | |
137 static inline bool IsStartCode(const uint8* data) { | |
138 return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01; | |
139 } | |
140 | |
141 // Find offset from start of data to next NALU start code | |
142 // and size of found start code (3 or 4 bytes). | |
143 static bool FindStartCode(const uint8* data, off_t data_size, | |
144 off_t* offset, | |
145 off_t* start_code_size) { | |
146 off_t bytes_left = data_size; | |
147 | |
148 while (bytes_left > 3) { | |
149 if (IsStartCode(data)) { | |
150 // Found three-byte start code, set pointer at its beginning. | |
151 *offset = data_size - bytes_left; | |
152 *start_code_size = 3; | |
153 | |
154 // If there is a zero byte before this start code, | |
155 // then it's actually a four-byte start code, so backtrack one byte. | |
156 if (*offset > 0 && *(data - 1) == 0x00) { | |
157 --(*offset); | |
158 ++(*start_code_size); | |
159 } | |
160 | |
161 return true; | |
162 } | |
163 | |
164 ++data; | |
165 --bytes_left; | |
166 } | |
167 | |
168 // End of data. | |
169 return false; | |
170 } | |
171 | |
172 // Find the next NALU in stream, returning its start offset without the start | |
173 // code (i.e. at the beginning of NALU data). | |
174 // Size will include trailing zero bits, and will be from start offset to | |
175 // before the start code of the next NALU (or end of stream). | |
176 static bool LocateNALU(const uint8* stream, off_t stream_size, | |
177 off_t* nalu_start_off, off_t* nalu_size) { | |
178 off_t start_code_size; | |
179 | |
180 // Find start code of the next NALU. | |
181 if (!FindStartCode(stream, stream_size, nalu_start_off, &start_code_size)) { | |
182 DVLOG(4) << "Could not find start code, end of stream?"; | |
183 return false; | |
184 } | |
185 | |
186 // Discard its start code. | |
187 *nalu_start_off += start_code_size; | |
188 // Move the stream to the beginning of it (skip the start code). | |
189 stream_size -= *nalu_start_off; | |
190 stream += *nalu_start_off; | |
191 | |
192 // Find the start code of next NALU; if successful, NALU size is the number | |
193 // of bytes from after previous start code to before this one; | |
194 // if next start code is not found, it is still a valid NALU if there | |
195 // are still some bytes left after the first start code. | |
196 // nalu_size is the offset to the next start code | |
197 if (!FindStartCode(stream, stream_size, nalu_size, &start_code_size)) { | |
198 // end of stream (no next NALU), but still valid NALU if any bytes left | |
199 *nalu_size = stream_size; | |
200 if (*nalu_size < 1) { | |
201 DVLOG(3) << "End of stream"; | |
202 return false; | |
203 } | |
204 } | |
205 | |
206 return true; | |
207 } | |
208 | |
209 H264Parser::Result H264Parser::ReadUE(int* val) { | |
210 int num_bits = -1; | |
211 int bit; | |
212 int rest; | |
213 | |
214 // Count the number of contiguous zero bits. | |
215 do { | |
216 READ_BITS_OR_RETURN(1, &bit); | |
217 num_bits++; | |
218 } while (bit == 0); | |
219 | |
220 if (num_bits > 31) | |
221 return kInvalidStream; | |
222 | |
223 // Calculate exp-Golomb code value of size num_bits. | |
224 *val = (1 << num_bits) - 1; | |
225 | |
226 if (num_bits > 0) { | |
227 READ_BITS_OR_RETURN(num_bits, &rest); | |
228 *val += rest; | |
229 } | |
230 | |
231 return kOk; | |
232 } | |
233 | |
234 H264Parser::Result H264Parser::ReadSE(int* val) { | |
235 int ue; | |
236 Result res; | |
237 | |
238 // See Chapter 9 in the spec. | |
239 res = ReadUE(&ue); | |
240 if (res != kOk) | |
241 return res; | |
242 | |
243 if (ue % 2 == 0) | |
244 *val = -(ue / 2); | |
245 else | |
246 *val = ue / 2 + 1; | |
247 | |
248 return kOk; | |
249 } | |
250 | |
251 H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU *nalu) { | |
252 int data; | |
253 off_t off_to_nalu_start; | |
254 | |
255 if (!LocateNALU(stream_, bytes_left_, &off_to_nalu_start, &nalu->size)) { | |
256 DVLOG(4) << "Could not find next NALU, bytes left in stream: " | |
257 << bytes_left_; | |
258 return kEOStream; | |
259 } | |
260 | |
261 nalu->data = stream_ + off_to_nalu_start; | |
262 | |
263 // Initialize bit reader at the start of found NALU. | |
264 if (!br_.Initialize(nalu->data, nalu->size)) | |
265 return kEOStream; | |
266 | |
267 DVLOG(4) << "Looking for NALU, Stream bytes left: " << bytes_left_ | |
268 << " off to next nalu: " << off_to_nalu_start; | |
269 | |
270 // Move parser state to after this NALU, so next time AdvanceToNextNALU | |
271 // is called, we will effectively be skipping it; | |
272 // other parsing functions will use the position saved | |
273 // in bit reader for parsing, so we don't have to remember it here. | |
274 stream_ += off_to_nalu_start + nalu->size; | |
275 bytes_left_ -= off_to_nalu_start + nalu->size; | |
276 | |
277 // Read NALU header, skip the forbidden_zero_bit, but check for it. | |
278 READ_BITS_OR_RETURN(1, &data); | |
279 TRUE_OR_RETURN(data == 0); | |
280 | |
281 READ_BITS_OR_RETURN(2, &nalu->nal_ref_idc); | |
282 READ_BITS_OR_RETURN(5, &nalu->nal_unit_type); | |
283 | |
284 DVLOG(4) << "NALU type: " << static_cast<int>(nalu->nal_unit_type) | |
285 << " at: " << reinterpret_cast<const void*>(nalu->data) | |
286 << " size: " << nalu->size | |
287 << " ref: " << static_cast<int>(nalu->nal_ref_idc); | |
288 | |
289 return kOk; | |
290 } | |
291 | |
292 // Default scaling lists (per spec). | |
293 static const int kDefault4x4Intra[kH264ScalingList4x4Length] = { | |
294 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42, }; | |
295 | |
296 static const int kDefault4x4Inter[kH264ScalingList4x4Length] = { | |
297 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34, }; | |
298 | |
299 static const int kDefault8x8Intra[kH264ScalingList8x8Length] = { | |
300 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, | |
301 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, | |
302 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, | |
303 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42, }; | |
304 | |
305 static const int kDefault8x8Inter[kH264ScalingList8x8Length] = { | |
306 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, | |
307 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, | |
308 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, | |
309 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35, }; | |
310 | |
311 static inline void DefaultScalingList4x4( | |
312 int i, | |
313 int scaling_list4x4[][kH264ScalingList4x4Length]) { | |
314 DCHECK_LT(i, 6); | |
315 | |
316 if (i < 3) | |
317 memcpy(scaling_list4x4[i], kDefault4x4Intra, sizeof(kDefault4x4Intra)); | |
318 else if (i < 6) | |
319 memcpy(scaling_list4x4[i], kDefault4x4Inter, sizeof(kDefault4x4Inter)); | |
320 } | |
321 | |
322 static inline void DefaultScalingList8x8( | |
323 int i, | |
324 int scaling_list8x8[][kH264ScalingList8x8Length]) { | |
325 DCHECK_LT(i, 6); | |
326 | |
327 if (i % 2 == 0) | |
328 memcpy(scaling_list8x8[i], kDefault8x8Intra, sizeof(kDefault8x8Intra)); | |
329 else | |
330 memcpy(scaling_list8x8[i], kDefault8x8Inter, sizeof(kDefault8x8Inter)); | |
331 } | |
332 | |
333 static void FallbackScalingList4x4( | |
334 int i, | |
335 const int default_scaling_list_intra[], | |
336 const int default_scaling_list_inter[], | |
337 int scaling_list4x4[][kH264ScalingList4x4Length]) { | |
338 static const int kScalingList4x4ByteSize = sizeof(scaling_list4x4[0][0]) * | |
339 kH264ScalingList4x4Length; | |
340 | |
341 switch (i) { | |
342 case 0: | |
343 memcpy(scaling_list4x4[i], default_scaling_list_intra, | |
344 kScalingList4x4ByteSize); | |
345 break; | |
346 | |
347 case 1: | |
348 memcpy(scaling_list4x4[i], scaling_list4x4[0], | |
349 kScalingList4x4ByteSize); | |
350 break; | |
351 | |
352 case 2: | |
353 memcpy(scaling_list4x4[i], scaling_list4x4[1], | |
354 kScalingList4x4ByteSize); | |
355 break; | |
356 | |
357 case 3: | |
358 memcpy(scaling_list4x4[i], default_scaling_list_inter, | |
359 kScalingList4x4ByteSize); | |
360 break; | |
361 | |
362 case 4: | |
363 memcpy(scaling_list4x4[i], scaling_list4x4[3], | |
364 kScalingList4x4ByteSize); | |
365 break; | |
366 | |
367 case 5: | |
368 memcpy(scaling_list4x4[i], scaling_list4x4[4], | |
369 kScalingList4x4ByteSize); | |
370 break; | |
371 | |
372 default: | |
373 NOTREACHED(); | |
374 break; | |
375 } | |
376 } | |
377 | |
378 static void FallbackScalingList8x8( | |
379 int i, | |
380 const int default_scaling_list_intra[], | |
381 const int default_scaling_list_inter[], | |
382 int scaling_list8x8[][kH264ScalingList8x8Length]) { | |
383 static const int kScalingList8x8ByteSize = sizeof(scaling_list8x8[0][0]) * | |
384 kH264ScalingList8x8Length; | |
385 | |
386 switch (i) { | |
387 case 0: | |
388 memcpy(scaling_list8x8[i], default_scaling_list_intra, | |
389 kScalingList8x8ByteSize); | |
390 break; | |
391 | |
392 case 1: | |
393 memcpy(scaling_list8x8[i], default_scaling_list_inter, | |
394 kScalingList8x8ByteSize); | |
395 break; | |
396 | |
397 case 2: | |
398 memcpy(scaling_list8x8[i], scaling_list8x8[0], | |
399 kScalingList8x8ByteSize); | |
400 break; | |
401 | |
402 case 3: | |
403 memcpy(scaling_list8x8[i], scaling_list8x8[1], | |
404 kScalingList8x8ByteSize); | |
405 break; | |
406 | |
407 case 4: | |
408 memcpy(scaling_list8x8[i], scaling_list8x8[2], | |
409 kScalingList8x8ByteSize); | |
410 break; | |
411 | |
412 case 5: | |
413 memcpy(scaling_list8x8[i], scaling_list8x8[3], | |
414 kScalingList8x8ByteSize); | |
415 break; | |
416 | |
417 default: | |
418 NOTREACHED(); | |
419 break; | |
420 } | |
421 } | |
422 | |
423 H264Parser::Result H264Parser::ParseScalingList(int size, | |
424 int* scaling_list, | |
425 bool* use_default) { | |
426 // See chapter 7.3.2.1.1.1. | |
427 int last_scale = 8; | |
428 int next_scale = 8; | |
429 int delta_scale; | |
430 | |
431 *use_default = false; | |
432 | |
433 for (int j = 0; j < size; ++j) { | |
434 if (next_scale != 0) { | |
435 READ_SE_OR_RETURN(&delta_scale); | |
436 IN_RANGE_OR_RETURN(delta_scale, -128, 127); | |
437 next_scale = (last_scale + delta_scale + 256) & 0xff; | |
438 | |
439 if (j == 0 && next_scale == 0) { | |
440 *use_default = true; | |
441 return kOk; | |
442 } | |
443 } | |
444 | |
445 scaling_list[j] = (next_scale == 0) ? last_scale : next_scale; | |
446 last_scale = scaling_list[j]; | |
447 } | |
448 | |
449 return kOk; | |
450 } | |
451 | |
452 H264Parser::Result H264Parser::ParseSPSScalingLists(H264SPS* sps) { | |
453 // See 7.4.2.1.1. | |
454 bool seq_scaling_list_present_flag; | |
455 bool use_default; | |
456 Result res; | |
457 | |
458 // Parse scaling_list4x4. | |
459 for (int i = 0; i < 6; ++i) { | |
460 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); | |
461 | |
462 if (seq_scaling_list_present_flag) { | |
463 res = ParseScalingList(arraysize(sps->scaling_list4x4[i]), | |
464 sps->scaling_list4x4[i], &use_default); | |
465 if (res != kOk) | |
466 return res; | |
467 | |
468 if (use_default) | |
469 DefaultScalingList4x4(i, sps->scaling_list4x4); | |
470 | |
471 } else { | |
472 FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, | |
473 sps->scaling_list4x4); | |
474 } | |
475 } | |
476 | |
477 // Parse scaling_list8x8. | |
478 for (int i = 0; i < ((sps->chroma_format_idc != 3) ? 2 : 6); ++i) { | |
479 READ_BOOL_OR_RETURN(&seq_scaling_list_present_flag); | |
480 | |
481 if (seq_scaling_list_present_flag) { | |
482 res = ParseScalingList(arraysize(sps->scaling_list8x8[i]), | |
483 sps->scaling_list8x8[i], &use_default); | |
484 if (res != kOk) | |
485 return res; | |
486 | |
487 if (use_default) | |
488 DefaultScalingList8x8(i, sps->scaling_list8x8); | |
489 | |
490 } else { | |
491 FallbackScalingList8x8(i, kDefault8x8Intra, kDefault8x8Inter, | |
492 sps->scaling_list8x8); | |
493 } | |
494 } | |
495 | |
496 return kOk; | |
497 } | |
498 | |
499 H264Parser::Result H264Parser::ParsePPSScalingLists(const H264SPS& sps, | |
500 H264PPS* pps) { | |
501 // See 7.4.2.2. | |
502 bool pic_scaling_list_present_flag; | |
503 bool use_default; | |
504 Result res; | |
505 | |
506 for (int i = 0; i < 6; ++i) { | |
507 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); | |
508 | |
509 if (pic_scaling_list_present_flag) { | |
510 res = ParseScalingList(arraysize(pps->scaling_list4x4[i]), | |
511 pps->scaling_list4x4[i], &use_default); | |
512 if (res != kOk) | |
513 return res; | |
514 | |
515 if (use_default) | |
516 DefaultScalingList4x4(i, pps->scaling_list4x4); | |
517 | |
518 } else { | |
519 if (sps.seq_scaling_matrix_present_flag) { | |
520 // Table 7-2 fallback rule A in spec. | |
521 FallbackScalingList4x4(i, kDefault4x4Intra, kDefault4x4Inter, | |
522 pps->scaling_list4x4); | |
523 } else { | |
524 // Table 7-2 fallback rule B in spec. | |
525 FallbackScalingList4x4(i, sps.scaling_list4x4[0], | |
526 sps.scaling_list4x4[3], pps->scaling_list4x4); | |
527 } | |
528 } | |
529 } | |
530 | |
531 if (pps->transform_8x8_mode_flag) { | |
532 for (int i = 0; i < ((sps.chroma_format_idc != 3) ? 2 : 6); ++i) { | |
533 READ_BOOL_OR_RETURN(&pic_scaling_list_present_flag); | |
534 | |
535 if (pic_scaling_list_present_flag) { | |
536 res = ParseScalingList(arraysize(pps->scaling_list8x8[i]), | |
537 pps->scaling_list8x8[i], &use_default); | |
538 if (res != kOk) | |
539 return res; | |
540 | |
541 if (use_default) | |
542 DefaultScalingList8x8(i, pps->scaling_list8x8); | |
543 | |
544 } else { | |
545 if (sps.seq_scaling_matrix_present_flag) { | |
546 // Table 7-2 fallback rule A in spec. | |
547 FallbackScalingList8x8(i, kDefault8x8Intra, | |
548 kDefault8x8Inter, pps->scaling_list8x8); | |
549 } else { | |
550 // Table 7-2 fallback rule B in spec. | |
551 FallbackScalingList8x8(i, sps.scaling_list8x8[0], | |
552 sps.scaling_list8x8[1], pps->scaling_list8x8); | |
553 } | |
554 } | |
555 } | |
556 } | |
557 return kOk; | |
558 } | |
559 | |
560 static void FillDefaultSeqScalingLists(H264SPS* sps) { | |
561 for (int i = 0; i < 6; ++i) | |
562 for (int j = 0; j < kH264ScalingList4x4Length; ++j) | |
563 sps->scaling_list4x4[i][j] = 16; | |
564 | |
565 for (int i = 0; i < 6; ++i) | |
566 for (int j = 0; j < kH264ScalingList8x8Length; ++j) | |
567 sps->scaling_list8x8[i][j] = 16; | |
568 } | |
569 | |
570 H264Parser::Result H264Parser::ParseSPS(int* sps_id) { | |
571 // See 7.4.2.1. | |
572 int data; | |
573 Result res; | |
574 | |
575 *sps_id = -1; | |
576 | |
577 scoped_ptr<H264SPS> sps(new H264SPS()); | |
578 | |
579 READ_BITS_OR_RETURN(8, &sps->profile_idc); | |
580 READ_BITS_OR_RETURN(6, &sps->constraint_setx_flag); | |
581 READ_BITS_OR_RETURN(2, &data); | |
582 READ_BITS_OR_RETURN(8, &sps->level_idc); | |
583 READ_UE_OR_RETURN(&sps->seq_parameter_set_id); | |
584 TRUE_OR_RETURN(sps->seq_parameter_set_id < 32); | |
585 | |
586 if (sps->profile_idc == 100 || sps->profile_idc == 110 || | |
587 sps->profile_idc == 122 || sps->profile_idc == 244 || | |
588 sps->profile_idc == 44 || sps->profile_idc == 83 || | |
589 sps->profile_idc == 86 || sps->profile_idc == 118 || | |
590 sps->profile_idc == 128) { | |
591 READ_UE_OR_RETURN(&sps->chroma_format_idc); | |
592 TRUE_OR_RETURN(sps->chroma_format_idc < 4); | |
593 | |
594 if (sps->chroma_format_idc == 3) | |
595 READ_BOOL_OR_RETURN(&sps->separate_colour_plane_flag); | |
596 | |
597 READ_UE_OR_RETURN(&sps->bit_depth_luma_minus8); | |
598 TRUE_OR_RETURN(sps->bit_depth_luma_minus8 < 7); | |
599 | |
600 READ_UE_OR_RETURN(&sps->bit_depth_chroma_minus8); | |
601 TRUE_OR_RETURN(sps->bit_depth_chroma_minus8 < 7); | |
602 | |
603 READ_BOOL_OR_RETURN(&sps->qpprime_y_zero_transform_bypass_flag); | |
604 READ_BOOL_OR_RETURN(&sps->seq_scaling_matrix_present_flag); | |
605 | |
606 if (sps->seq_scaling_matrix_present_flag) { | |
607 DVLOG(4) << "Scaling matrix present"; | |
608 res = ParseSPSScalingLists(sps.get()); | |
609 if (res != kOk) | |
610 return res; | |
611 } else { | |
612 FillDefaultSeqScalingLists(sps.get()); | |
613 } | |
614 } else { | |
615 sps->chroma_format_idc = 1; | |
616 FillDefaultSeqScalingLists(sps.get()); | |
617 } | |
618 | |
619 if (sps->separate_colour_plane_flag) | |
620 sps->chroma_array_type = 0; | |
621 else | |
622 sps->chroma_array_type = sps->chroma_format_idc; | |
623 | |
624 READ_UE_OR_RETURN(&sps->log2_max_frame_num_minus4); | |
625 TRUE_OR_RETURN(sps->log2_max_frame_num_minus4 < 13); | |
626 | |
627 READ_UE_OR_RETURN(&sps->pic_order_cnt_type); | |
628 TRUE_OR_RETURN(sps->pic_order_cnt_type < 3); | |
629 | |
630 sps->expected_delta_per_pic_order_cnt_cycle = 0; | |
631 if (sps->pic_order_cnt_type == 0) { | |
632 READ_UE_OR_RETURN(&sps->log2_max_pic_order_cnt_lsb_minus4); | |
633 TRUE_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 < 13); | |
634 } else if (sps->pic_order_cnt_type == 1) { | |
635 READ_BOOL_OR_RETURN(&sps->delta_pic_order_always_zero_flag); | |
636 READ_SE_OR_RETURN(&sps->offset_for_non_ref_pic); | |
637 READ_SE_OR_RETURN(&sps->offset_for_top_to_bottom_field); | |
638 READ_UE_OR_RETURN(&sps->num_ref_frames_in_pic_order_cnt_cycle); | |
639 TRUE_OR_RETURN(sps->num_ref_frames_in_pic_order_cnt_cycle < 255); | |
640 | |
641 for (int i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) { | |
642 READ_SE_OR_RETURN(&sps->offset_for_ref_frame[i]); | |
643 sps->expected_delta_per_pic_order_cnt_cycle += | |
644 sps->offset_for_ref_frame[i]; | |
645 } | |
646 } | |
647 | |
648 READ_UE_OR_RETURN(&sps->max_num_ref_frames); | |
649 READ_BOOL_OR_RETURN(&sps->gaps_in_frame_num_value_allowed_flag); | |
650 | |
651 if (sps->gaps_in_frame_num_value_allowed_flag) | |
652 return kUnsupportedStream; | |
653 | |
654 READ_UE_OR_RETURN(&sps->pic_width_in_mbs_minus1); | |
655 READ_UE_OR_RETURN(&sps->pic_height_in_map_units_minus1); | |
656 | |
657 READ_BOOL_OR_RETURN(&sps->frame_mbs_only_flag); | |
658 if (!sps->frame_mbs_only_flag) | |
659 READ_BOOL_OR_RETURN(&sps->mb_adaptive_frame_field_flag); | |
660 | |
661 READ_BOOL_OR_RETURN(&sps->direct_8x8_inference_flag); | |
662 | |
663 READ_BOOL_OR_RETURN(&sps->frame_cropping_flag); | |
664 if (sps->frame_cropping_flag) { | |
665 READ_UE_OR_RETURN(&sps->frame_crop_left_offset); | |
666 READ_UE_OR_RETURN(&sps->frame_crop_right_offset); | |
667 READ_UE_OR_RETURN(&sps->frame_crop_top_offset); | |
668 READ_UE_OR_RETURN(&sps->frame_crop_bottom_offset); | |
669 } | |
670 | |
671 READ_BOOL_OR_RETURN(&sps->vui_parameters_present_flag); | |
672 if (sps->vui_parameters_present_flag) { | |
673 DVLOG(1) << "VUI parameters present in SPS, ignoring"; | |
674 } | |
675 | |
676 // If an SPS with the same id already exists, replace it. | |
677 *sps_id = sps->seq_parameter_set_id; | |
678 delete active_SPSes_[*sps_id]; | |
679 active_SPSes_[*sps_id] = sps.release(); | |
680 | |
681 return kOk; | |
682 } | |
683 | |
684 H264Parser::Result H264Parser::ParsePPS(int* pps_id) { | |
685 // See 7.4.2.2. | |
686 const H264SPS* sps; | |
687 Result res; | |
688 | |
689 *pps_id = -1; | |
690 | |
691 scoped_ptr<H264PPS> pps(new H264PPS()); | |
692 | |
693 READ_UE_OR_RETURN(&pps->pic_parameter_set_id); | |
694 READ_UE_OR_RETURN(&pps->seq_parameter_set_id); | |
695 TRUE_OR_RETURN(pps->seq_parameter_set_id < 32); | |
696 | |
697 sps = GetSPS(pps->seq_parameter_set_id); | |
698 TRUE_OR_RETURN(sps); | |
699 | |
700 READ_BOOL_OR_RETURN(&pps->entropy_coding_mode_flag); | |
701 READ_BOOL_OR_RETURN(&pps->bottom_field_pic_order_in_frame_present_flag); | |
702 | |
703 READ_UE_OR_RETURN(&pps->num_slice_groups_minus1); | |
704 if (pps->num_slice_groups_minus1 > 1) { | |
705 DVLOG(1) << "Slice groups not supported"; | |
706 return kUnsupportedStream; | |
707 } | |
708 | |
709 READ_UE_OR_RETURN(&pps->num_ref_idx_l0_default_active_minus1); | |
710 TRUE_OR_RETURN(pps->num_ref_idx_l0_default_active_minus1 < 32); | |
711 | |
712 READ_UE_OR_RETURN(&pps->num_ref_idx_l1_default_active_minus1); | |
713 TRUE_OR_RETURN(pps->num_ref_idx_l1_default_active_minus1 < 32); | |
714 | |
715 READ_BOOL_OR_RETURN(&pps->weighted_pred_flag); | |
716 READ_BITS_OR_RETURN(2, &pps->weighted_bipred_idc); | |
717 TRUE_OR_RETURN(pps->weighted_bipred_idc < 3); | |
718 | |
719 READ_SE_OR_RETURN(&pps->pic_init_qp_minus26); | |
720 IN_RANGE_OR_RETURN(pps->pic_init_qp_minus26, -26, 25); | |
721 | |
722 READ_SE_OR_RETURN(&pps->pic_init_qs_minus26); | |
723 IN_RANGE_OR_RETURN(pps->pic_init_qs_minus26, -26, 25); | |
724 | |
725 READ_SE_OR_RETURN(&pps->chroma_qp_index_offset); | |
726 IN_RANGE_OR_RETURN(pps->chroma_qp_index_offset, -12, 12); | |
727 pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset; | |
728 | |
729 READ_BOOL_OR_RETURN(&pps->deblocking_filter_control_present_flag); | |
730 READ_BOOL_OR_RETURN(&pps->constrained_intra_pred_flag); | |
731 READ_BOOL_OR_RETURN(&pps->redundant_pic_cnt_present_flag); | |
732 | |
733 if (br_.HasMoreRBSPData()) { | |
734 READ_BOOL_OR_RETURN(&pps->transform_8x8_mode_flag); | |
735 READ_BOOL_OR_RETURN(&pps->pic_scaling_matrix_present_flag); | |
736 | |
737 if (pps->pic_scaling_matrix_present_flag) { | |
738 DVLOG(4) << "Picture scaling matrix present"; | |
739 res = ParsePPSScalingLists(*sps, pps.get()); | |
740 if (res != kOk) | |
741 return res; | |
742 } | |
743 | |
744 READ_SE_OR_RETURN(&pps->second_chroma_qp_index_offset); | |
745 } | |
746 | |
747 // If a PPS with the same id already exists, replace it. | |
748 *pps_id = pps->pic_parameter_set_id; | |
749 delete active_PPSes_[*pps_id]; | |
750 active_PPSes_[*pps_id] = pps.release(); | |
751 | |
752 return kOk; | |
753 } | |
754 | |
755 H264Parser::Result H264Parser::ParseRefPicListModification( | |
756 int num_ref_idx_active_minus1, | |
757 H264ModificationOfPicNum* ref_list_mods) { | |
758 H264ModificationOfPicNum* pic_num_mod; | |
759 | |
760 if (num_ref_idx_active_minus1 >= 32) | |
761 return kInvalidStream; | |
762 | |
763 for (int i = 0; i < 32; ++i) { | |
764 pic_num_mod = &ref_list_mods[i]; | |
765 READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc); | |
766 TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4); | |
767 | |
768 switch (pic_num_mod->modification_of_pic_nums_idc) { | |
769 case 0: | |
770 case 1: | |
771 READ_UE_OR_RETURN(&pic_num_mod->abs_diff_pic_num_minus1); | |
772 break; | |
773 | |
774 case 2: | |
775 READ_UE_OR_RETURN(&pic_num_mod->long_term_pic_num); | |
776 break; | |
777 | |
778 case 3: | |
779 // Per spec, list cannot be empty. | |
780 if (i == 0) | |
781 return kInvalidStream; | |
782 return kOk; | |
783 | |
784 default: | |
785 return kInvalidStream; | |
786 } | |
787 } | |
788 | |
789 // If we got here, we didn't get loop end marker prematurely, | |
790 // so make sure it is there for our client. | |
791 int modification_of_pic_nums_idc; | |
792 READ_UE_OR_RETURN(&modification_of_pic_nums_idc); | |
793 TRUE_OR_RETURN(modification_of_pic_nums_idc == 3); | |
794 | |
795 return kOk; | |
796 } | |
797 | |
798 H264Parser::Result H264Parser::ParseRefPicListModifications( | |
799 H264SliceHeader* shdr) { | |
800 Result res; | |
801 | |
802 if (!shdr->IsISlice() && !shdr->IsSISlice()) { | |
803 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l0); | |
804 if (shdr->ref_pic_list_modification_flag_l0) { | |
805 res = ParseRefPicListModification(shdr->num_ref_idx_l0_active_minus1, | |
806 shdr->ref_list_l0_modifications); | |
807 if (res != kOk) | |
808 return res; | |
809 } | |
810 } | |
811 | |
812 if (shdr->IsBSlice()) { | |
813 READ_BOOL_OR_RETURN(&shdr->ref_pic_list_modification_flag_l1); | |
814 if (shdr->ref_pic_list_modification_flag_l1) { | |
815 res = ParseRefPicListModification(shdr->num_ref_idx_l1_active_minus1, | |
816 shdr->ref_list_l1_modifications); | |
817 if (res != kOk) | |
818 return res; | |
819 } | |
820 } | |
821 | |
822 return kOk; | |
823 } | |
824 | |
825 H264Parser::Result H264Parser::ParseWeightingFactors( | |
826 int num_ref_idx_active_minus1, | |
827 int chroma_array_type, | |
828 int luma_log2_weight_denom, | |
829 int chroma_log2_weight_denom, | |
830 H264WeightingFactors* w_facts) { | |
831 | |
832 int def_luma_weight = 1 << luma_log2_weight_denom; | |
833 int def_chroma_weight = 1 << chroma_log2_weight_denom; | |
834 | |
835 for (int i = 0; i < num_ref_idx_active_minus1 + 1; ++i) { | |
836 READ_BOOL_OR_RETURN(&w_facts->luma_weight_flag); | |
837 if (w_facts->luma_weight_flag) { | |
838 READ_SE_OR_RETURN(&w_facts->luma_weight[i]); | |
839 IN_RANGE_OR_RETURN(w_facts->luma_weight[i], -128, 127); | |
840 | |
841 READ_SE_OR_RETURN(&w_facts->luma_offset[i]); | |
842 IN_RANGE_OR_RETURN(w_facts->luma_offset[i], -128, 127); | |
843 } else { | |
844 w_facts->luma_weight[i] = def_luma_weight; | |
845 w_facts->luma_offset[i] = 0; | |
846 } | |
847 | |
848 if (chroma_array_type != 0) { | |
849 READ_BOOL_OR_RETURN(&w_facts->chroma_weight_flag); | |
850 if (w_facts->chroma_weight_flag) { | |
851 for (int j = 0; j < 2; ++j) { | |
852 READ_SE_OR_RETURN(&w_facts->chroma_weight[i][j]); | |
853 IN_RANGE_OR_RETURN(w_facts->chroma_weight[i][j], -128, 127); | |
854 | |
855 READ_SE_OR_RETURN(&w_facts->chroma_offset[i][j]); | |
856 IN_RANGE_OR_RETURN(w_facts->chroma_offset[i][j], -128, 127); | |
857 } | |
858 } else { | |
859 for (int j = 0; j < 2; ++j) { | |
860 w_facts->chroma_weight[i][j] = def_chroma_weight; | |
861 w_facts->chroma_offset[i][j] = 0; | |
862 } | |
863 } | |
864 } | |
865 } | |
866 | |
867 return kOk; | |
868 } | |
869 | |
870 H264Parser::Result H264Parser::ParsePredWeightTable(const H264SPS& sps, | |
871 H264SliceHeader* shdr) { | |
872 READ_UE_OR_RETURN(&shdr->luma_log2_weight_denom); | |
873 TRUE_OR_RETURN(shdr->luma_log2_weight_denom < 8); | |
874 | |
875 if (sps.chroma_array_type != 0) | |
876 READ_UE_OR_RETURN(&shdr->chroma_log2_weight_denom); | |
877 TRUE_OR_RETURN(shdr->chroma_log2_weight_denom < 8); | |
878 | |
879 Result res = ParseWeightingFactors(shdr->num_ref_idx_l0_active_minus1, | |
880 sps.chroma_array_type, | |
881 shdr->luma_log2_weight_denom, | |
882 shdr->chroma_log2_weight_denom, | |
883 &shdr->pred_weight_table_l0); | |
884 if (res != kOk) | |
885 return res; | |
886 | |
887 if (shdr->IsBSlice()) { | |
888 res = ParseWeightingFactors(shdr->num_ref_idx_l1_active_minus1, | |
889 sps.chroma_array_type, | |
890 shdr->luma_log2_weight_denom, | |
891 shdr->chroma_log2_weight_denom, | |
892 &shdr->pred_weight_table_l1); | |
893 if (res != kOk) | |
894 return res; | |
895 } | |
896 | |
897 return kOk; | |
898 } | |
899 | |
900 H264Parser::Result H264Parser::ParseDecRefPicMarking(H264SliceHeader *shdr) { | |
901 if (shdr->idr_pic_flag) { | |
902 READ_BOOL_OR_RETURN(&shdr->no_output_of_prior_pics_flag); | |
903 READ_BOOL_OR_RETURN(&shdr->long_term_reference_flag); | |
904 } else { | |
905 READ_BOOL_OR_RETURN(&shdr->adaptive_ref_pic_marking_mode_flag); | |
906 | |
907 H264DecRefPicMarking* marking; | |
908 if (shdr->adaptive_ref_pic_marking_mode_flag) { | |
909 size_t i; | |
910 for (i = 0; i < arraysize(shdr->ref_pic_marking); ++i) { | |
911 marking = &shdr->ref_pic_marking[i]; | |
912 | |
913 READ_UE_OR_RETURN(&marking->memory_mgmnt_control_operation); | |
914 if (marking->memory_mgmnt_control_operation == 0) | |
915 break; | |
916 | |
917 if (marking->memory_mgmnt_control_operation == 1 || | |
918 marking->memory_mgmnt_control_operation == 3) | |
919 READ_UE_OR_RETURN(&marking->difference_of_pic_nums_minus1); | |
920 | |
921 if (marking->memory_mgmnt_control_operation == 2) | |
922 READ_UE_OR_RETURN(&marking->long_term_pic_num); | |
923 | |
924 if (marking->memory_mgmnt_control_operation == 3 || | |
925 marking->memory_mgmnt_control_operation == 6) | |
926 READ_UE_OR_RETURN(&marking->long_term_frame_idx); | |
927 | |
928 if (marking->memory_mgmnt_control_operation == 4) | |
929 READ_UE_OR_RETURN(&marking->max_long_term_frame_idx_plus1); | |
930 | |
931 if (marking->memory_mgmnt_control_operation > 6) | |
932 return kInvalidStream; | |
933 } | |
934 | |
935 if (i == arraysize(shdr->ref_pic_marking)) { | |
936 DVLOG(1) << "Ran out of dec ref pic marking fields"; | |
937 return kUnsupportedStream; | |
938 } | |
939 } | |
940 } | |
941 | |
942 return kOk; | |
943 } | |
944 | |
945 H264Parser::Result H264Parser::ParseSliceHeader(const H264NALU& nalu, | |
946 H264SliceHeader* shdr) { | |
947 // See 7.4.3. | |
948 const H264SPS* sps; | |
949 const H264PPS* pps; | |
950 Result res; | |
951 | |
952 memset(shdr, 0, sizeof(*shdr)); | |
953 | |
954 shdr->idr_pic_flag = (nalu.nal_unit_type == 5); | |
955 shdr->nal_ref_idc = nalu.nal_ref_idc; | |
956 shdr->nalu_data = nalu.data; | |
957 shdr->nalu_size = nalu.size; | |
958 | |
959 READ_UE_OR_RETURN(&shdr->first_mb_in_slice); | |
960 READ_UE_OR_RETURN(&shdr->slice_type); | |
961 TRUE_OR_RETURN(shdr->slice_type < 10); | |
962 | |
963 READ_UE_OR_RETURN(&shdr->pic_parameter_set_id); | |
964 | |
965 pps = GetPPS(shdr->pic_parameter_set_id); | |
966 TRUE_OR_RETURN(pps); | |
967 | |
968 sps = GetSPS(pps->seq_parameter_set_id); | |
969 TRUE_OR_RETURN(sps); | |
970 | |
971 if (sps->separate_colour_plane_flag) { | |
972 DVLOG(1) << "Interlaced streams not supported"; | |
973 return kUnsupportedStream; | |
974 } | |
975 | |
976 READ_BITS_OR_RETURN(sps->log2_max_frame_num_minus4 + 4, | |
977 &shdr->frame_num); | |
978 if (!sps->frame_mbs_only_flag) { | |
979 READ_BOOL_OR_RETURN(&shdr->field_pic_flag); | |
980 if (shdr->field_pic_flag) { | |
981 DVLOG(1) << "Interlaced streams not supported"; | |
982 return kUnsupportedStream; | |
983 } | |
984 } | |
985 | |
986 if (shdr->idr_pic_flag) | |
987 READ_UE_OR_RETURN(&shdr->idr_pic_id); | |
988 | |
989 if (sps->pic_order_cnt_type == 0) { | |
990 READ_BITS_OR_RETURN(sps->log2_max_pic_order_cnt_lsb_minus4 + 4, | |
991 &shdr->pic_order_cnt_lsb); | |
992 if (pps->bottom_field_pic_order_in_frame_present_flag && | |
993 !shdr->field_pic_flag) | |
994 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt_bottom); | |
995 } | |
996 | |
997 if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) { | |
998 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[0]); | |
999 if (pps->bottom_field_pic_order_in_frame_present_flag && | |
1000 !shdr->field_pic_flag) | |
1001 READ_SE_OR_RETURN(&shdr->delta_pic_order_cnt[1]); | |
1002 } | |
1003 | |
1004 if (pps->redundant_pic_cnt_present_flag) { | |
1005 READ_UE_OR_RETURN(&shdr->redundant_pic_cnt); | |
1006 TRUE_OR_RETURN(shdr->redundant_pic_cnt < 128); | |
1007 } | |
1008 | |
1009 if (shdr->IsBSlice()) | |
1010 READ_BOOL_OR_RETURN(&shdr->direct_spatial_mv_pred_flag); | |
1011 | |
1012 if (shdr->IsPSlice() || shdr->IsSPSlice() || shdr->IsBSlice()) { | |
1013 READ_BOOL_OR_RETURN(&shdr->num_ref_idx_active_override_flag); | |
1014 if (shdr->num_ref_idx_active_override_flag) { | |
1015 READ_UE_OR_RETURN(&shdr->num_ref_idx_l0_active_minus1); | |
1016 if (shdr->IsBSlice()) | |
1017 READ_UE_OR_RETURN(&shdr->num_ref_idx_l1_active_minus1); | |
1018 } else { | |
1019 shdr->num_ref_idx_l0_active_minus1 = | |
1020 pps->num_ref_idx_l0_default_active_minus1; | |
1021 if (shdr->IsBSlice()) { | |
1022 shdr->num_ref_idx_l1_active_minus1 = | |
1023 pps->num_ref_idx_l1_default_active_minus1; | |
1024 } | |
1025 } | |
1026 } | |
1027 if (shdr->field_pic_flag) { | |
1028 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 32); | |
1029 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 32); | |
1030 } else { | |
1031 TRUE_OR_RETURN(shdr->num_ref_idx_l0_active_minus1 < 16); | |
1032 TRUE_OR_RETURN(shdr->num_ref_idx_l1_active_minus1 < 16); | |
1033 } | |
1034 | |
1035 if (nalu.nal_unit_type == H264NALU::kCodedSliceExtension) { | |
1036 return kUnsupportedStream; | |
1037 } else { | |
1038 res = ParseRefPicListModifications(shdr); | |
1039 if (res != kOk) | |
1040 return res; | |
1041 } | |
1042 | |
1043 if ((pps->weighted_pred_flag && (shdr->IsPSlice() || shdr->IsSPSlice())) || | |
1044 (pps->weighted_bipred_idc == 1 && shdr->IsBSlice())) { | |
1045 res = ParsePredWeightTable(*sps, shdr); | |
1046 if (res != kOk) | |
1047 return res; | |
1048 } | |
1049 | |
1050 if (nalu.nal_ref_idc != 0) { | |
1051 res = ParseDecRefPicMarking(shdr); | |
1052 if (res != kOk) | |
1053 return res; | |
1054 } | |
1055 | |
1056 if (pps->entropy_coding_mode_flag && | |
1057 !shdr->IsISlice() && !shdr->IsSISlice()) { | |
1058 READ_UE_OR_RETURN(&shdr->cabac_init_idc); | |
1059 TRUE_OR_RETURN(shdr->cabac_init_idc < 3); | |
1060 } | |
1061 | |
1062 READ_SE_OR_RETURN(&shdr->slice_qp_delta); | |
1063 | |
1064 if (shdr->IsSPSlice() || shdr->IsSISlice()) { | |
1065 if (shdr->IsSPSlice()) | |
1066 READ_BOOL_OR_RETURN(&shdr->sp_for_switch_flag); | |
1067 READ_SE_OR_RETURN(&shdr->slice_qs_delta); | |
1068 } | |
1069 | |
1070 if (pps->deblocking_filter_control_present_flag) { | |
1071 READ_UE_OR_RETURN(&shdr->disable_deblocking_filter_idc); | |
1072 TRUE_OR_RETURN(shdr->disable_deblocking_filter_idc < 3); | |
1073 | |
1074 if (shdr->disable_deblocking_filter_idc != 1) { | |
1075 READ_SE_OR_RETURN(&shdr->slice_alpha_c0_offset_div2); | |
1076 IN_RANGE_OR_RETURN(shdr->slice_alpha_c0_offset_div2, -6, 6); | |
1077 | |
1078 READ_SE_OR_RETURN(&shdr->slice_beta_offset_div2); | |
1079 IN_RANGE_OR_RETURN(shdr->slice_beta_offset_div2, -6, 6); | |
1080 } | |
1081 } | |
1082 | |
1083 if (pps->num_slice_groups_minus1 > 0) { | |
1084 DVLOG(1) << "Slice groups not supported"; | |
1085 return kUnsupportedStream; | |
1086 } | |
1087 | |
1088 size_t epb = br_.NumEmulationPreventionBytesRead(); | |
1089 shdr->header_bit_size = (shdr->nalu_size - epb) * 8 - br_.NumBitsLeft(); | |
1090 | |
1091 return kOk; | |
1092 } | |
1093 | |
1094 H264Parser::Result H264Parser::ParseSEI(H264SEIMessage* sei_msg) { | |
1095 int byte; | |
1096 | |
1097 memset(sei_msg, 0, sizeof(*sei_msg)); | |
1098 | |
1099 READ_BITS_OR_RETURN(8, &byte); | |
1100 while (byte == 0xff) { | |
1101 sei_msg->type += 255; | |
1102 READ_BITS_OR_RETURN(8, &byte); | |
1103 } | |
1104 sei_msg->type += byte; | |
1105 | |
1106 READ_BITS_OR_RETURN(8, &byte); | |
1107 while (byte == 0xff) { | |
1108 sei_msg->payload_size += 255; | |
1109 READ_BITS_OR_RETURN(8, &byte); | |
1110 } | |
1111 sei_msg->payload_size += byte; | |
1112 | |
1113 DVLOG(4) << "Found SEI message type: " << sei_msg->type | |
1114 << " payload size: " << sei_msg->payload_size; | |
1115 | |
1116 switch (sei_msg->type) { | |
1117 case H264SEIMessage::kSEIRecoveryPoint: | |
1118 READ_UE_OR_RETURN(&sei_msg->recovery_point.recovery_frame_cnt); | |
1119 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.exact_match_flag); | |
1120 READ_BOOL_OR_RETURN(&sei_msg->recovery_point.broken_link_flag); | |
1121 READ_BITS_OR_RETURN(2, | |
1122 &sei_msg->recovery_point.changing_slice_group_idc); | |
1123 break; | |
1124 | |
1125 default: | |
1126 DVLOG(4) << "Unsupported SEI message"; | |
1127 break; | |
1128 } | |
1129 | |
1130 return kOk; | |
1131 } | |
1132 | |
1133 } // namespace content | |
OLD | NEW |