Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: content/common/gpu/media/h264_parser.cc

Issue 119153002: Move H264Parser and H264BitReader to media/filters. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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
OLDNEW
« no previous file with comments | « content/common/gpu/media/h264_parser.h ('k') | content/common/gpu/media/h264_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698