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

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

Issue 852103002: Revert of Add accelerated video decoder interface, VP8 and H.264 implementations and hook up to V4L2SVDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
« no previous file with comments | « content/common/gpu/media/h264_decoder.h ('k') | content/common/gpu/media/h264_dpb.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <algorithm>
6 #include <limits>
7
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/callback_helpers.h"
11 #include "base/numerics/safe_conversions.h"
12 #include "base/stl_util.h"
13 #include "content/common/gpu/media/h264_decoder.h"
14
15 namespace content {
16
17 H264Decoder::H264Accelerator::H264Accelerator() {
18 }
19
20 H264Decoder::H264Accelerator::~H264Accelerator() {
21 }
22
23 H264Decoder::H264Decoder(H264Accelerator* accelerator)
24 : max_pic_order_cnt_lsb_(0),
25 max_frame_num_(0),
26 max_pic_num_(0),
27 max_long_term_frame_idx_(0),
28 max_num_reorder_frames_(0),
29 curr_sps_id_(-1),
30 curr_pps_id_(-1),
31 accelerator_(accelerator) {
32 DCHECK(accelerator_);
33 Reset();
34 state_ = kNeedStreamMetadata;
35 }
36
37 H264Decoder::~H264Decoder() {
38 }
39
40 void H264Decoder::Reset() {
41 curr_pic_ = nullptr;
42 curr_nalu_ = nullptr;
43 curr_slice_hdr_ = nullptr;
44
45 frame_num_ = 0;
46 prev_frame_num_ = -1;
47 prev_frame_num_offset_ = -1;
48
49 prev_ref_has_memmgmnt5_ = false;
50 prev_ref_top_field_order_cnt_ = -1;
51 prev_ref_pic_order_cnt_msb_ = -1;
52 prev_ref_pic_order_cnt_lsb_ = -1;
53 prev_ref_field_ = H264Picture::FIELD_NONE;
54
55 ref_pic_list_p0_.clear();
56 ref_pic_list_b0_.clear();
57 ref_pic_list_b1_.clear();
58 dpb_.Clear();
59 parser_.Reset();
60 last_output_poc_ = std::numeric_limits<int>::min();
61
62 // If we are in kDecoding, we can resume without processing an SPS.
63 if (state_ == kDecoding)
64 state_ = kAfterReset;
65 }
66
67 void H264Decoder::PrepareRefPicLists(media::H264SliceHeader* slice_hdr) {
68 ConstructReferencePicListsP(slice_hdr);
69 ConstructReferencePicListsB(slice_hdr);
70 }
71
72 bool H264Decoder::ModifyReferencePicLists(media::H264SliceHeader* slice_hdr,
73 H264Picture::Vector* ref_pic_list0,
74 H264Picture::Vector* ref_pic_list1) {
75 ref_pic_list0->clear();
76 ref_pic_list1->clear();
77
78 // Fill reference picture lists for B and S/SP slices.
79 if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) {
80 *ref_pic_list0 = ref_pic_list_p0_;
81 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0);
82 } else if (slice_hdr->IsBSlice()) {
83 *ref_pic_list0 = ref_pic_list_b0_;
84 *ref_pic_list1 = ref_pic_list_b1_;
85 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0) &&
86 ModifyReferencePicList(slice_hdr, 1, ref_pic_list1);
87 }
88
89 return true;
90 }
91
92 bool H264Decoder::DecodePicture() {
93 DCHECK(curr_pic_.get());
94
95 DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt;
96 return accelerator_->SubmitDecode(curr_pic_);
97 }
98
99 bool H264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) {
100 DCHECK(curr_pic_.get());
101
102 curr_pic_->idr = slice_hdr->idr_pic_flag;
103
104 if (slice_hdr->field_pic_flag) {
105 curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM
106 : H264Picture::FIELD_TOP;
107 } else {
108 curr_pic_->field = H264Picture::FIELD_NONE;
109 }
110
111 curr_pic_->ref = slice_hdr->nal_ref_idc != 0;
112 // This assumes non-interlaced stream.
113 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num;
114
115 if (!CalculatePicOrderCounts(slice_hdr))
116 return false;
117
118 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag;
119 curr_pic_->adaptive_ref_pic_marking_mode_flag =
120 slice_hdr->adaptive_ref_pic_marking_mode_flag;
121
122 // If the slice header indicates we will have to perform reference marking
123 // process after this picture is decoded, store required data for that
124 // purpose.
125 if (slice_hdr->adaptive_ref_pic_marking_mode_flag) {
126 COMPILE_ASSERT(sizeof(curr_pic_->ref_pic_marking) ==
127 sizeof(slice_hdr->ref_pic_marking),
128 ref_pic_marking_array_sizes_do_not_match);
129 memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking,
130 sizeof(curr_pic_->ref_pic_marking));
131 }
132
133 return true;
134 }
135
136 bool H264Decoder::CalculatePicOrderCounts(media::H264SliceHeader* slice_hdr) {
137 DCHECK_NE(curr_sps_id_, -1);
138 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_);
139
140 int pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb;
141 curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb;
142
143 switch (sps->pic_order_cnt_type) {
144 case 0:
145 // See spec 8.2.1.1.
146 int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb;
147 if (slice_hdr->idr_pic_flag) {
148 prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0;
149 } else {
150 if (prev_ref_has_memmgmnt5_) {
151 if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) {
152 prev_pic_order_cnt_msb = 0;
153 prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_;
154 } else {
155 prev_pic_order_cnt_msb = 0;
156 prev_pic_order_cnt_lsb = 0;
157 }
158 } else {
159 prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_;
160 prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_;
161 }
162 }
163
164 DCHECK_NE(max_pic_order_cnt_lsb_, 0);
165 if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
166 (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >=
167 max_pic_order_cnt_lsb_ / 2)) {
168 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb +
169 max_pic_order_cnt_lsb_;
170 } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
171 (pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
172 max_pic_order_cnt_lsb_ / 2)) {
173 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb -
174 max_pic_order_cnt_lsb_;
175 } else {
176 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb;
177 }
178
179 if (curr_pic_->field != H264Picture::FIELD_BOTTOM) {
180 curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb +
181 pic_order_cnt_lsb;
182 }
183
184 if (curr_pic_->field != H264Picture::FIELD_TOP) {
185 // TODO posciak: perhaps replace with pic->field?
186 if (!slice_hdr->field_pic_flag) {
187 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
188 slice_hdr->delta_pic_order_cnt_bottom;
189 } else {
190 curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb +
191 pic_order_cnt_lsb;
192 }
193 }
194 break;
195
196 case 1: {
197 // See spec 8.2.1.2.
198 if (prev_has_memmgmnt5_)
199 prev_frame_num_offset_ = 0;
200
201 if (slice_hdr->idr_pic_flag)
202 curr_pic_->frame_num_offset = 0;
203 else if (prev_frame_num_ > slice_hdr->frame_num)
204 curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
205 else
206 curr_pic_->frame_num_offset = prev_frame_num_offset_;
207
208 int abs_frame_num = 0;
209 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0)
210 abs_frame_num = curr_pic_->frame_num_offset + slice_hdr->frame_num;
211 else
212 abs_frame_num = 0;
213
214 if (slice_hdr->nal_ref_idc == 0 && abs_frame_num > 0)
215 --abs_frame_num;
216
217 int expected_pic_order_cnt = 0;
218 if (abs_frame_num > 0) {
219 if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) {
220 DVLOG(1) << "Invalid num_ref_frames_in_pic_order_cnt_cycle "
221 << "in stream";
222 return false;
223 }
224
225 int pic_order_cnt_cycle_cnt = (abs_frame_num - 1) /
226 sps->num_ref_frames_in_pic_order_cnt_cycle;
227 int frame_num_in_pic_order_cnt_cycle = (abs_frame_num - 1) %
228 sps->num_ref_frames_in_pic_order_cnt_cycle;
229
230 expected_pic_order_cnt = pic_order_cnt_cycle_cnt *
231 sps->expected_delta_per_pic_order_cnt_cycle;
232 // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser
233 for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i)
234 expected_pic_order_cnt += sps->offset_for_ref_frame[i];
235 }
236
237 if (!slice_hdr->nal_ref_idc)
238 expected_pic_order_cnt += sps->offset_for_non_ref_pic;
239
240 if (!slice_hdr->field_pic_flag) {
241 curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
242 slice_hdr->delta_pic_order_cnt0;
243 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
244 sps->offset_for_top_to_bottom_field +
245 slice_hdr->delta_pic_order_cnt1;
246 } else if (!slice_hdr->bottom_field_flag) {
247 curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
248 slice_hdr->delta_pic_order_cnt0;
249 } else {
250 curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt +
251 sps->offset_for_top_to_bottom_field +
252 slice_hdr->delta_pic_order_cnt0;
253 }
254 break;
255 }
256
257 case 2:
258 // See spec 8.2.1.3.
259 if (prev_has_memmgmnt5_)
260 prev_frame_num_offset_ = 0;
261
262 if (slice_hdr->idr_pic_flag)
263 curr_pic_->frame_num_offset = 0;
264 else if (prev_frame_num_ > slice_hdr->frame_num)
265 curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_;
266 else
267 curr_pic_->frame_num_offset = prev_frame_num_offset_;
268
269 int temp_pic_order_cnt;
270 if (slice_hdr->idr_pic_flag) {
271 temp_pic_order_cnt = 0;
272 } else if (!slice_hdr->nal_ref_idc) {
273 temp_pic_order_cnt =
274 2 * (curr_pic_->frame_num_offset + slice_hdr->frame_num) - 1;
275 } else {
276 temp_pic_order_cnt = 2 * (curr_pic_->frame_num_offset +
277 slice_hdr->frame_num);
278 }
279
280 if (!slice_hdr->field_pic_flag) {
281 curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
282 curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
283 } else if (slice_hdr->bottom_field_flag) {
284 curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt;
285 } else {
286 curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
287 }
288 break;
289
290 default:
291 DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
292 return false;
293 }
294
295 switch (curr_pic_->field) {
296 case H264Picture::FIELD_NONE:
297 curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt,
298 curr_pic_->bottom_field_order_cnt);
299 break;
300 case H264Picture::FIELD_TOP:
301 curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt;
302 break;
303 case H264Picture::FIELD_BOTTOM:
304 curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt;
305 break;
306 }
307
308 return true;
309 }
310
311 void H264Decoder::UpdatePicNums() {
312 for (auto& pic : dpb_) {
313 if (!pic->ref)
314 continue;
315
316 // Below assumes non-interlaced stream.
317 DCHECK_EQ(pic->field, H264Picture::FIELD_NONE);
318 if (pic->long_term) {
319 pic->long_term_pic_num = pic->long_term_frame_idx;
320 } else {
321 if (pic->frame_num > frame_num_)
322 pic->frame_num_wrap = pic->frame_num - max_frame_num_;
323 else
324 pic->frame_num_wrap = pic->frame_num;
325
326 pic->pic_num = pic->frame_num_wrap;
327 }
328 }
329 }
330
331 struct PicNumDescCompare {
332 bool operator()(const scoped_refptr<H264Picture>& a,
333 const scoped_refptr<H264Picture>& b) const {
334 return a->pic_num > b->pic_num;
335 }
336 };
337
338 struct LongTermPicNumAscCompare {
339 bool operator()(const scoped_refptr<H264Picture>& a,
340 const scoped_refptr<H264Picture>& b) const {
341 return a->long_term_pic_num < b->long_term_pic_num;
342 }
343 };
344
345 void H264Decoder::ConstructReferencePicListsP(
346 media::H264SliceHeader* slice_hdr) {
347 // RefPicList0 (8.2.4.2.1) [[1] [2]], where:
348 // [1] shortterm ref pics sorted by descending pic_num,
349 // [2] longterm ref pics by ascending long_term_pic_num.
350 ref_pic_list_p0_.clear();
351
352 // First get the short ref pics...
353 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_p0_);
354 size_t num_short_refs = ref_pic_list_p0_.size();
355
356 // and sort them to get [1].
357 std::sort(ref_pic_list_p0_.begin(), ref_pic_list_p0_.end(),
358 PicNumDescCompare());
359
360 // Now get long term pics and sort them by long_term_pic_num to get [2].
361 dpb_.GetLongTermRefPicsAppending(&ref_pic_list_p0_);
362 std::sort(ref_pic_list_p0_.begin() + num_short_refs, ref_pic_list_p0_.end(),
363 LongTermPicNumAscCompare());
364
365 // Cut off if we have more than requested in slice header.
366 ref_pic_list_p0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
367 }
368
369 struct POCAscCompare {
370 bool operator()(const scoped_refptr<H264Picture>& a,
371 const scoped_refptr<H264Picture>& b) const {
372 return a->pic_order_cnt < b->pic_order_cnt;
373 }
374 };
375
376 struct POCDescCompare {
377 bool operator()(const scoped_refptr<H264Picture>& a,
378 const scoped_refptr<H264Picture>& b) const {
379 return a->pic_order_cnt > b->pic_order_cnt;
380 }
381 };
382
383 void H264Decoder::ConstructReferencePicListsB(
384 media::H264SliceHeader* slice_hdr) {
385 // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where:
386 // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC,
387 // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC,
388 // [3] longterm ref pics by ascending long_term_pic_num.
389 ref_pic_list_b0_.clear();
390 ref_pic_list_b1_.clear();
391 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_b0_);
392 size_t num_short_refs = ref_pic_list_b0_.size();
393
394 // First sort ascending, this will put [1] in right place and finish [2].
395 std::sort(ref_pic_list_b0_.begin(), ref_pic_list_b0_.end(), POCAscCompare());
396
397 // Find first with POC > curr_pic's POC to get first element in [2]...
398 H264Picture::Vector::iterator iter;
399 iter = std::upper_bound(ref_pic_list_b0_.begin(), ref_pic_list_b0_.end(),
400 curr_pic_.get(), POCAscCompare());
401
402 // and sort [1] descending, thus finishing sequence [1] [2].
403 std::sort(ref_pic_list_b0_.begin(), iter, POCDescCompare());
404
405 // Now add [3] and sort by ascending long_term_pic_num.
406 dpb_.GetLongTermRefPicsAppending(&ref_pic_list_b0_);
407 std::sort(ref_pic_list_b0_.begin() + num_short_refs, ref_pic_list_b0_.end(),
408 LongTermPicNumAscCompare());
409
410 // RefPicList1 (8.2.4.2.4) [[1] [2] [3]], where:
411 // [1] shortterm ref pics with POC > curr_pic's POC sorted by ascending POC,
412 // [2] shortterm ref pics with POC < curr_pic's POC by descending POC,
413 // [3] longterm ref pics by ascending long_term_pic_num.
414
415 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_b1_);
416 num_short_refs = ref_pic_list_b1_.size();
417
418 // First sort by descending POC.
419 std::sort(ref_pic_list_b1_.begin(), ref_pic_list_b1_.end(), POCDescCompare());
420
421 // Find first with POC < curr_pic's POC to get first element in [2]...
422 iter = std::upper_bound(ref_pic_list_b1_.begin(), ref_pic_list_b1_.end(),
423 curr_pic_.get(), POCDescCompare());
424
425 // and sort [1] ascending.
426 std::sort(ref_pic_list_b1_.begin(), iter, POCAscCompare());
427
428 // Now add [3] and sort by ascending long_term_pic_num
429 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_b1_);
430 std::sort(ref_pic_list_b1_.begin() + num_short_refs, ref_pic_list_b1_.end(),
431 LongTermPicNumAscCompare());
432
433 // If lists identical, swap first two entries in RefPicList1 (spec 8.2.4.2.3)
434 if (ref_pic_list_b1_.size() > 1 &&
435 std::equal(ref_pic_list_b0_.begin(), ref_pic_list_b0_.end(),
436 ref_pic_list_b1_.begin()))
437 std::swap(ref_pic_list_b1_[0], ref_pic_list_b1_[1]);
438
439 // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate
440 // there should be more ref pics on list than we constructed.
441 // Those superfluous ones should be treated as non-reference.
442 ref_pic_list_b0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
443 ref_pic_list_b1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1);
444 }
445
446 // See 8.2.4
447 int H264Decoder::PicNumF(const scoped_refptr<H264Picture>& pic) {
448 if (!pic)
449 return -1;
450
451 if (!pic->long_term)
452 return pic->pic_num;
453 else
454 return max_pic_num_;
455 }
456
457 // See 8.2.4
458 int H264Decoder::LongTermPicNumF(const scoped_refptr<H264Picture>& pic) {
459 if (pic->ref && pic->long_term)
460 return pic->long_term_pic_num;
461 else
462 return 2 * (max_long_term_frame_idx_ + 1);
463 }
464
465 // Shift elements on the |v| starting from |from| to |to|, inclusive,
466 // one position to the right and insert pic at |from|.
467 static void ShiftRightAndInsert(H264Picture::Vector* v,
468 int from,
469 int to,
470 const scoped_refptr<H264Picture>& pic) {
471 // Security checks, do not disable in Debug mode.
472 CHECK(from <= to);
473 CHECK(to <= std::numeric_limits<int>::max() - 2);
474 // Additional checks. Debug mode ok.
475 DCHECK(v);
476 DCHECK(pic);
477 DCHECK((to + 1 == static_cast<int>(v->size())) ||
478 (to + 2 == static_cast<int>(v->size())));
479
480 v->resize(to + 2);
481
482 for (int i = to + 1; i > from; --i)
483 (*v)[i] = (*v)[i - 1];
484
485 (*v)[from] = pic;
486 }
487
488 bool H264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr,
489 int list,
490 H264Picture::Vector* ref_pic_listx) {
491 int num_ref_idx_lX_active_minus1;
492 media::H264ModificationOfPicNum* list_mod;
493
494 // This can process either ref_pic_list0 or ref_pic_list1, depending on
495 // the list argument. Set up pointers to proper list to be processed here.
496 if (list == 0) {
497 if (!slice_hdr->ref_pic_list_modification_flag_l0)
498 return true;
499
500 list_mod = slice_hdr->ref_list_l0_modifications;
501 } else {
502 if (!slice_hdr->ref_pic_list_modification_flag_l1)
503 return true;
504
505 list_mod = slice_hdr->ref_list_l1_modifications;
506 }
507
508 num_ref_idx_lX_active_minus1 = ref_pic_listx->size() - 1;
509 DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
510
511 // Spec 8.2.4.3:
512 // Reorder pictures on the list in a way specified in the stream.
513 int pic_num_lx_pred = curr_pic_->pic_num;
514 int ref_idx_lx = 0;
515 int pic_num_lx_no_wrap;
516 int pic_num_lx;
517 bool done = false;
518 scoped_refptr<H264Picture> pic;
519 for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) {
520 switch (list_mod->modification_of_pic_nums_idc) {
521 case 0:
522 case 1:
523 // Modify short reference picture position.
524 if (list_mod->modification_of_pic_nums_idc == 0) {
525 // Subtract given value from predicted PicNum.
526 pic_num_lx_no_wrap = pic_num_lx_pred -
527 (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
528 // Wrap around max_pic_num_ if it becomes < 0 as result
529 // of subtraction.
530 if (pic_num_lx_no_wrap < 0)
531 pic_num_lx_no_wrap += max_pic_num_;
532 } else {
533 // Add given value to predicted PicNum.
534 pic_num_lx_no_wrap = pic_num_lx_pred +
535 (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
536 // Wrap around max_pic_num_ if it becomes >= max_pic_num_ as result
537 // of the addition.
538 if (pic_num_lx_no_wrap >= max_pic_num_)
539 pic_num_lx_no_wrap -= max_pic_num_;
540 }
541
542 // For use in next iteration.
543 pic_num_lx_pred = pic_num_lx_no_wrap;
544
545 if (pic_num_lx_no_wrap > curr_pic_->pic_num)
546 pic_num_lx = pic_num_lx_no_wrap - max_pic_num_;
547 else
548 pic_num_lx = pic_num_lx_no_wrap;
549
550 DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
551 media::H264SliceHeader::kRefListModSize);
552 pic = dpb_.GetShortRefPicByPicNum(pic_num_lx);
553 if (!pic) {
554 DVLOG(1) << "Malformed stream, no pic num " << pic_num_lx;
555 return false;
556 }
557 ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
558 num_ref_idx_lX_active_minus1, pic);
559 ref_idx_lx++;
560
561 for (int src = ref_idx_lx, dst = ref_idx_lx;
562 src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
563 if (PicNumF((*ref_pic_listx)[src]) != pic_num_lx)
564 (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
565 }
566 break;
567
568 case 2:
569 // Modify long term reference picture position.
570 DCHECK_LT(num_ref_idx_lX_active_minus1 + 1,
571 media::H264SliceHeader::kRefListModSize);
572 pic = dpb_.GetLongRefPicByLongTermPicNum(list_mod->long_term_pic_num);
573 if (!pic) {
574 DVLOG(1) << "Malformed stream, no pic num "
575 << list_mod->long_term_pic_num;
576 return false;
577 }
578 ShiftRightAndInsert(ref_pic_listx, ref_idx_lx,
579 num_ref_idx_lX_active_minus1, pic);
580 ref_idx_lx++;
581
582 for (int src = ref_idx_lx, dst = ref_idx_lx;
583 src <= num_ref_idx_lX_active_minus1 + 1; ++src) {
584 if (LongTermPicNumF((*ref_pic_listx)[src]) !=
585 static_cast<int>(list_mod->long_term_pic_num))
586 (*ref_pic_listx)[dst++] = (*ref_pic_listx)[src];
587 }
588 break;
589
590 case 3:
591 // End of modification list.
592 done = true;
593 break;
594
595 default:
596 // May be recoverable.
597 DVLOG(1) << "Invalid modification_of_pic_nums_idc="
598 << list_mod->modification_of_pic_nums_idc
599 << " in position " << i;
600 break;
601 }
602
603 ++list_mod;
604 }
605
606 // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is
607 // temporarily made one element longer than the required final list.
608 // Resize the list back to its required size.
609 ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1);
610
611 return true;
612 }
613
614 void H264Decoder::OutputPic(scoped_refptr<H264Picture> pic) {
615 DCHECK(!pic->outputted);
616 pic->outputted = true;
617 last_output_poc_ = pic->pic_order_cnt;
618
619 DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt;
620 accelerator_->OutputPicture(pic);
621 }
622
623 void H264Decoder::ClearDPB() {
624 // Clear DPB contents, marking the pictures as unused first.
625 dpb_.Clear();
626 last_output_poc_ = std::numeric_limits<int>::min();
627 }
628
629 bool H264Decoder::OutputAllRemainingPics() {
630 // Output all pictures that are waiting to be outputted.
631 FinishPrevFrameIfPresent();
632 H264Picture::Vector to_output;
633 dpb_.GetNotOutputtedPicsAppending(&to_output);
634 // Sort them by ascending POC to output in order.
635 std::sort(to_output.begin(), to_output.end(), POCAscCompare());
636
637 for (auto& pic : to_output)
638 OutputPic(pic);
639
640 return true;
641 }
642
643 bool H264Decoder::Flush() {
644 DVLOG(2) << "Decoder flush";
645
646 if (!OutputAllRemainingPics())
647 return false;
648
649 ClearDPB();
650 DVLOG(2) << "Decoder flush finished";
651 return true;
652 }
653
654 bool H264Decoder::StartNewFrame(media::H264SliceHeader* slice_hdr) {
655 // TODO posciak: add handling of max_num_ref_frames per spec.
656 CHECK(curr_pic_.get());
657
658 if (!InitCurrPicture(slice_hdr))
659 return false;
660
661 DCHECK_GT(max_frame_num_, 0);
662
663 UpdatePicNums();
664 DCHECK(slice_hdr);
665 PrepareRefPicLists(slice_hdr);
666
667 const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_);
668 DCHECK(pps);
669 const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id);
670 DCHECK(sps);
671
672 if (!accelerator_->SubmitFrameMetadata(sps, pps, dpb_, ref_pic_list_p0_,
673 ref_pic_list_b0_, ref_pic_list_b1_,
674 curr_pic_.get()))
675 return false;
676
677 return true;
678 }
679
680 bool H264Decoder::HandleMemoryManagementOps() {
681 // 8.2.5.4
682 for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) {
683 // Code below does not support interlaced stream (per-field pictures).
684 media::H264DecRefPicMarking* ref_pic_marking =
685 &curr_pic_->ref_pic_marking[i];
686 scoped_refptr<H264Picture> to_mark;
687 int pic_num_x;
688
689 switch (ref_pic_marking->memory_mgmnt_control_operation) {
690 case 0:
691 // Normal end of operations' specification.
692 return true;
693
694 case 1:
695 // Mark a short term reference picture as unused so it can be removed
696 // if outputted.
697 pic_num_x = curr_pic_->pic_num -
698 (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
699 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
700 if (to_mark) {
701 to_mark->ref = false;
702 } else {
703 DVLOG(1) << "Invalid short ref pic num to unmark";
704 return false;
705 }
706 break;
707
708 case 2:
709 // Mark a long term reference picture as unused so it can be removed
710 // if outputted.
711 to_mark = dpb_.GetLongRefPicByLongTermPicNum(
712 ref_pic_marking->long_term_pic_num);
713 if (to_mark) {
714 to_mark->ref = false;
715 } else {
716 DVLOG(1) << "Invalid long term ref pic num to unmark";
717 return false;
718 }
719 break;
720
721 case 3:
722 // Mark a short term reference picture as long term reference.
723 pic_num_x = curr_pic_->pic_num -
724 (ref_pic_marking->difference_of_pic_nums_minus1 + 1);
725 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x);
726 if (to_mark) {
727 DCHECK(to_mark->ref && !to_mark->long_term);
728 to_mark->long_term = true;
729 to_mark->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
730 } else {
731 DVLOG(1) << "Invalid short term ref pic num to mark as long ref";
732 return false;
733 }
734 break;
735
736 case 4: {
737 // Unmark all reference pictures with long_term_frame_idx over new max.
738 max_long_term_frame_idx_ =
739 ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
740 H264Picture::Vector long_terms;
741 dpb_.GetLongTermRefPicsAppending(&long_terms);
742 for (size_t i = 0; i < long_terms.size(); ++i) {
743 scoped_refptr<H264Picture>& pic = long_terms[i];
744 DCHECK(pic->ref && pic->long_term);
745 // Ok to cast, max_long_term_frame_idx is much smaller than 16bit.
746 if (pic->long_term_frame_idx >
747 static_cast<int>(max_long_term_frame_idx_))
748 pic->ref = false;
749 }
750 break;
751 }
752
753 case 5:
754 // Unmark all reference pictures.
755 dpb_.MarkAllUnusedForRef();
756 max_long_term_frame_idx_ = -1;
757 curr_pic_->mem_mgmt_5 = true;
758 break;
759
760 case 6: {
761 // Replace long term reference pictures with current picture.
762 // First unmark if any existing with this long_term_frame_idx...
763 H264Picture::Vector long_terms;
764 dpb_.GetLongTermRefPicsAppending(&long_terms);
765 for (size_t i = 0; i < long_terms.size(); ++i) {
766 scoped_refptr<H264Picture>& pic = long_terms[i];
767 DCHECK(pic->ref && pic->long_term);
768 // Ok to cast, long_term_frame_idx is much smaller than 16bit.
769 if (pic->long_term_frame_idx ==
770 static_cast<int>(ref_pic_marking->long_term_frame_idx))
771 pic->ref = false;
772 }
773
774 // and mark the current one instead.
775 curr_pic_->ref = true;
776 curr_pic_->long_term = true;
777 curr_pic_->long_term_frame_idx = ref_pic_marking->long_term_frame_idx;
778 break;
779 }
780
781 default:
782 // Would indicate a bug in parser.
783 NOTREACHED();
784 }
785 }
786
787 return true;
788 }
789
790 // This method ensures that DPB does not overflow, either by removing
791 // reference pictures as specified in the stream, or using a sliding window
792 // procedure to remove the oldest one.
793 // It also performs marking and unmarking pictures as reference.
794 // See spac 8.2.5.1.
795 void H264Decoder::ReferencePictureMarking() {
796 if (curr_pic_->idr) {
797 // If current picture is an IDR, all reference pictures are unmarked.
798 dpb_.MarkAllUnusedForRef();
799
800 if (curr_pic_->long_term_reference_flag) {
801 curr_pic_->long_term = true;
802 curr_pic_->long_term_frame_idx = 0;
803 max_long_term_frame_idx_ = 0;
804 } else {
805 curr_pic_->long_term = false;
806 max_long_term_frame_idx_ = -1;
807 }
808 } else {
809 if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) {
810 // If non-IDR, and the stream does not indicate what we should do to
811 // ensure DPB doesn't overflow, discard oldest picture.
812 // See spec 8.2.5.3.
813 if (curr_pic_->field == H264Picture::FIELD_NONE) {
814 DCHECK_LE(
815 dpb_.CountRefPics(),
816 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames, 1));
817 if (dpb_.CountRefPics() ==
818 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
819 1)) {
820 // Max number of reference pics reached,
821 // need to remove one of the short term ones.
822 // Find smallest frame_num_wrap short reference picture and mark
823 // it as unused.
824 scoped_refptr<H264Picture> to_unmark =
825 dpb_.GetLowestFrameNumWrapShortRefPic();
826 if (to_unmark == NULL) {
827 DVLOG(1) << "Couldn't find a short ref picture to unmark";
828 return;
829 }
830 to_unmark->ref = false;
831 }
832 } else {
833 // Shouldn't get here.
834 DVLOG(1) << "Interlaced video not supported.";
835 }
836 } else {
837 // Stream has instructions how to discard pictures from DPB and how
838 // to mark/unmark existing reference pictures. Do it.
839 // Spec 8.2.5.4.
840 if (curr_pic_->field == H264Picture::FIELD_NONE) {
841 HandleMemoryManagementOps();
842 } else {
843 // Shouldn't get here.
844 DVLOG(1) << "Interlaced video not supported.";
845 }
846 }
847 }
848 }
849
850 bool H264Decoder::FinishPicture() {
851 DCHECK(curr_pic_.get());
852
853 // Finish processing previous picture.
854 // Start by storing previous reference picture data for later use,
855 // if picture being finished is a reference picture.
856 if (curr_pic_->ref) {
857 ReferencePictureMarking();
858 prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
859 prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt;
860 prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb;
861 prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb;
862 prev_ref_field_ = curr_pic_->field;
863 }
864 prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
865 prev_frame_num_offset_ = curr_pic_->frame_num_offset;
866
867 // Remove unused (for reference or later output) pictures from DPB, marking
868 // them as such.
869 dpb_.DeleteUnused();
870
871 DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size();
872
873 // Whatever happens below, curr_pic_ will stop managing the pointer to the
874 // picture after this. The ownership will either be transferred to DPB, if
875 // the image is still needed (for output and/or reference), or the memory
876 // will be released if we manage to output it here without having to store
877 // it for future reference.
878 scoped_refptr<H264Picture> pic = curr_pic_;
879 curr_pic_ = nullptr;
880
881 // Get all pictures that haven't been outputted yet.
882 H264Picture::Vector not_outputted;
883 dpb_.GetNotOutputtedPicsAppending(&not_outputted);
884 // Include the one we've just decoded.
885 not_outputted.push_back(pic);
886
887 // Sort in output order.
888 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare());
889
890 // Try to output as many pictures as we can. A picture can be output,
891 // if the number of decoded and not yet outputted pictures that would remain
892 // in DPB afterwards would at least be equal to max_num_reorder_frames.
893 // If the outputted picture is not a reference picture, it doesn't have
894 // to remain in the DPB and can be removed.
895 H264Picture::Vector::iterator output_candidate = not_outputted.begin();
896 size_t num_remaining = not_outputted.size();
897 while (num_remaining > max_num_reorder_frames_) {
898 int poc = (*output_candidate)->pic_order_cnt;
899 DCHECK_GE(poc, last_output_poc_);
900 OutputPic(*output_candidate);
901
902 if (!(*output_candidate)->ref) {
903 // Current picture hasn't been inserted into DPB yet, so don't remove it
904 // if we managed to output it immediately.
905 if ((*output_candidate)->pic_order_cnt != pic->pic_order_cnt)
906 dpb_.DeleteByPOC(poc);
907 }
908
909 ++output_candidate;
910 --num_remaining;
911 }
912
913 // If we haven't managed to output the picture that we just decoded, or if
914 // it's a reference picture, we have to store it in DPB.
915 if (!pic->outputted || pic->ref) {
916 if (dpb_.IsFull()) {
917 // If we haven't managed to output anything to free up space in DPB
918 // to store this picture, it's an error in the stream.
919 DVLOG(1) << "Could not free up space in DPB!";
920 return false;
921 }
922
923 dpb_.StorePic(pic);
924 }
925
926 return true;
927 }
928
929 static int LevelToMaxDpbMbs(int level) {
930 // See table A-1 in spec.
931 switch (level) {
932 case 10: return 396;
933 case 11: return 900;
934 case 12: // fallthrough
935 case 13: // fallthrough
936 case 20: return 2376;
937 case 21: return 4752;
938 case 22: // fallthrough
939 case 30: return 8100;
940 case 31: return 18000;
941 case 32: return 20480;
942 case 40: // fallthrough
943 case 41: return 32768;
944 case 42: return 34816;
945 case 50: return 110400;
946 case 51: // fallthrough
947 case 52: return 184320;
948 default:
949 DVLOG(1) << "Invalid codec level (" << level << ")";
950 return 0;
951 }
952 }
953
954 bool H264Decoder::UpdateMaxNumReorderFrames(const media::H264SPS* sps) {
955 if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) {
956 max_num_reorder_frames_ =
957 base::checked_cast<size_t>(sps->max_num_reorder_frames);
958 if (max_num_reorder_frames_ > dpb_.max_num_pics()) {
959 DVLOG(1)
960 << "max_num_reorder_frames present, but larger than MaxDpbFrames ("
961 << max_num_reorder_frames_ << " > " << dpb_.max_num_pics() << ")";
962 max_num_reorder_frames_ = 0;
963 return false;
964 }
965 return true;
966 }
967
968 // max_num_reorder_frames not present, infer from profile/constraints
969 // (see VUI semantics in spec).
970 if (sps->constraint_set3_flag) {
971 switch (sps->profile_idc) {
972 case 44:
973 case 86:
974 case 100:
975 case 110:
976 case 122:
977 case 244:
978 max_num_reorder_frames_ = 0;
979 break;
980 default:
981 max_num_reorder_frames_ = dpb_.max_num_pics();
982 break;
983 }
984 } else {
985 max_num_reorder_frames_ = dpb_.max_num_pics();
986 }
987
988 return true;
989 }
990
991 bool H264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) {
992 const media::H264SPS* sps = parser_.GetSPS(sps_id);
993 DCHECK(sps);
994 DVLOG(4) << "Processing SPS";
995
996 *need_new_buffers = false;
997
998 if (sps->frame_mbs_only_flag == 0) {
999 DVLOG(1) << "frame_mbs_only_flag != 1 not supported";
1000 return false;
1001 }
1002
1003 if (sps->gaps_in_frame_num_value_allowed_flag) {
1004 DVLOG(1) << "Gaps in frame numbers not supported";
1005 return false;
1006 }
1007
1008 curr_sps_id_ = sps->seq_parameter_set_id;
1009
1010 // Calculate picture height/width in macroblocks and pixels
1011 // (spec 7.4.2.1.1, 7.4.3).
1012 int width_mb = sps->pic_width_in_mbs_minus1 + 1;
1013 int height_mb = (2 - sps->frame_mbs_only_flag) *
1014 (sps->pic_height_in_map_units_minus1 + 1);
1015
1016 gfx::Size new_pic_size(16 * width_mb, 16 * height_mb);
1017 if (new_pic_size.IsEmpty()) {
1018 DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString();
1019 return false;
1020 }
1021
1022 if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) {
1023 // Already have surfaces and this SPS keeps the same resolution,
1024 // no need to request a new set.
1025 return true;
1026 }
1027
1028 pic_size_ = new_pic_size;
1029 DVLOG(1) << "New picture size: " << pic_size_.ToString();
1030
1031 max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1032 max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
1033
1034 int level = sps->level_idc;
1035 int max_dpb_mbs = LevelToMaxDpbMbs(level);
1036 if (max_dpb_mbs == 0)
1037 return false;
1038
1039 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
1040 static_cast<int>(H264DPB::kDPBMaxSize));
1041 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
1042 if (max_dpb_size == 0) {
1043 DVLOG(1) << "Invalid DPB Size";
1044 return false;
1045 }
1046
1047 dpb_.set_max_num_pics(max_dpb_size);
1048
1049 if (!UpdateMaxNumReorderFrames(sps))
1050 return false;
1051 DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_;
1052
1053 *need_new_buffers = true;
1054 return true;
1055 }
1056
1057 bool H264Decoder::ProcessPPS(int pps_id) {
1058 const media::H264PPS* pps = parser_.GetPPS(pps_id);
1059 DCHECK(pps);
1060
1061 curr_pps_id_ = pps->pic_parameter_set_id;
1062
1063 return true;
1064 }
1065
1066 bool H264Decoder::FinishPrevFrameIfPresent() {
1067 // If we already have a frame waiting to be decoded, decode it and finish.
1068 if (curr_pic_ != NULL) {
1069 if (!DecodePicture())
1070 return false;
1071 return FinishPicture();
1072 }
1073
1074 return true;
1075 }
1076
1077 bool H264Decoder::PreprocessSlice(media::H264SliceHeader* slice_hdr) {
1078 prev_frame_num_ = frame_num_;
1079 frame_num_ = slice_hdr->frame_num;
1080
1081 if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) {
1082 DVLOG(1) << "Gap in frame_num!";
1083 return false;
1084 }
1085
1086 if (slice_hdr->field_pic_flag == 0)
1087 max_pic_num_ = max_frame_num_;
1088 else
1089 max_pic_num_ = 2 * max_frame_num_;
1090
1091 // TODO posciak: switch to new picture detection per 7.4.1.2.4.
1092 if (curr_pic_ != NULL && slice_hdr->first_mb_in_slice != 0) {
1093 // More slice data of the current picture.
1094 return true;
1095 } else {
1096 // A new frame, so first finish the previous one before processing it...
1097 if (!FinishPrevFrameIfPresent())
1098 return false;
1099 }
1100
1101 // If the new frame is an IDR, output what's left to output and clear DPB
1102 if (slice_hdr->idr_pic_flag) {
1103 // (unless we are explicitly instructed not to do so).
1104 if (!slice_hdr->no_output_of_prior_pics_flag) {
1105 // Output DPB contents.
1106 if (!Flush())
1107 return false;
1108 }
1109 dpb_.Clear();
1110 last_output_poc_ = std::numeric_limits<int>::min();
1111 }
1112
1113 return true;
1114 }
1115
1116 bool H264Decoder::ProcessSlice(media::H264SliceHeader* slice_hdr) {
1117 DCHECK(curr_pic_.get());
1118 H264Picture::Vector ref_pic_list0, ref_pic_list1;
1119
1120 if (!ModifyReferencePicLists(slice_hdr, &ref_pic_list0, &ref_pic_list1))
1121 return false;
1122
1123 const media::H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id);
1124 DCHECK(pps);
1125
1126 if (!accelerator_->SubmitSlice(pps, slice_hdr, ref_pic_list0, ref_pic_list1,
1127 curr_pic_.get(), slice_hdr->nalu_data,
1128 slice_hdr->nalu_size))
1129 return false;
1130
1131 curr_slice_hdr_.reset();
1132 return true;
1133 }
1134
1135 #define SET_ERROR_AND_RETURN() \
1136 do { \
1137 DVLOG(1) << "Error during decode"; \
1138 state_ = kError; \
1139 return H264Decoder::kDecodeError; \
1140 } while (0)
1141
1142 void H264Decoder::SetStream(const uint8_t* ptr, size_t size) {
1143 DCHECK(ptr);
1144 DCHECK(size);
1145
1146 DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size;
1147 parser_.SetStream(ptr, size);
1148 }
1149
1150 H264Decoder::DecodeResult H264Decoder::Decode() {
1151 DCHECK_NE(state_, kError);
1152
1153 while (1) {
1154 media::H264Parser::Result par_res;
1155
1156 if (!curr_nalu_) {
1157 curr_nalu_.reset(new media::H264NALU());
1158 par_res = parser_.AdvanceToNextNALU(curr_nalu_.get());
1159 if (par_res == media::H264Parser::kEOStream)
1160 return kRanOutOfStreamData;
1161 else if (par_res != media::H264Parser::kOk)
1162 SET_ERROR_AND_RETURN();
1163 }
1164
1165 DVLOG(4) << "NALU found: " << static_cast<int>(curr_nalu_->nal_unit_type);
1166
1167 switch (curr_nalu_->nal_unit_type) {
1168 case media::H264NALU::kNonIDRSlice:
1169 // We can't resume from a non-IDR slice.
1170 if (state_ != kDecoding)
1171 break;
1172 // else fallthrough
1173 case media::H264NALU::kIDRSlice: {
1174 // TODO(posciak): the IDR may require an SPS that we don't have
1175 // available. For now we'd fail if that happens, but ideally we'd like
1176 // to keep going until the next SPS in the stream.
1177 if (state_ == kNeedStreamMetadata) {
1178 // We need an SPS, skip this IDR and keep looking.
1179 break;
1180 }
1181
1182 // If after reset, we should be able to recover from an IDR.
1183 if (!curr_slice_hdr_) {
1184 curr_slice_hdr_.reset(new media::H264SliceHeader());
1185 par_res =
1186 parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get());
1187 if (par_res != media::H264Parser::kOk)
1188 SET_ERROR_AND_RETURN();
1189
1190 if (!PreprocessSlice(curr_slice_hdr_.get()))
1191 SET_ERROR_AND_RETURN();
1192 }
1193
1194 if (!curr_pic_) {
1195 // New picture/finished previous one, try to start a new one
1196 // or tell the client we need more surfaces.
1197 curr_pic_ = accelerator_->CreateH264Picture();
1198 if (!curr_pic_)
1199 return kRanOutOfSurfaces;
1200
1201 if (!StartNewFrame(curr_slice_hdr_.get()))
1202 SET_ERROR_AND_RETURN();
1203 }
1204
1205 if (!ProcessSlice(curr_slice_hdr_.get()))
1206 SET_ERROR_AND_RETURN();
1207
1208 state_ = kDecoding;
1209 break;
1210 }
1211
1212 case media::H264NALU::kSPS: {
1213 int sps_id;
1214
1215 if (!FinishPrevFrameIfPresent())
1216 SET_ERROR_AND_RETURN();
1217
1218 par_res = parser_.ParseSPS(&sps_id);
1219 if (par_res != media::H264Parser::kOk)
1220 SET_ERROR_AND_RETURN();
1221
1222 bool need_new_buffers = false;
1223 if (!ProcessSPS(sps_id, &need_new_buffers))
1224 SET_ERROR_AND_RETURN();
1225
1226 state_ = kDecoding;
1227
1228 if (need_new_buffers) {
1229 if (!Flush())
1230 return kDecodeError;
1231
1232 curr_pic_ = nullptr;
1233 curr_nalu_ = nullptr;
1234 ref_pic_list_p0_.clear();
1235 ref_pic_list_b0_.clear();
1236 ref_pic_list_b1_.clear();
1237
1238 return kAllocateNewSurfaces;
1239 }
1240 break;
1241 }
1242
1243 case media::H264NALU::kPPS: {
1244 if (state_ != kDecoding)
1245 break;
1246
1247 int pps_id;
1248
1249 if (!FinishPrevFrameIfPresent())
1250 SET_ERROR_AND_RETURN();
1251
1252 par_res = parser_.ParsePPS(&pps_id);
1253 if (par_res != media::H264Parser::kOk)
1254 SET_ERROR_AND_RETURN();
1255
1256 if (!ProcessPPS(pps_id))
1257 SET_ERROR_AND_RETURN();
1258 break;
1259 }
1260
1261 default:
1262 DVLOG(4) << "Skipping NALU type: " << curr_nalu_->nal_unit_type;
1263 break;
1264 }
1265
1266 DVLOG(4) << "Dropping nalu";
1267 curr_nalu_.reset();
1268 }
1269 }
1270
1271 size_t H264Decoder::GetRequiredNumOfPictures() const {
1272 return dpb_.max_num_pics() + kPicsInPipeline;
1273 }
1274
1275 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/h264_decoder.h ('k') | content/common/gpu/media/h264_dpb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698