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

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

Issue 833063003: 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: Rebase 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <limits> 6 #include <limits>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/bind_helpers.h" 9 #include "base/bind_helpers.h"
10 #include "base/numerics/safe_conversions.h" 10 #include "base/numerics/safe_conversions.h"
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 81
82 curr_input_id_ = -1; 82 curr_input_id_ = -1;
83 frame_num_ = 0; 83 frame_num_ = 0;
84 prev_frame_num_ = -1; 84 prev_frame_num_ = -1;
85 prev_frame_num_offset_ = -1; 85 prev_frame_num_offset_ = -1;
86 86
87 prev_ref_has_memmgmnt5_ = false; 87 prev_ref_has_memmgmnt5_ = false;
88 prev_ref_top_field_order_cnt_ = -1; 88 prev_ref_top_field_order_cnt_ = -1;
89 prev_ref_pic_order_cnt_msb_ = -1; 89 prev_ref_pic_order_cnt_msb_ = -1;
90 prev_ref_pic_order_cnt_lsb_ = -1; 90 prev_ref_pic_order_cnt_lsb_ = -1;
91 prev_ref_field_ = H264Picture::FIELD_NONE; 91 prev_ref_field_ = VaapiH264Picture::FIELD_NONE;
92 92
93 vaapi_wrapper_->DestroyPendingBuffers(); 93 vaapi_wrapper_->DestroyPendingBuffers();
94 94
95 ref_pic_list0_.clear(); 95 ref_pic_list0_.clear();
96 ref_pic_list1_.clear(); 96 ref_pic_list1_.clear();
97 97
98 for (DecSurfacesInUse::iterator it = decode_surfaces_in_use_.begin(); 98 for (DecSurfacesInUse::iterator it = decode_surfaces_in_use_.begin();
99 it != decode_surfaces_in_use_.end(); ) { 99 it != decode_surfaces_in_use_.end(); ) {
100 int poc = it->second->poc(); 100 int poc = it->second->poc();
101 // Must be incremented before UnassignSurfaceFromPoC as this call 101 // Must be incremented before UnassignSurfaceFromPoC as this call
(...skipping 17 matching lines...) Expand all
119 available_va_surfaces_.push_back(va_surface); 119 available_va_surfaces_.push_back(va_surface);
120 } 120 }
121 121
122 // Fill |va_pic| with default/neutral values. 122 // Fill |va_pic| with default/neutral values.
123 static void InitVAPicture(VAPictureH264* va_pic) { 123 static void InitVAPicture(VAPictureH264* va_pic) {
124 memset(va_pic, 0, sizeof(*va_pic)); 124 memset(va_pic, 0, sizeof(*va_pic));
125 va_pic->picture_id = VA_INVALID_ID; 125 va_pic->picture_id = VA_INVALID_ID;
126 va_pic->flags = VA_PICTURE_H264_INVALID; 126 va_pic->flags = VA_PICTURE_H264_INVALID;
127 } 127 }
128 128
129 void VaapiH264Decoder::FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic) { 129 void VaapiH264Decoder::FillVAPicture(VAPictureH264* va_pic,
130 VaapiH264Picture* pic) {
130 DCHECK(pic); 131 DCHECK(pic);
131 132
132 DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt); 133 DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
133 if (!dec_surface) { 134 if (!dec_surface) {
134 // Cannot provide a ref picture, will corrupt output, but may be able 135 // Cannot provide a ref picture, will corrupt output, but may be able
135 // to recover. 136 // to recover.
136 InitVAPicture(va_pic); 137 InitVAPicture(va_pic);
137 return; 138 return;
138 } 139 }
139 140
140 va_pic->picture_id = dec_surface->va_surface()->id(); 141 va_pic->picture_id = dec_surface->va_surface()->id();
141 va_pic->frame_idx = pic->frame_num; 142 va_pic->frame_idx = pic->frame_num;
142 va_pic->flags = 0; 143 va_pic->flags = 0;
143 144
144 switch (pic->field) { 145 switch (pic->field) {
145 case H264Picture::FIELD_NONE: 146 case VaapiH264Picture::FIELD_NONE:
146 break; 147 break;
147 case H264Picture::FIELD_TOP: 148 case VaapiH264Picture::FIELD_TOP:
148 va_pic->flags |= VA_PICTURE_H264_TOP_FIELD; 149 va_pic->flags |= VA_PICTURE_H264_TOP_FIELD;
149 break; 150 break;
150 case H264Picture::FIELD_BOTTOM: 151 case VaapiH264Picture::FIELD_BOTTOM:
151 va_pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD; 152 va_pic->flags |= VA_PICTURE_H264_BOTTOM_FIELD;
152 break; 153 break;
153 } 154 }
154 155
155 if (pic->ref) { 156 if (pic->ref) {
156 va_pic->flags |= pic->long_term ? VA_PICTURE_H264_LONG_TERM_REFERENCE 157 va_pic->flags |= pic->long_term ? VA_PICTURE_H264_LONG_TERM_REFERENCE
157 : VA_PICTURE_H264_SHORT_TERM_REFERENCE; 158 : VA_PICTURE_H264_SHORT_TERM_REFERENCE;
158 } 159 }
159 160
160 va_pic->TopFieldOrderCnt = pic->top_field_order_cnt; 161 va_pic->TopFieldOrderCnt = pic->top_field_order_cnt;
161 va_pic->BottomFieldOrderCnt = pic->bottom_field_order_cnt; 162 va_pic->BottomFieldOrderCnt = pic->bottom_field_order_cnt;
162 } 163 }
163 164
164 int VaapiH264Decoder::FillVARefFramesFromDPB(VAPictureH264 *va_pics, 165 int VaapiH264Decoder::FillVARefFramesFromDPB(VAPictureH264 *va_pics,
165 int num_pics) { 166 int num_pics) {
166 H264DPB::Pictures::reverse_iterator rit; 167 VaapiH264DPB::Pictures::reverse_iterator rit;
167 int i; 168 int i;
168 169
169 // Return reference frames in reverse order of insertion. 170 // Return reference frames in reverse order of insertion.
170 // Libva does not document this, but other implementations (e.g. mplayer) 171 // Libva does not document this, but other implementations (e.g. mplayer)
171 // do it this way as well. 172 // do it this way as well.
172 for (rit = dpb_.rbegin(), i = 0; rit != dpb_.rend() && i < num_pics; ++rit) { 173 for (rit = dpb_.rbegin(), i = 0; rit != dpb_.rend() && i < num_pics; ++rit) {
173 if ((*rit)->ref) 174 if ((*rit)->ref)
174 FillVAPicture(&va_pics[i++], *rit); 175 FillVAPicture(&va_pics[i++], *rit);
175 } 176 }
176 177
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 } 416 }
416 } 417 }
417 } 418 }
418 419
419 for (int i = 0; i < 32; ++i) { 420 for (int i = 0; i < 32; ++i) {
420 InitVAPicture(&slice_param.RefPicList0[i]); 421 InitVAPicture(&slice_param.RefPicList0[i]);
421 InitVAPicture(&slice_param.RefPicList1[i]); 422 InitVAPicture(&slice_param.RefPicList1[i]);
422 } 423 }
423 424
424 int i; 425 int i;
425 H264Picture::PtrVector::iterator it; 426 VaapiH264Picture::PtrVector::iterator it;
426 for (it = ref_pic_list0_.begin(), i = 0; it != ref_pic_list0_.end() && *it; 427 for (it = ref_pic_list0_.begin(), i = 0; it != ref_pic_list0_.end() && *it;
427 ++it, ++i) 428 ++it, ++i)
428 FillVAPicture(&slice_param.RefPicList0[i], *it); 429 FillVAPicture(&slice_param.RefPicList0[i], *it);
429 for (it = ref_pic_list1_.begin(), i = 0; it != ref_pic_list1_.end() && *it; 430 for (it = ref_pic_list1_.begin(), i = 0; it != ref_pic_list1_.end() && *it;
430 ++it, ++i) 431 ++it, ++i)
431 FillVAPicture(&slice_param.RefPicList1[i], *it); 432 FillVAPicture(&slice_param.RefPicList1[i], *it);
432 433
433 return vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType, 434 return vaapi_wrapper_->SubmitBuffer(VASliceParameterBufferType,
434 sizeof(VASliceParameterBufferH264), 435 sizeof(VASliceParameterBufferH264),
435 &slice_param); 436 &slice_param);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 DVLOG(1) << "Failed decoding picture"; 494 DVLOG(1) << "Failed decoding picture";
494 return false; 495 return false;
495 } 496 }
496 497
497 return true; 498 return true;
498 } 499 }
499 500
500 bool VaapiH264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) { 501 bool VaapiH264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) {
501 DCHECK(curr_pic_.get()); 502 DCHECK(curr_pic_.get());
502 503
503 memset(curr_pic_.get(), 0, sizeof(H264Picture)); 504 memset(curr_pic_.get(), 0, sizeof(VaapiH264Picture));
504 505
505 curr_pic_->idr = slice_hdr->idr_pic_flag; 506 curr_pic_->idr = slice_hdr->idr_pic_flag;
506 507
507 if (slice_hdr->field_pic_flag) { 508 if (slice_hdr->field_pic_flag) {
508 curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM 509 curr_pic_->field = slice_hdr->bottom_field_flag
509 : H264Picture::FIELD_TOP; 510 ? VaapiH264Picture::FIELD_BOTTOM
511 : VaapiH264Picture::FIELD_TOP;
510 } else { 512 } else {
511 curr_pic_->field = H264Picture::FIELD_NONE; 513 curr_pic_->field = VaapiH264Picture::FIELD_NONE;
512 } 514 }
513 515
514 curr_pic_->ref = slice_hdr->nal_ref_idc != 0; 516 curr_pic_->ref = slice_hdr->nal_ref_idc != 0;
515 // This assumes non-interlaced stream. 517 // This assumes non-interlaced stream.
516 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num; 518 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num;
517 519
518 if (!CalculatePicOrderCounts(slice_hdr)) 520 if (!CalculatePicOrderCounts(slice_hdr))
519 return false; 521 return false;
520 522
521 // Try to get an empty surface to decode this picture to. 523 // Try to get an empty surface to decode this picture to.
(...skipping 29 matching lines...) Expand all
551 curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb; 553 curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb;
552 554
553 switch (sps->pic_order_cnt_type) { 555 switch (sps->pic_order_cnt_type) {
554 case 0: 556 case 0:
555 // See spec 8.2.1.1. 557 // See spec 8.2.1.1.
556 int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb; 558 int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb;
557 if (slice_hdr->idr_pic_flag) { 559 if (slice_hdr->idr_pic_flag) {
558 prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0; 560 prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0;
559 } else { 561 } else {
560 if (prev_ref_has_memmgmnt5_) { 562 if (prev_ref_has_memmgmnt5_) {
561 if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) { 563 if (prev_ref_field_ != VaapiH264Picture::FIELD_BOTTOM) {
562 prev_pic_order_cnt_msb = 0; 564 prev_pic_order_cnt_msb = 0;
563 prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_; 565 prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_;
564 } else { 566 } else {
565 prev_pic_order_cnt_msb = 0; 567 prev_pic_order_cnt_msb = 0;
566 prev_pic_order_cnt_lsb = 0; 568 prev_pic_order_cnt_lsb = 0;
567 } 569 }
568 } else { 570 } else {
569 prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_; 571 prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_;
570 prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_; 572 prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_;
571 } 573 }
572 } 574 }
573 575
574 DCHECK_NE(max_pic_order_cnt_lsb_, 0); 576 DCHECK_NE(max_pic_order_cnt_lsb_, 0);
575 if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) && 577 if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) &&
576 (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >= 578 (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >=
577 max_pic_order_cnt_lsb_ / 2)) { 579 max_pic_order_cnt_lsb_ / 2)) {
578 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb + 580 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb +
579 max_pic_order_cnt_lsb_; 581 max_pic_order_cnt_lsb_;
580 } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) && 582 } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) &&
581 (pic_order_cnt_lsb - prev_pic_order_cnt_lsb > 583 (pic_order_cnt_lsb - prev_pic_order_cnt_lsb >
582 max_pic_order_cnt_lsb_ / 2)) { 584 max_pic_order_cnt_lsb_ / 2)) {
583 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb - 585 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb -
584 max_pic_order_cnt_lsb_; 586 max_pic_order_cnt_lsb_;
585 } else { 587 } else {
586 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb; 588 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb;
587 } 589 }
588 590
589 if (curr_pic_->field != H264Picture::FIELD_BOTTOM) { 591 if (curr_pic_->field != VaapiH264Picture::FIELD_BOTTOM) {
590 curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb + 592 curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb +
591 pic_order_cnt_lsb; 593 pic_order_cnt_lsb;
592 } 594 }
593 595
594 if (curr_pic_->field != H264Picture::FIELD_TOP) { 596 if (curr_pic_->field != VaapiH264Picture::FIELD_TOP) {
595 // TODO posciak: perhaps replace with pic->field? 597 // TODO posciak: perhaps replace with pic->field?
596 if (!slice_hdr->field_pic_flag) { 598 if (!slice_hdr->field_pic_flag) {
597 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt + 599 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
598 slice_hdr->delta_pic_order_cnt_bottom; 600 slice_hdr->delta_pic_order_cnt_bottom;
599 } else { 601 } else {
600 curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb + 602 curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb +
601 pic_order_cnt_lsb; 603 pic_order_cnt_lsb;
602 } 604 }
603 } 605 }
604 break; 606 break;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser 644 // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser
643 for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i) 645 for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i)
644 expected_pic_order_cnt += sps->offset_for_ref_frame[i]; 646 expected_pic_order_cnt += sps->offset_for_ref_frame[i];
645 } 647 }
646 648
647 if (!slice_hdr->nal_ref_idc) 649 if (!slice_hdr->nal_ref_idc)
648 expected_pic_order_cnt += sps->offset_for_non_ref_pic; 650 expected_pic_order_cnt += sps->offset_for_non_ref_pic;
649 651
650 if (!slice_hdr->field_pic_flag) { 652 if (!slice_hdr->field_pic_flag) {
651 curr_pic_->top_field_order_cnt = expected_pic_order_cnt + 653 curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
652 slice_hdr->delta_pic_order_cnt[0]; 654 slice_hdr->delta_pic_order_cnt0;
653 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt + 655 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt +
654 sps->offset_for_top_to_bottom_field + 656 sps->offset_for_top_to_bottom_field +
655 slice_hdr->delta_pic_order_cnt[1]; 657 slice_hdr->delta_pic_order_cnt1;
656 } else if (!slice_hdr->bottom_field_flag) { 658 } else if (!slice_hdr->bottom_field_flag) {
657 curr_pic_->top_field_order_cnt = expected_pic_order_cnt + 659 curr_pic_->top_field_order_cnt = expected_pic_order_cnt +
658 slice_hdr->delta_pic_order_cnt[0]; 660 slice_hdr->delta_pic_order_cnt0;
659 } else { 661 } else {
660 curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt + 662 curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt +
661 sps->offset_for_top_to_bottom_field + 663 sps->offset_for_top_to_bottom_field +
662 slice_hdr->delta_pic_order_cnt[0]; 664 slice_hdr->delta_pic_order_cnt0;
663 } 665 }
664 break; 666 break;
665 } 667 }
666 668
667 case 2: 669 case 2:
668 // See spec 8.2.1.3. 670 // See spec 8.2.1.3.
669 if (prev_has_memmgmnt5_) 671 if (prev_has_memmgmnt5_)
670 prev_frame_num_offset_ = 0; 672 prev_frame_num_offset_ = 0;
671 673
672 if (slice_hdr->idr_pic_flag) 674 if (slice_hdr->idr_pic_flag)
(...skipping 23 matching lines...) Expand all
696 curr_pic_->top_field_order_cnt = temp_pic_order_cnt; 698 curr_pic_->top_field_order_cnt = temp_pic_order_cnt;
697 } 699 }
698 break; 700 break;
699 701
700 default: 702 default:
701 DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type; 703 DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type;
702 return false; 704 return false;
703 } 705 }
704 706
705 switch (curr_pic_->field) { 707 switch (curr_pic_->field) {
706 case H264Picture::FIELD_NONE: 708 case VaapiH264Picture::FIELD_NONE:
707 curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt, 709 curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt,
708 curr_pic_->bottom_field_order_cnt); 710 curr_pic_->bottom_field_order_cnt);
709 break; 711 break;
710 case H264Picture::FIELD_TOP: 712 case VaapiH264Picture::FIELD_TOP:
711 curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt; 713 curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt;
712 break; 714 break;
713 case H264Picture::FIELD_BOTTOM: 715 case VaapiH264Picture::FIELD_BOTTOM:
714 curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt; 716 curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt;
715 break; 717 break;
716 } 718 }
717 719
718 return true; 720 return true;
719 } 721 }
720 722
721 void VaapiH264Decoder::UpdatePicNums() { 723 void VaapiH264Decoder::UpdatePicNums() {
722 for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) { 724 for (VaapiH264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end();
723 H264Picture* pic = *it; 725 ++it) {
726 VaapiH264Picture* pic = *it;
724 DCHECK(pic); 727 DCHECK(pic);
725 if (!pic->ref) 728 if (!pic->ref)
726 continue; 729 continue;
727 730
728 // Below assumes non-interlaced stream. 731 // Below assumes non-interlaced stream.
729 DCHECK_EQ(pic->field, H264Picture::FIELD_NONE); 732 DCHECK_EQ(pic->field, VaapiH264Picture::FIELD_NONE);
730 if (pic->long_term) { 733 if (pic->long_term) {
731 pic->long_term_pic_num = pic->long_term_frame_idx; 734 pic->long_term_pic_num = pic->long_term_frame_idx;
732 } else { 735 } else {
733 if (pic->frame_num > frame_num_) 736 if (pic->frame_num > frame_num_)
734 pic->frame_num_wrap = pic->frame_num - max_frame_num_; 737 pic->frame_num_wrap = pic->frame_num - max_frame_num_;
735 else 738 else
736 pic->frame_num_wrap = pic->frame_num; 739 pic->frame_num_wrap = pic->frame_num;
737 740
738 pic->pic_num = pic->frame_num_wrap; 741 pic->pic_num = pic->frame_num_wrap;
739 } 742 }
740 } 743 }
741 } 744 }
742 745
743 struct PicNumDescCompare { 746 struct PicNumDescCompare {
744 bool operator()(const H264Picture* a, const H264Picture* b) const { 747 bool operator()(const VaapiH264Picture* a, const VaapiH264Picture* b) const {
745 return a->pic_num > b->pic_num; 748 return a->pic_num > b->pic_num;
746 } 749 }
747 }; 750 };
748 751
749 struct LongTermPicNumAscCompare { 752 struct LongTermPicNumAscCompare {
750 bool operator()(const H264Picture* a, const H264Picture* b) const { 753 bool operator()(const VaapiH264Picture* a, const VaapiH264Picture* b) const {
751 return a->long_term_pic_num < b->long_term_pic_num; 754 return a->long_term_pic_num < b->long_term_pic_num;
752 } 755 }
753 }; 756 };
754 757
755 void VaapiH264Decoder::ConstructReferencePicListsP( 758 void VaapiH264Decoder::ConstructReferencePicListsP(
756 media::H264SliceHeader* slice_hdr) { 759 media::H264SliceHeader* slice_hdr) {
757 // RefPicList0 (8.2.4.2.1) [[1] [2]], where: 760 // RefPicList0 (8.2.4.2.1) [[1] [2]], where:
758 // [1] shortterm ref pics sorted by descending pic_num, 761 // [1] shortterm ref pics sorted by descending pic_num,
759 // [2] longterm ref pics by ascending long_term_pic_num. 762 // [2] longterm ref pics by ascending long_term_pic_num.
760 DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty()); 763 DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
761 // First get the short ref pics... 764 // First get the short ref pics...
762 dpb_.GetShortTermRefPicsAppending(ref_pic_list0_); 765 dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
763 size_t num_short_refs = ref_pic_list0_.size(); 766 size_t num_short_refs = ref_pic_list0_.size();
764 767
765 // and sort them to get [1]. 768 // and sort them to get [1].
766 std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), PicNumDescCompare()); 769 std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), PicNumDescCompare());
767 770
768 // Now get long term pics and sort them by long_term_pic_num to get [2]. 771 // Now get long term pics and sort them by long_term_pic_num to get [2].
769 dpb_.GetLongTermRefPicsAppending(ref_pic_list0_); 772 dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
770 std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(), 773 std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
771 LongTermPicNumAscCompare()); 774 LongTermPicNumAscCompare());
772 775
773 // Cut off if we have more than requested in slice header. 776 // Cut off if we have more than requested in slice header.
774 ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1); 777 ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
775 } 778 }
776 779
777 struct POCAscCompare { 780 struct POCAscCompare {
778 bool operator()(const H264Picture* a, const H264Picture* b) const { 781 bool operator()(const VaapiH264Picture* a, const VaapiH264Picture* b) const {
779 return a->pic_order_cnt < b->pic_order_cnt; 782 return a->pic_order_cnt < b->pic_order_cnt;
780 } 783 }
781 }; 784 };
782 785
783 struct POCDescCompare { 786 struct POCDescCompare {
784 bool operator()(const H264Picture* a, const H264Picture* b) const { 787 bool operator()(const VaapiH264Picture* a, const VaapiH264Picture* b) const {
785 return a->pic_order_cnt > b->pic_order_cnt; 788 return a->pic_order_cnt > b->pic_order_cnt;
786 } 789 }
787 }; 790 };
788 791
789 void VaapiH264Decoder::ConstructReferencePicListsB( 792 void VaapiH264Decoder::ConstructReferencePicListsB(
790 media::H264SliceHeader* slice_hdr) { 793 media::H264SliceHeader* slice_hdr) {
791 // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where: 794 // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where:
792 // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC, 795 // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC,
793 // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC, 796 // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC,
794 // [3] longterm ref pics by ascending long_term_pic_num. 797 // [3] longterm ref pics by ascending long_term_pic_num.
795 DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty()); 798 DCHECK(ref_pic_list0_.empty() && ref_pic_list1_.empty());
796 dpb_.GetShortTermRefPicsAppending(ref_pic_list0_); 799 dpb_.GetShortTermRefPicsAppending(ref_pic_list0_);
797 size_t num_short_refs = ref_pic_list0_.size(); 800 size_t num_short_refs = ref_pic_list0_.size();
798 801
799 // First sort ascending, this will put [1] in right place and finish [2]. 802 // First sort ascending, this will put [1] in right place and finish [2].
800 std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), POCAscCompare()); 803 std::sort(ref_pic_list0_.begin(), ref_pic_list0_.end(), POCAscCompare());
801 804
802 // Find first with POC > curr_pic's POC to get first element in [2]... 805 // Find first with POC > curr_pic's POC to get first element in [2]...
803 H264Picture::PtrVector::iterator iter; 806 VaapiH264Picture::PtrVector::iterator iter;
804 iter = std::upper_bound(ref_pic_list0_.begin(), ref_pic_list0_.end(), 807 iter = std::upper_bound(ref_pic_list0_.begin(), ref_pic_list0_.end(),
805 curr_pic_.get(), POCAscCompare()); 808 curr_pic_.get(), POCAscCompare());
806 809
807 // and sort [1] descending, thus finishing sequence [1] [2]. 810 // and sort [1] descending, thus finishing sequence [1] [2].
808 std::sort(ref_pic_list0_.begin(), iter, POCDescCompare()); 811 std::sort(ref_pic_list0_.begin(), iter, POCDescCompare());
809 812
810 // Now add [3] and sort by ascending long_term_pic_num. 813 // Now add [3] and sort by ascending long_term_pic_num.
811 dpb_.GetLongTermRefPicsAppending(ref_pic_list0_); 814 dpb_.GetLongTermRefPicsAppending(ref_pic_list0_);
812 std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(), 815 std::sort(ref_pic_list0_.begin() + num_short_refs, ref_pic_list0_.end(),
813 LongTermPicNumAscCompare()); 816 LongTermPicNumAscCompare());
(...skipping 28 matching lines...) Expand all
842 std::swap(ref_pic_list1_[0], ref_pic_list1_[1]); 845 std::swap(ref_pic_list1_[0], ref_pic_list1_[1]);
843 846
844 // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate 847 // Per 8.2.4.2 it's possible for num_ref_idx_lX_active_minus1 to indicate
845 // there should be more ref pics on list than we constructed. 848 // there should be more ref pics on list than we constructed.
846 // Those superfluous ones should be treated as non-reference. 849 // Those superfluous ones should be treated as non-reference.
847 ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1); 850 ref_pic_list0_.resize(slice_hdr->num_ref_idx_l0_active_minus1 + 1);
848 ref_pic_list1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1); 851 ref_pic_list1_.resize(slice_hdr->num_ref_idx_l1_active_minus1 + 1);
849 } 852 }
850 853
851 // See 8.2.4 854 // See 8.2.4
852 int VaapiH264Decoder::PicNumF(H264Picture *pic) { 855 int VaapiH264Decoder::PicNumF(VaapiH264Picture* pic) {
853 if (!pic) 856 if (!pic)
854 return -1; 857 return -1;
855 858
856 if (!pic->long_term) 859 if (!pic->long_term)
857 return pic->pic_num; 860 return pic->pic_num;
858 else 861 else
859 return max_pic_num_; 862 return max_pic_num_;
860 } 863 }
861 864
862 // See 8.2.4 865 // See 8.2.4
863 int VaapiH264Decoder::LongTermPicNumF(H264Picture *pic) { 866 int VaapiH264Decoder::LongTermPicNumF(VaapiH264Picture* pic) {
864 if (pic->ref && pic->long_term) 867 if (pic->ref && pic->long_term)
865 return pic->long_term_pic_num; 868 return pic->long_term_pic_num;
866 else 869 else
867 return 2 * (max_long_term_frame_idx_ + 1); 870 return 2 * (max_long_term_frame_idx_ + 1);
868 } 871 }
869 872
870 // Shift elements on the |v| starting from |from| to |to|, inclusive, 873 // Shift elements on the |v| starting from |from| to |to|, inclusive,
871 // one position to the right and insert pic at |from|. 874 // one position to the right and insert pic at |from|.
872 static void ShiftRightAndInsert(H264Picture::PtrVector *v, 875 static void ShiftRightAndInsert(VaapiH264Picture::PtrVector* v,
873 int from, 876 int from,
874 int to, 877 int to,
875 H264Picture* pic) { 878 VaapiH264Picture* pic) {
876 // Security checks, do not disable in Debug mode. 879 // Security checks, do not disable in Debug mode.
877 CHECK(from <= to); 880 CHECK(from <= to);
878 CHECK(to <= std::numeric_limits<int>::max() - 2); 881 CHECK(to <= std::numeric_limits<int>::max() - 2);
879 // Additional checks. Debug mode ok. 882 // Additional checks. Debug mode ok.
880 DCHECK(v); 883 DCHECK(v);
881 DCHECK(pic); 884 DCHECK(pic);
882 DCHECK((to + 1 == static_cast<int>(v->size())) || 885 DCHECK((to + 1 == static_cast<int>(v->size())) ||
883 (to + 2 == static_cast<int>(v->size()))); 886 (to + 2 == static_cast<int>(v->size())));
884 887
885 v->resize(to + 2); 888 v->resize(to + 2);
886 889
887 for (int i = to + 1; i > from; --i) 890 for (int i = to + 1; i > from; --i)
888 (*v)[i] = (*v)[i - 1]; 891 (*v)[i] = (*v)[i - 1];
889 892
890 (*v)[from] = pic; 893 (*v)[from] = pic;
891 } 894 }
892 895
893 bool VaapiH264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr, 896 bool VaapiH264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr,
894 int list) { 897 int list) {
895 int num_ref_idx_lX_active_minus1; 898 int num_ref_idx_lX_active_minus1;
896 H264Picture::PtrVector* ref_pic_listx; 899 VaapiH264Picture::PtrVector* ref_pic_listx;
897 media::H264ModificationOfPicNum* list_mod; 900 media::H264ModificationOfPicNum* list_mod;
898 901
899 // This can process either ref_pic_list0 or ref_pic_list1, depending on 902 // This can process either ref_pic_list0 or ref_pic_list1, depending on
900 // the list argument. Set up pointers to proper list to be processed here. 903 // the list argument. Set up pointers to proper list to be processed here.
901 if (list == 0) { 904 if (list == 0) {
902 if (!slice_hdr->ref_pic_list_modification_flag_l0) 905 if (!slice_hdr->ref_pic_list_modification_flag_l0)
903 return true; 906 return true;
904 907
905 list_mod = slice_hdr->ref_list_l0_modifications; 908 list_mod = slice_hdr->ref_list_l0_modifications;
906 num_ref_idx_lX_active_minus1 = ref_pic_list0_.size() - 1; 909 num_ref_idx_lX_active_minus1 = ref_pic_list0_.size() - 1;
(...skipping 11 matching lines...) Expand all
918 921
919 DCHECK_GE(num_ref_idx_lX_active_minus1, 0); 922 DCHECK_GE(num_ref_idx_lX_active_minus1, 0);
920 923
921 // Spec 8.2.4.3: 924 // Spec 8.2.4.3:
922 // Reorder pictures on the list in a way specified in the stream. 925 // Reorder pictures on the list in a way specified in the stream.
923 int pic_num_lx_pred = curr_pic_->pic_num; 926 int pic_num_lx_pred = curr_pic_->pic_num;
924 int ref_idx_lx = 0; 927 int ref_idx_lx = 0;
925 int pic_num_lx_no_wrap; 928 int pic_num_lx_no_wrap;
926 int pic_num_lx; 929 int pic_num_lx;
927 bool done = false; 930 bool done = false;
928 H264Picture* pic; 931 VaapiH264Picture* pic;
929 for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) { 932 for (int i = 0; i < media::H264SliceHeader::kRefListModSize && !done; ++i) {
930 switch (list_mod->modification_of_pic_nums_idc) { 933 switch (list_mod->modification_of_pic_nums_idc) {
931 case 0: 934 case 0:
932 case 1: 935 case 1:
933 // Modify short reference picture position. 936 // Modify short reference picture position.
934 if (list_mod->modification_of_pic_nums_idc == 0) { 937 if (list_mod->modification_of_pic_nums_idc == 0) {
935 // Subtract given value from predicted PicNum. 938 // Subtract given value from predicted PicNum.
936 pic_num_lx_no_wrap = pic_num_lx_pred - 939 pic_num_lx_no_wrap = pic_num_lx_pred -
937 (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1); 940 (static_cast<int>(list_mod->abs_diff_pic_num_minus1) + 1);
938 // Wrap around max_pic_num_ if it becomes < 0 as result 941 // Wrap around max_pic_num_ if it becomes < 0 as result
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 } 1017 }
1015 1018
1016 // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is 1019 // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is
1017 // temporarily made one element longer than the required final list. 1020 // temporarily made one element longer than the required final list.
1018 // Resize the list back to its required size. 1021 // Resize the list back to its required size.
1019 ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1); 1022 ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1);
1020 1023
1021 return true; 1024 return true;
1022 } 1025 }
1023 1026
1024 bool VaapiH264Decoder::OutputPic(H264Picture* pic) { 1027 bool VaapiH264Decoder::OutputPic(VaapiH264Picture* pic) {
1025 DCHECK(!pic->outputted); 1028 DCHECK(!pic->outputted);
1026 pic->outputted = true; 1029 pic->outputted = true;
1027 last_output_poc_ = pic->pic_order_cnt; 1030 last_output_poc_ = pic->pic_order_cnt;
1028 1031
1029 DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt); 1032 DecodeSurface* dec_surface = DecodeSurfaceByPoC(pic->pic_order_cnt);
1030 if (!dec_surface) 1033 if (!dec_surface)
1031 return false; 1034 return false;
1032 1035
1033 DCHECK_GE(dec_surface->input_id(), 0); 1036 DCHECK_GE(dec_surface->input_id(), 0);
1034 DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt 1037 DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt
1035 << " input_id: " << dec_surface->input_id(); 1038 << " input_id: " << dec_surface->input_id();
1036 output_pic_cb_.Run(dec_surface->input_id(), dec_surface->va_surface()); 1039 output_pic_cb_.Run(dec_surface->input_id(), dec_surface->va_surface());
1037 1040
1038 return true; 1041 return true;
1039 } 1042 }
1040 1043
1041 void VaapiH264Decoder::ClearDPB() { 1044 void VaapiH264Decoder::ClearDPB() {
1042 // Clear DPB contents, marking the pictures as unused first. 1045 // Clear DPB contents, marking the pictures as unused first.
1043 for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) 1046 for (VaapiH264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end();
1047 ++it)
1044 UnassignSurfaceFromPoC((*it)->pic_order_cnt); 1048 UnassignSurfaceFromPoC((*it)->pic_order_cnt);
1045 1049
1046 dpb_.Clear(); 1050 dpb_.Clear();
1047 last_output_poc_ = std::numeric_limits<int>::min(); 1051 last_output_poc_ = std::numeric_limits<int>::min();
1048 } 1052 }
1049 1053
1050 bool VaapiH264Decoder::OutputAllRemainingPics() { 1054 bool VaapiH264Decoder::OutputAllRemainingPics() {
1051 // Output all pictures that are waiting to be outputted. 1055 // Output all pictures that are waiting to be outputted.
1052 FinishPrevFrameIfPresent(); 1056 FinishPrevFrameIfPresent();
1053 H264Picture::PtrVector to_output; 1057 VaapiH264Picture::PtrVector to_output;
1054 dpb_.GetNotOutputtedPicsAppending(to_output); 1058 dpb_.GetNotOutputtedPicsAppending(to_output);
1055 // Sort them by ascending POC to output in order. 1059 // Sort them by ascending POC to output in order.
1056 std::sort(to_output.begin(), to_output.end(), POCAscCompare()); 1060 std::sort(to_output.begin(), to_output.end(), POCAscCompare());
1057 1061
1058 H264Picture::PtrVector::iterator it; 1062 VaapiH264Picture::PtrVector::iterator it;
1059 for (it = to_output.begin(); it != to_output.end(); ++it) { 1063 for (it = to_output.begin(); it != to_output.end(); ++it) {
1060 if (!OutputPic(*it)) { 1064 if (!OutputPic(*it)) {
1061 DVLOG(1) << "Failed to output pic POC: " << (*it)->pic_order_cnt; 1065 DVLOG(1) << "Failed to output pic POC: " << (*it)->pic_order_cnt;
1062 return false; 1066 return false;
1063 } 1067 }
1064 } 1068 }
1065 1069
1066 return true; 1070 return true;
1067 } 1071 }
1068 1072
(...skipping 21 matching lines...) Expand all
1090 return false; 1094 return false;
1091 } 1095 }
1092 dpb_.Clear(); 1096 dpb_.Clear();
1093 last_output_poc_ = std::numeric_limits<int>::min(); 1097 last_output_poc_ = std::numeric_limits<int>::min();
1094 } 1098 }
1095 1099
1096 // curr_pic_ should have either been added to DPB or discarded when finishing 1100 // curr_pic_ should have either been added to DPB or discarded when finishing
1097 // the last frame. DPB is responsible for releasing that memory once it's 1101 // the last frame. DPB is responsible for releasing that memory once it's
1098 // not needed anymore. 1102 // not needed anymore.
1099 DCHECK(!curr_pic_.get()); 1103 DCHECK(!curr_pic_.get());
1100 curr_pic_.reset(new H264Picture); 1104 curr_pic_.reset(new VaapiH264Picture);
1101 CHECK(curr_pic_.get()); 1105 CHECK(curr_pic_.get());
1102 1106
1103 if (!InitCurrPicture(slice_hdr)) 1107 if (!InitCurrPicture(slice_hdr))
1104 return false; 1108 return false;
1105 1109
1106 DCHECK_GT(max_frame_num_, 0); 1110 DCHECK_GT(max_frame_num_, 0);
1107 1111
1108 UpdatePicNums(); 1112 UpdatePicNums();
1109 1113
1110 // Send parameter buffers before each new picture, before the first slice. 1114 // Send parameter buffers before each new picture, before the first slice.
1111 if (!SendPPS()) 1115 if (!SendPPS())
1112 return false; 1116 return false;
1113 1117
1114 if (!SendIQMatrix()) 1118 if (!SendIQMatrix())
1115 return false; 1119 return false;
1116 1120
1117 if (!QueueSlice(slice_hdr)) 1121 if (!QueueSlice(slice_hdr))
1118 return false; 1122 return false;
1119 1123
1120 return true; 1124 return true;
1121 } 1125 }
1122 1126
1123 bool VaapiH264Decoder::HandleMemoryManagementOps() { 1127 bool VaapiH264Decoder::HandleMemoryManagementOps() {
1124 // 8.2.5.4 1128 // 8.2.5.4
1125 for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) { 1129 for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) {
1126 // Code below does not support interlaced stream (per-field pictures). 1130 // Code below does not support interlaced stream (per-field pictures).
1127 media::H264DecRefPicMarking* ref_pic_marking = 1131 media::H264DecRefPicMarking* ref_pic_marking =
1128 &curr_pic_->ref_pic_marking[i]; 1132 &curr_pic_->ref_pic_marking[i];
1129 H264Picture* to_mark; 1133 VaapiH264Picture* to_mark;
1130 int pic_num_x; 1134 int pic_num_x;
1131 1135
1132 switch (ref_pic_marking->memory_mgmnt_control_operation) { 1136 switch (ref_pic_marking->memory_mgmnt_control_operation) {
1133 case 0: 1137 case 0:
1134 // Normal end of operations' specification. 1138 // Normal end of operations' specification.
1135 return true; 1139 return true;
1136 1140
1137 case 1: 1141 case 1:
1138 // Mark a short term reference picture as unused so it can be removed 1142 // Mark a short term reference picture as unused so it can be removed
1139 // if outputted. 1143 // if outputted.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 } else { 1177 } else {
1174 DVLOG(1) << "Invalid short term ref pic num to mark as long ref"; 1178 DVLOG(1) << "Invalid short term ref pic num to mark as long ref";
1175 return false; 1179 return false;
1176 } 1180 }
1177 break; 1181 break;
1178 1182
1179 case 4: { 1183 case 4: {
1180 // Unmark all reference pictures with long_term_frame_idx over new max. 1184 // Unmark all reference pictures with long_term_frame_idx over new max.
1181 max_long_term_frame_idx_ 1185 max_long_term_frame_idx_
1182 = ref_pic_marking->max_long_term_frame_idx_plus1 - 1; 1186 = ref_pic_marking->max_long_term_frame_idx_plus1 - 1;
1183 H264Picture::PtrVector long_terms; 1187 VaapiH264Picture::PtrVector long_terms;
1184 dpb_.GetLongTermRefPicsAppending(long_terms); 1188 dpb_.GetLongTermRefPicsAppending(long_terms);
1185 for (size_t i = 0; i < long_terms.size(); ++i) { 1189 for (size_t i = 0; i < long_terms.size(); ++i) {
1186 H264Picture* pic = long_terms[i]; 1190 VaapiH264Picture* pic = long_terms[i];
1187 DCHECK(pic->ref && pic->long_term); 1191 DCHECK(pic->ref && pic->long_term);
1188 // Ok to cast, max_long_term_frame_idx is much smaller than 16bit. 1192 // Ok to cast, max_long_term_frame_idx is much smaller than 16bit.
1189 if (pic->long_term_frame_idx > 1193 if (pic->long_term_frame_idx >
1190 static_cast<int>(max_long_term_frame_idx_)) 1194 static_cast<int>(max_long_term_frame_idx_))
1191 pic->ref = false; 1195 pic->ref = false;
1192 } 1196 }
1193 break; 1197 break;
1194 } 1198 }
1195 1199
1196 case 5: 1200 case 5:
1197 // Unmark all reference pictures. 1201 // Unmark all reference pictures.
1198 dpb_.MarkAllUnusedForRef(); 1202 dpb_.MarkAllUnusedForRef();
1199 max_long_term_frame_idx_ = -1; 1203 max_long_term_frame_idx_ = -1;
1200 curr_pic_->mem_mgmt_5 = true; 1204 curr_pic_->mem_mgmt_5 = true;
1201 break; 1205 break;
1202 1206
1203 case 6: { 1207 case 6: {
1204 // Replace long term reference pictures with current picture. 1208 // Replace long term reference pictures with current picture.
1205 // First unmark if any existing with this long_term_frame_idx... 1209 // First unmark if any existing with this long_term_frame_idx...
1206 H264Picture::PtrVector long_terms; 1210 VaapiH264Picture::PtrVector long_terms;
1207 dpb_.GetLongTermRefPicsAppending(long_terms); 1211 dpb_.GetLongTermRefPicsAppending(long_terms);
1208 for (size_t i = 0; i < long_terms.size(); ++i) { 1212 for (size_t i = 0; i < long_terms.size(); ++i) {
1209 H264Picture* pic = long_terms[i]; 1213 VaapiH264Picture* pic = long_terms[i];
1210 DCHECK(pic->ref && pic->long_term); 1214 DCHECK(pic->ref && pic->long_term);
1211 // Ok to cast, long_term_frame_idx is much smaller than 16bit. 1215 // Ok to cast, long_term_frame_idx is much smaller than 16bit.
1212 if (pic->long_term_frame_idx == 1216 if (pic->long_term_frame_idx ==
1213 static_cast<int>(ref_pic_marking->long_term_frame_idx)) 1217 static_cast<int>(ref_pic_marking->long_term_frame_idx))
1214 pic->ref = false; 1218 pic->ref = false;
1215 } 1219 }
1216 1220
1217 // and mark the current one instead. 1221 // and mark the current one instead.
1218 curr_pic_->ref = true; 1222 curr_pic_->ref = true;
1219 curr_pic_->long_term = true; 1223 curr_pic_->long_term = true;
(...skipping 26 matching lines...) Expand all
1246 max_long_term_frame_idx_ = 0; 1250 max_long_term_frame_idx_ = 0;
1247 } else { 1251 } else {
1248 curr_pic_->long_term = false; 1252 curr_pic_->long_term = false;
1249 max_long_term_frame_idx_ = -1; 1253 max_long_term_frame_idx_ = -1;
1250 } 1254 }
1251 } else { 1255 } else {
1252 if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) { 1256 if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) {
1253 // If non-IDR, and the stream does not indicate what we should do to 1257 // If non-IDR, and the stream does not indicate what we should do to
1254 // ensure DPB doesn't overflow, discard oldest picture. 1258 // ensure DPB doesn't overflow, discard oldest picture.
1255 // See spec 8.2.5.3. 1259 // See spec 8.2.5.3.
1256 if (curr_pic_->field == H264Picture::FIELD_NONE) { 1260 if (curr_pic_->field == VaapiH264Picture::FIELD_NONE) {
1257 DCHECK_LE(dpb_.CountRefPics(), 1261 DCHECK_LE(dpb_.CountRefPics(),
1258 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames, 1262 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
1259 1)); 1263 1));
1260 if (dpb_.CountRefPics() == 1264 if (dpb_.CountRefPics() ==
1261 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames, 1265 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames,
1262 1)) { 1266 1)) {
1263 // Max number of reference pics reached, 1267 // Max number of reference pics reached,
1264 // need to remove one of the short term ones. 1268 // need to remove one of the short term ones.
1265 // Find smallest frame_num_wrap short reference picture and mark 1269 // Find smallest frame_num_wrap short reference picture and mark
1266 // it as unused. 1270 // it as unused.
1267 H264Picture* to_unmark = dpb_.GetLowestFrameNumWrapShortRefPic(); 1271 VaapiH264Picture* to_unmark = dpb_.GetLowestFrameNumWrapShortRefPic();
1268 if (to_unmark == NULL) { 1272 if (to_unmark == NULL) {
1269 DVLOG(1) << "Couldn't find a short ref picture to unmark"; 1273 DVLOG(1) << "Couldn't find a short ref picture to unmark";
1270 return; 1274 return;
1271 } 1275 }
1272 to_unmark->ref = false; 1276 to_unmark->ref = false;
1273 } 1277 }
1274 } else { 1278 } else {
1275 // Shouldn't get here. 1279 // Shouldn't get here.
1276 DVLOG(1) << "Interlaced video not supported."; 1280 DVLOG(1) << "Interlaced video not supported.";
1277 report_error_to_uma_cb_.Run(INTERLACED_STREAM); 1281 report_error_to_uma_cb_.Run(INTERLACED_STREAM);
1278 } 1282 }
1279 } else { 1283 } else {
1280 // Stream has instructions how to discard pictures from DPB and how 1284 // Stream has instructions how to discard pictures from DPB and how
1281 // to mark/unmark existing reference pictures. Do it. 1285 // to mark/unmark existing reference pictures. Do it.
1282 // Spec 8.2.5.4. 1286 // Spec 8.2.5.4.
1283 if (curr_pic_->field == H264Picture::FIELD_NONE) { 1287 if (curr_pic_->field == VaapiH264Picture::FIELD_NONE) {
1284 HandleMemoryManagementOps(); 1288 HandleMemoryManagementOps();
1285 } else { 1289 } else {
1286 // Shouldn't get here. 1290 // Shouldn't get here.
1287 DVLOG(1) << "Interlaced video not supported."; 1291 DVLOG(1) << "Interlaced video not supported.";
1288 report_error_to_uma_cb_.Run(INTERLACED_STREAM); 1292 report_error_to_uma_cb_.Run(INTERLACED_STREAM);
1289 } 1293 }
1290 } 1294 }
1291 } 1295 }
1292 } 1296 }
1293 1297
1294 bool VaapiH264Decoder::FinishPicture() { 1298 bool VaapiH264Decoder::FinishPicture() {
1295 DCHECK(curr_pic_.get()); 1299 DCHECK(curr_pic_.get());
1296 1300
1297 // Finish processing previous picture. 1301 // Finish processing previous picture.
1298 // Start by storing previous reference picture data for later use, 1302 // Start by storing previous reference picture data for later use,
1299 // if picture being finished is a reference picture. 1303 // if picture being finished is a reference picture.
1300 if (curr_pic_->ref) { 1304 if (curr_pic_->ref) {
1301 ReferencePictureMarking(); 1305 ReferencePictureMarking();
1302 prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5; 1306 prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
1303 prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt; 1307 prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt;
1304 prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb; 1308 prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb;
1305 prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb; 1309 prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb;
1306 prev_ref_field_ = curr_pic_->field; 1310 prev_ref_field_ = curr_pic_->field;
1307 } 1311 }
1308 prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5; 1312 prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5;
1309 prev_frame_num_offset_ = curr_pic_->frame_num_offset; 1313 prev_frame_num_offset_ = curr_pic_->frame_num_offset;
1310 1314
1311 // Remove unused (for reference or later output) pictures from DPB, marking 1315 // Remove unused (for reference or later output) pictures from DPB, marking
1312 // them as such. 1316 // them as such.
1313 for (H264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end(); ++it) { 1317 for (VaapiH264DPB::Pictures::iterator it = dpb_.begin(); it != dpb_.end();
1318 ++it) {
1314 if ((*it)->outputted && !(*it)->ref) 1319 if ((*it)->outputted && !(*it)->ref)
1315 UnassignSurfaceFromPoC((*it)->pic_order_cnt); 1320 UnassignSurfaceFromPoC((*it)->pic_order_cnt);
1316 } 1321 }
1317 dpb_.DeleteUnused(); 1322 dpb_.DeleteUnused();
1318 1323
1319 DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size(); 1324 DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size();
1320 1325
1321 // Whatever happens below, curr_pic_ will stop managing the pointer to the 1326 // Whatever happens below, curr_pic_ will stop managing the pointer to the
1322 // picture after this function returns. The ownership will either be 1327 // picture after this function returns. The ownership will either be
1323 // transferred to DPB, if the image is still needed (for output and/or 1328 // transferred to DPB, if the image is still needed (for output and/or
1324 // reference), or the memory will be released if we manage to output it here 1329 // reference), or the memory will be released if we manage to output it here
1325 // without having to store it for future reference. 1330 // without having to store it for future reference.
1326 scoped_ptr<H264Picture> pic(curr_pic_.release()); 1331 scoped_ptr<VaapiH264Picture> pic(curr_pic_.release());
1327 1332
1328 // Get all pictures that haven't been outputted yet. 1333 // Get all pictures that haven't been outputted yet.
1329 H264Picture::PtrVector not_outputted; 1334 VaapiH264Picture::PtrVector not_outputted;
1330 // TODO(posciak): pass as pointer, not reference (violates coding style). 1335 // TODO(posciak): pass as pointer, not reference (violates coding style).
1331 dpb_.GetNotOutputtedPicsAppending(not_outputted); 1336 dpb_.GetNotOutputtedPicsAppending(not_outputted);
1332 // Include the one we've just decoded. 1337 // Include the one we've just decoded.
1333 not_outputted.push_back(pic.get()); 1338 not_outputted.push_back(pic.get());
1334 1339
1335 // Sort in output order. 1340 // Sort in output order.
1336 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); 1341 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare());
1337 1342
1338 // Try to output as many pictures as we can. A picture can be output, 1343 // Try to output as many pictures as we can. A picture can be output,
1339 // if the number of decoded and not yet outputted pictures that would remain 1344 // if the number of decoded and not yet outputted pictures that would remain
1340 // in DPB afterwards would at least be equal to max_num_reorder_frames. 1345 // in DPB afterwards would at least be equal to max_num_reorder_frames.
1341 // If the outputted picture is not a reference picture, it doesn't have 1346 // If the outputted picture is not a reference picture, it doesn't have
1342 // to remain in the DPB and can be removed. 1347 // to remain in the DPB and can be removed.
1343 H264Picture::PtrVector::iterator output_candidate = not_outputted.begin(); 1348 VaapiH264Picture::PtrVector::iterator output_candidate =
1349 not_outputted.begin();
1344 size_t num_remaining = not_outputted.size(); 1350 size_t num_remaining = not_outputted.size();
1345 while (num_remaining > max_num_reorder_frames_) { 1351 while (num_remaining > max_num_reorder_frames_) {
1346 int poc = (*output_candidate)->pic_order_cnt; 1352 int poc = (*output_candidate)->pic_order_cnt;
1347 DCHECK_GE(poc, last_output_poc_); 1353 DCHECK_GE(poc, last_output_poc_);
1348 if (!OutputPic(*output_candidate)) 1354 if (!OutputPic(*output_candidate))
1349 return false; 1355 return false;
1350 1356
1351 if (!(*output_candidate)->ref) { 1357 if (!(*output_candidate)->ref) {
1352 // Current picture hasn't been inserted into DPB yet, so don't remove it 1358 // Current picture hasn't been inserted into DPB yet, so don't remove it
1353 // if we managed to output it immediately. 1359 // if we managed to output it immediately.
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1483 1489
1484 max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); 1490 max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
1485 max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4); 1491 max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4);
1486 1492
1487 int level = sps->level_idc; 1493 int level = sps->level_idc;
1488 int max_dpb_mbs = LevelToMaxDpbMbs(level); 1494 int max_dpb_mbs = LevelToMaxDpbMbs(level);
1489 if (max_dpb_mbs == 0) 1495 if (max_dpb_mbs == 0)
1490 return false; 1496 return false;
1491 1497
1492 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb), 1498 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb),
1493 static_cast<int>(H264DPB::kDPBMaxSize)); 1499 static_cast<int>(VaapiH264DPB::kDPBMaxSize));
1494 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size; 1500 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size;
1495 if (max_dpb_size == 0) { 1501 if (max_dpb_size == 0) {
1496 DVLOG(1) << "Invalid DPB Size"; 1502 DVLOG(1) << "Invalid DPB Size";
1497 return false; 1503 return false;
1498 } 1504 }
1499 1505
1500 dpb_.set_max_num_pics(max_dpb_size); 1506 dpb_.set_max_num_pics(max_dpb_size);
1501 1507
1502 if (!UpdateMaxNumReorderFrames(sps)) 1508 if (!UpdateMaxNumReorderFrames(sps))
1503 return false; 1509 return false;
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 break; 1697 break;
1692 } 1698 }
1693 } 1699 }
1694 } 1700 }
1695 1701
1696 size_t VaapiH264Decoder::GetRequiredNumOfPictures() { 1702 size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
1697 return dpb_.max_num_pics() + kPicsInPipeline; 1703 return dpb_.max_num_pics() + kPicsInPipeline;
1698 } 1704 }
1699 1705
1700 } // namespace content 1706 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vaapi_h264_decoder.h ('k') | content/common/gpu/media/vaapi_h264_dpb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698