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