Chromium Code Reviews| 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/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/numerics/safe_conversions.h" | 11 #include "base/numerics/safe_conversions.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "content/common/gpu/media/h264_decoder.h" | 13 #include "content/common/gpu/media/h264_decoder.h" |
| 14 | 14 |
| 15 namespace content { | 15 namespace content { |
| 16 | 16 |
| 17 H264Decoder::H264Accelerator::H264Accelerator() { | 17 H264Decoder::H264Accelerator::H264Accelerator() { |
| 18 } | 18 } |
| 19 | 19 |
| 20 H264Decoder::H264Accelerator::~H264Accelerator() { | 20 H264Decoder::H264Accelerator::~H264Accelerator() { |
| 21 } | 21 } |
| 22 | 22 |
| 23 H264Decoder::H264Decoder(H264Accelerator* accelerator) | 23 H264Decoder::H264Decoder(H264Accelerator* accelerator) |
| 24 : max_pic_order_cnt_lsb_(0), | 24 : max_frame_num_(0), |
| 25 max_frame_num_(0), | |
| 26 max_pic_num_(0), | 25 max_pic_num_(0), |
| 27 max_long_term_frame_idx_(0), | 26 max_long_term_frame_idx_(0), |
| 28 max_num_reorder_frames_(0), | 27 max_num_reorder_frames_(0), |
| 29 curr_sps_id_(-1), | |
| 30 curr_pps_id_(-1), | |
| 31 accelerator_(accelerator) { | 28 accelerator_(accelerator) { |
| 32 DCHECK(accelerator_); | 29 DCHECK(accelerator_); |
| 33 Reset(); | 30 Reset(); |
| 34 state_ = kNeedStreamMetadata; | 31 state_ = kNeedStreamMetadata; |
| 35 } | 32 } |
| 36 | 33 |
| 37 H264Decoder::~H264Decoder() { | 34 H264Decoder::~H264Decoder() { |
| 38 } | 35 } |
| 39 | 36 |
| 40 void H264Decoder::Reset() { | 37 void H264Decoder::Reset() { |
| 41 curr_pic_ = nullptr; | 38 curr_pic_ = nullptr; |
| 42 curr_nalu_ = nullptr; | 39 curr_nalu_ = nullptr; |
| 43 curr_slice_hdr_ = nullptr; | 40 curr_slice_hdr_ = nullptr; |
| 41 curr_sps_id_ = -1; | |
| 42 curr_pps_id_ = -1; | |
| 44 | 43 |
| 45 frame_num_ = 0; | |
| 46 prev_frame_num_ = -1; | 44 prev_frame_num_ = -1; |
| 45 prev_ref_frame_num_ = -1; | |
| 47 prev_frame_num_offset_ = -1; | 46 prev_frame_num_offset_ = -1; |
| 47 prev_has_memmgmnt5_ = false; | |
| 48 | 48 |
| 49 prev_ref_has_memmgmnt5_ = false; | 49 prev_ref_has_memmgmnt5_ = false; |
| 50 prev_ref_top_field_order_cnt_ = -1; | 50 prev_ref_top_field_order_cnt_ = -1; |
| 51 prev_ref_pic_order_cnt_msb_ = -1; | 51 prev_ref_pic_order_cnt_msb_ = -1; |
| 52 prev_ref_pic_order_cnt_lsb_ = -1; | 52 prev_ref_pic_order_cnt_lsb_ = -1; |
| 53 prev_ref_field_ = H264Picture::FIELD_NONE; | 53 prev_ref_field_ = H264Picture::FIELD_NONE; |
| 54 | 54 |
| 55 ref_pic_list_p0_.clear(); | 55 ref_pic_list_p0_.clear(); |
| 56 ref_pic_list_b0_.clear(); | 56 ref_pic_list_b0_.clear(); |
| 57 ref_pic_list_b1_.clear(); | 57 ref_pic_list_b1_.clear(); |
| 58 dpb_.Clear(); | 58 dpb_.Clear(); |
| 59 parser_.Reset(); | 59 parser_.Reset(); |
| 60 accelerator_->Reset(); | 60 accelerator_->Reset(); |
| 61 last_output_poc_ = std::numeric_limits<int>::min(); | 61 last_output_poc_ = std::numeric_limits<int>::min(); |
| 62 | 62 |
| 63 // If we are in kDecoding, we can resume without processing an SPS. | 63 // If we are in kDecoding, we can resume without processing an SPS. |
| 64 if (state_ == kDecoding) | 64 if (state_ == kDecoding) |
| 65 state_ = kAfterReset; | 65 state_ = kAfterReset; |
| 66 } | 66 } |
| 67 | 67 |
| 68 void H264Decoder::PrepareRefPicLists(media::H264SliceHeader* slice_hdr) { | 68 void H264Decoder::PrepareRefPicLists(const media::H264SliceHeader* slice_hdr) { |
| 69 ConstructReferencePicListsP(slice_hdr); | 69 ConstructReferencePicListsP(slice_hdr); |
| 70 ConstructReferencePicListsB(slice_hdr); | 70 ConstructReferencePicListsB(slice_hdr); |
| 71 } | 71 } |
| 72 | 72 |
| 73 bool H264Decoder::ModifyReferencePicLists(media::H264SliceHeader* slice_hdr, | 73 bool H264Decoder::ModifyReferencePicLists( |
| 74 H264Picture::Vector* ref_pic_list0, | 74 const media::H264SliceHeader* slice_hdr, |
| 75 H264Picture::Vector* ref_pic_list1) { | 75 H264Picture::Vector* ref_pic_list0, |
| 76 H264Picture::Vector* ref_pic_list1) { | |
| 76 ref_pic_list0->clear(); | 77 ref_pic_list0->clear(); |
| 77 ref_pic_list1->clear(); | 78 ref_pic_list1->clear(); |
| 78 | 79 |
| 79 // Fill reference picture lists for B and S/SP slices. | 80 // Fill reference picture lists for B and S/SP slices. |
| 80 if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) { | 81 if (slice_hdr->IsPSlice() || slice_hdr->IsSPSlice()) { |
| 81 *ref_pic_list0 = ref_pic_list_p0_; | 82 *ref_pic_list0 = ref_pic_list_p0_; |
| 82 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0); | 83 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0); |
| 83 } else if (slice_hdr->IsBSlice()) { | 84 } else if (slice_hdr->IsBSlice()) { |
| 84 *ref_pic_list0 = ref_pic_list_b0_; | 85 *ref_pic_list0 = ref_pic_list_b0_; |
| 85 *ref_pic_list1 = ref_pic_list_b1_; | 86 *ref_pic_list1 = ref_pic_list_b1_; |
| 86 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0) && | 87 return ModifyReferencePicList(slice_hdr, 0, ref_pic_list0) && |
| 87 ModifyReferencePicList(slice_hdr, 1, ref_pic_list1); | 88 ModifyReferencePicList(slice_hdr, 1, ref_pic_list1); |
| 88 } | 89 } |
| 89 | 90 |
| 90 return true; | 91 return true; |
| 91 } | 92 } |
| 92 | 93 |
| 93 bool H264Decoder::DecodePicture() { | 94 bool H264Decoder::DecodePicture() { |
| 94 DCHECK(curr_pic_.get()); | 95 DCHECK(curr_pic_.get()); |
| 95 | 96 |
| 96 DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt; | 97 DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt; |
| 97 return accelerator_->SubmitDecode(curr_pic_); | 98 return accelerator_->SubmitDecode(curr_pic_); |
| 98 } | 99 } |
| 99 | 100 |
| 100 bool H264Decoder::InitCurrPicture(media::H264SliceHeader* slice_hdr) { | 101 bool H264Decoder::InitNonexistingPicture(scoped_refptr<H264Picture> pic, |
|
xhwang
2015/10/12 18:01:17
nit: in media code, we pass const-ref of scoped_re
Pawel Osciak
2015/10/13 01:23:22
Yes, I'd like to do that too, but for now wanted t
| |
| 102 int frame_num) { | |
| 103 pic->nonexisting = true; | |
| 104 pic->nal_ref_idc = 1; | |
| 105 pic->frame_num = pic->pic_num = frame_num; | |
| 106 pic->adaptive_ref_pic_marking_mode_flag = false; | |
| 107 pic->ref = true; | |
| 108 pic->long_term_reference_flag = false; | |
| 109 pic->field = H264Picture::FIELD_NONE; | |
| 110 | |
| 111 return CalculatePicOrderCounts(pic); | |
| 112 } | |
| 113 | |
| 114 bool H264Decoder::InitCurrPicture(const media::H264SliceHeader* slice_hdr) { | |
| 101 DCHECK(curr_pic_.get()); | 115 DCHECK(curr_pic_.get()); |
| 102 | 116 |
| 103 curr_pic_->idr = slice_hdr->idr_pic_flag; | 117 curr_pic_->idr = slice_hdr->idr_pic_flag; |
| 118 if (curr_pic_->idr) | |
| 119 curr_pic_->idr_pic_id = slice_hdr->idr_pic_id; | |
| 104 | 120 |
| 105 if (slice_hdr->field_pic_flag) { | 121 if (slice_hdr->field_pic_flag) { |
| 106 curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM | 122 curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM |
| 107 : H264Picture::FIELD_TOP; | 123 : H264Picture::FIELD_TOP; |
| 108 } else { | 124 } else { |
| 109 curr_pic_->field = H264Picture::FIELD_NONE; | 125 curr_pic_->field = H264Picture::FIELD_NONE; |
| 110 } | 126 } |
| 111 | 127 |
| 128 if (curr_pic_->field != H264Picture::FIELD_NONE) { | |
| 129 DVLOG(1) << "Interlaced video not supported."; | |
| 130 return false; | |
| 131 } | |
| 132 | |
| 133 curr_pic_->nal_ref_idc = slice_hdr->nal_ref_idc; | |
| 112 curr_pic_->ref = slice_hdr->nal_ref_idc != 0; | 134 curr_pic_->ref = slice_hdr->nal_ref_idc != 0; |
| 113 // This assumes non-interlaced stream. | 135 // This assumes non-interlaced stream. |
| 114 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num; | 136 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num; |
| 115 | 137 |
| 116 if (!CalculatePicOrderCounts(slice_hdr)) | 138 DCHECK_NE(curr_sps_id_, -1); |
| 139 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); | |
| 140 if (!sps) | |
| 141 return false; | |
| 142 | |
| 143 curr_pic_->pic_order_cnt_type = sps->pic_order_cnt_type; | |
| 144 switch (curr_pic_->pic_order_cnt_type) { | |
|
xhwang
2015/10/12 18:01:17
nit: can you have an enum for |pic_order_cnt_type|
Pawel Osciak
2015/10/13 01:23:22
This is intentional, as the H264 spec uses "pic or
| |
| 145 case 0: | |
| 146 curr_pic_->pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; | |
| 147 curr_pic_->delta_pic_order_cnt_bottom = | |
| 148 slice_hdr->delta_pic_order_cnt_bottom; | |
| 149 break; | |
| 150 | |
| 151 case 1: | |
| 152 curr_pic_->delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt0; | |
| 153 curr_pic_->delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt1; | |
| 154 break; | |
| 155 | |
| 156 case 2: | |
| 157 break; | |
| 158 | |
| 159 default: | |
| 160 NOTREACHED(); | |
| 161 return false; | |
| 162 } | |
| 163 | |
| 164 if (!CalculatePicOrderCounts(curr_pic_)) | |
| 117 return false; | 165 return false; |
| 118 | 166 |
| 119 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; | 167 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; |
| 120 curr_pic_->adaptive_ref_pic_marking_mode_flag = | 168 curr_pic_->adaptive_ref_pic_marking_mode_flag = |
| 121 slice_hdr->adaptive_ref_pic_marking_mode_flag; | 169 slice_hdr->adaptive_ref_pic_marking_mode_flag; |
| 122 | 170 |
| 123 // If the slice header indicates we will have to perform reference marking | 171 // If the slice header indicates we will have to perform reference marking |
| 124 // process after this picture is decoded, store required data for that | 172 // process after this picture is decoded, store required data for that |
| 125 // purpose. | 173 // purpose. |
| 126 if (slice_hdr->adaptive_ref_pic_marking_mode_flag) { | 174 if (slice_hdr->adaptive_ref_pic_marking_mode_flag) { |
| 127 static_assert(sizeof(curr_pic_->ref_pic_marking) == | 175 static_assert(sizeof(curr_pic_->ref_pic_marking) == |
| 128 sizeof(slice_hdr->ref_pic_marking), | 176 sizeof(slice_hdr->ref_pic_marking), |
| 129 "Array sizes of ref pic marking do not match."); | 177 "Array sizes of ref pic marking do not match."); |
| 130 memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking, | 178 memcpy(curr_pic_->ref_pic_marking, slice_hdr->ref_pic_marking, |
| 131 sizeof(curr_pic_->ref_pic_marking)); | 179 sizeof(curr_pic_->ref_pic_marking)); |
| 132 } | 180 } |
| 133 | 181 |
| 134 return true; | 182 return true; |
| 135 } | 183 } |
| 136 | 184 |
| 137 bool H264Decoder::CalculatePicOrderCounts(media::H264SliceHeader* slice_hdr) { | 185 bool H264Decoder::CalculatePicOrderCounts(scoped_refptr<H264Picture> pic) { |
| 138 DCHECK_NE(curr_sps_id_, -1); | |
| 139 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); | 186 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); |
| 187 if (!sps) | |
| 188 return false; | |
| 140 | 189 |
| 141 int pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; | 190 switch (pic->pic_order_cnt_type) { |
| 142 curr_pic_->pic_order_cnt_lsb = pic_order_cnt_lsb; | 191 case 0: { |
|
xhwang
2015/10/12 18:01:17
ditto
| |
| 143 | |
| 144 switch (sps->pic_order_cnt_type) { | |
| 145 case 0: | |
| 146 // See spec 8.2.1.1. | 192 // See spec 8.2.1.1. |
| 147 int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb; | 193 int prev_pic_order_cnt_msb, prev_pic_order_cnt_lsb; |
| 148 if (slice_hdr->idr_pic_flag) { | 194 |
| 195 if (pic->idr) { | |
| 149 prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0; | 196 prev_pic_order_cnt_msb = prev_pic_order_cnt_lsb = 0; |
| 150 } else { | 197 } else { |
| 151 if (prev_ref_has_memmgmnt5_) { | 198 if (prev_ref_has_memmgmnt5_) { |
| 152 if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) { | 199 if (prev_ref_field_ != H264Picture::FIELD_BOTTOM) { |
| 153 prev_pic_order_cnt_msb = 0; | 200 prev_pic_order_cnt_msb = 0; |
| 154 prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_; | 201 prev_pic_order_cnt_lsb = prev_ref_top_field_order_cnt_; |
| 155 } else { | 202 } else { |
| 156 prev_pic_order_cnt_msb = 0; | 203 prev_pic_order_cnt_msb = 0; |
| 157 prev_pic_order_cnt_lsb = 0; | 204 prev_pic_order_cnt_lsb = 0; |
| 158 } | 205 } |
| 159 } else { | 206 } else { |
| 160 prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_; | 207 prev_pic_order_cnt_msb = prev_ref_pic_order_cnt_msb_; |
| 161 prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_; | 208 prev_pic_order_cnt_lsb = prev_ref_pic_order_cnt_lsb_; |
| 162 } | 209 } |
| 163 } | 210 } |
| 164 | 211 |
| 165 DCHECK_NE(max_pic_order_cnt_lsb_, 0); | 212 int max_pic_order_cnt_lsb = |
| 166 if ((pic_order_cnt_lsb < prev_pic_order_cnt_lsb) && | 213 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); |
| 167 (prev_pic_order_cnt_lsb - pic_order_cnt_lsb >= | 214 DCHECK_NE(max_pic_order_cnt_lsb, 0); |
| 168 max_pic_order_cnt_lsb_ / 2)) { | 215 if ((pic->pic_order_cnt_lsb < prev_pic_order_cnt_lsb) && |
| 169 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb + | 216 (prev_pic_order_cnt_lsb - pic->pic_order_cnt_lsb >= |
| 170 max_pic_order_cnt_lsb_; | 217 max_pic_order_cnt_lsb / 2)) { |
| 171 } else if ((pic_order_cnt_lsb > prev_pic_order_cnt_lsb) && | 218 pic->pic_order_cnt_msb = prev_pic_order_cnt_msb + max_pic_order_cnt_lsb; |
| 172 (pic_order_cnt_lsb - prev_pic_order_cnt_lsb > | 219 } else if ((pic->pic_order_cnt_lsb > prev_pic_order_cnt_lsb) && |
| 173 max_pic_order_cnt_lsb_ / 2)) { | 220 (pic->pic_order_cnt_lsb - prev_pic_order_cnt_lsb > |
| 174 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb - | 221 max_pic_order_cnt_lsb / 2)) { |
| 175 max_pic_order_cnt_lsb_; | 222 pic->pic_order_cnt_msb = prev_pic_order_cnt_msb - max_pic_order_cnt_lsb; |
| 176 } else { | 223 } else { |
| 177 curr_pic_->pic_order_cnt_msb = prev_pic_order_cnt_msb; | 224 pic->pic_order_cnt_msb = prev_pic_order_cnt_msb; |
| 178 } | 225 } |
| 179 | 226 |
| 180 if (curr_pic_->field != H264Picture::FIELD_BOTTOM) { | 227 if (pic->field != H264Picture::FIELD_BOTTOM) { |
| 181 curr_pic_->top_field_order_cnt = curr_pic_->pic_order_cnt_msb + | 228 pic->top_field_order_cnt = |
| 182 pic_order_cnt_lsb; | 229 pic->pic_order_cnt_msb + pic->pic_order_cnt_lsb; |
| 183 } | 230 } |
| 184 | 231 |
| 185 if (curr_pic_->field != H264Picture::FIELD_TOP) { | 232 if (pic->field != H264Picture::FIELD_TOP) { |
| 186 // TODO posciak: perhaps replace with pic->field? | 233 if (pic->field == H264Picture::FIELD_NONE) { |
| 187 if (!slice_hdr->field_pic_flag) { | 234 pic->bottom_field_order_cnt = |
| 188 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt + | 235 pic->top_field_order_cnt + pic->delta_pic_order_cnt_bottom; |
| 189 slice_hdr->delta_pic_order_cnt_bottom; | |
| 190 } else { | 236 } else { |
| 191 curr_pic_->bottom_field_order_cnt = curr_pic_->pic_order_cnt_msb + | 237 pic->bottom_field_order_cnt = |
| 192 pic_order_cnt_lsb; | 238 pic->pic_order_cnt_msb + pic->pic_order_cnt_lsb; |
| 193 } | 239 } |
| 194 } | 240 } |
| 195 break; | 241 break; |
| 242 } | |
| 196 | 243 |
| 197 case 1: { | 244 case 1: { |
| 198 // See spec 8.2.1.2. | 245 // See spec 8.2.1.2. |
| 199 if (prev_has_memmgmnt5_) | 246 if (prev_has_memmgmnt5_) |
| 200 prev_frame_num_offset_ = 0; | 247 prev_frame_num_offset_ = 0; |
| 201 | 248 |
| 202 if (slice_hdr->idr_pic_flag) | 249 if (pic->idr) |
| 203 curr_pic_->frame_num_offset = 0; | 250 pic->frame_num_offset = 0; |
| 204 else if (prev_frame_num_ > slice_hdr->frame_num) | 251 else if (prev_frame_num_ > pic->frame_num) |
| 205 curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_; | 252 pic->frame_num_offset = prev_frame_num_offset_ + max_frame_num_; |
| 206 else | 253 else |
| 207 curr_pic_->frame_num_offset = prev_frame_num_offset_; | 254 pic->frame_num_offset = prev_frame_num_offset_; |
| 208 | 255 |
| 209 int abs_frame_num = 0; | 256 int abs_frame_num = 0; |
| 210 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) | 257 if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) |
| 211 abs_frame_num = curr_pic_->frame_num_offset + slice_hdr->frame_num; | 258 abs_frame_num = pic->frame_num_offset + pic->frame_num; |
| 212 else | 259 else |
| 213 abs_frame_num = 0; | 260 abs_frame_num = 0; |
| 214 | 261 |
| 215 if (slice_hdr->nal_ref_idc == 0 && abs_frame_num > 0) | 262 if (pic->nal_ref_idc == 0 && abs_frame_num > 0) |
| 216 --abs_frame_num; | 263 --abs_frame_num; |
| 217 | 264 |
| 218 int expected_pic_order_cnt = 0; | 265 int expected_pic_order_cnt = 0; |
| 219 if (abs_frame_num > 0) { | 266 if (abs_frame_num > 0) { |
| 220 if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) { | 267 if (sps->num_ref_frames_in_pic_order_cnt_cycle == 0) { |
| 221 DVLOG(1) << "Invalid num_ref_frames_in_pic_order_cnt_cycle " | 268 DVLOG(1) << "Invalid num_ref_frames_in_pic_order_cnt_cycle " |
| 222 << "in stream"; | 269 << "in stream"; |
| 223 return false; | 270 return false; |
| 224 } | 271 } |
| 225 | 272 |
| 226 int pic_order_cnt_cycle_cnt = (abs_frame_num - 1) / | 273 int pic_order_cnt_cycle_cnt = (abs_frame_num - 1) / |
| 227 sps->num_ref_frames_in_pic_order_cnt_cycle; | 274 sps->num_ref_frames_in_pic_order_cnt_cycle; |
| 228 int frame_num_in_pic_order_cnt_cycle = (abs_frame_num - 1) % | 275 int frame_num_in_pic_order_cnt_cycle = (abs_frame_num - 1) % |
| 229 sps->num_ref_frames_in_pic_order_cnt_cycle; | 276 sps->num_ref_frames_in_pic_order_cnt_cycle; |
| 230 | 277 |
| 231 expected_pic_order_cnt = pic_order_cnt_cycle_cnt * | 278 expected_pic_order_cnt = pic_order_cnt_cycle_cnt * |
| 232 sps->expected_delta_per_pic_order_cnt_cycle; | 279 sps->expected_delta_per_pic_order_cnt_cycle; |
| 233 // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser | 280 // frame_num_in_pic_order_cnt_cycle is verified < 255 in parser |
| 234 for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i) | 281 for (int i = 0; i <= frame_num_in_pic_order_cnt_cycle; ++i) |
| 235 expected_pic_order_cnt += sps->offset_for_ref_frame[i]; | 282 expected_pic_order_cnt += sps->offset_for_ref_frame[i]; |
| 236 } | 283 } |
| 237 | 284 |
| 238 if (!slice_hdr->nal_ref_idc) | 285 if (!pic->nal_ref_idc) |
| 239 expected_pic_order_cnt += sps->offset_for_non_ref_pic; | 286 expected_pic_order_cnt += sps->offset_for_non_ref_pic; |
| 240 | 287 |
| 241 if (!slice_hdr->field_pic_flag) { | 288 if (pic->field == H264Picture::FIELD_NONE) { |
| 242 curr_pic_->top_field_order_cnt = expected_pic_order_cnt + | 289 pic->top_field_order_cnt = |
| 243 slice_hdr->delta_pic_order_cnt0; | 290 expected_pic_order_cnt + pic->delta_pic_order_cnt0; |
| 244 curr_pic_->bottom_field_order_cnt = curr_pic_->top_field_order_cnt + | 291 pic->bottom_field_order_cnt = pic->top_field_order_cnt + |
| 245 sps->offset_for_top_to_bottom_field + | 292 sps->offset_for_top_to_bottom_field + |
| 246 slice_hdr->delta_pic_order_cnt1; | 293 pic->delta_pic_order_cnt1; |
| 247 } else if (!slice_hdr->bottom_field_flag) { | 294 } else if (pic->field != H264Picture::FIELD_BOTTOM) { |
| 248 curr_pic_->top_field_order_cnt = expected_pic_order_cnt + | 295 pic->top_field_order_cnt = |
| 249 slice_hdr->delta_pic_order_cnt0; | 296 expected_pic_order_cnt + pic->delta_pic_order_cnt0; |
| 250 } else { | 297 } else { |
| 251 curr_pic_->bottom_field_order_cnt = expected_pic_order_cnt + | 298 pic->bottom_field_order_cnt = expected_pic_order_cnt + |
| 252 sps->offset_for_top_to_bottom_field + | 299 sps->offset_for_top_to_bottom_field + |
| 253 slice_hdr->delta_pic_order_cnt0; | 300 pic->delta_pic_order_cnt0; |
| 254 } | 301 } |
| 255 break; | 302 break; |
| 256 } | 303 } |
| 257 | 304 |
| 258 case 2: | 305 case 2: { |
| 259 // See spec 8.2.1.3. | 306 // See spec 8.2.1.3. |
| 260 if (prev_has_memmgmnt5_) | 307 if (prev_has_memmgmnt5_) |
| 261 prev_frame_num_offset_ = 0; | 308 prev_frame_num_offset_ = 0; |
| 262 | 309 |
| 263 if (slice_hdr->idr_pic_flag) | 310 if (pic->idr) |
| 264 curr_pic_->frame_num_offset = 0; | 311 pic->frame_num_offset = 0; |
| 265 else if (prev_frame_num_ > slice_hdr->frame_num) | 312 else if (prev_frame_num_ > pic->frame_num) |
| 266 curr_pic_->frame_num_offset = prev_frame_num_offset_ + max_frame_num_; | 313 pic->frame_num_offset = prev_frame_num_offset_ + max_frame_num_; |
| 267 else | 314 else |
| 268 curr_pic_->frame_num_offset = prev_frame_num_offset_; | 315 pic->frame_num_offset = prev_frame_num_offset_; |
| 269 | 316 |
| 270 int temp_pic_order_cnt; | 317 int temp_pic_order_cnt; |
| 271 if (slice_hdr->idr_pic_flag) { | 318 if (pic->idr) { |
| 272 temp_pic_order_cnt = 0; | 319 temp_pic_order_cnt = 0; |
| 273 } else if (!slice_hdr->nal_ref_idc) { | 320 } else if (!pic->nal_ref_idc) { |
| 274 temp_pic_order_cnt = | 321 temp_pic_order_cnt = 2 * (pic->frame_num_offset + pic->frame_num) - 1; |
| 275 2 * (curr_pic_->frame_num_offset + slice_hdr->frame_num) - 1; | |
| 276 } else { | 322 } else { |
| 277 temp_pic_order_cnt = 2 * (curr_pic_->frame_num_offset + | 323 temp_pic_order_cnt = 2 * (pic->frame_num_offset + pic->frame_num); |
| 278 slice_hdr->frame_num); | |
| 279 } | 324 } |
| 280 | 325 |
| 281 if (!slice_hdr->field_pic_flag) { | 326 if (pic->field == H264Picture::FIELD_NONE) { |
| 282 curr_pic_->top_field_order_cnt = temp_pic_order_cnt; | 327 pic->top_field_order_cnt = temp_pic_order_cnt; |
| 283 curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt; | 328 pic->bottom_field_order_cnt = temp_pic_order_cnt; |
| 284 } else if (slice_hdr->bottom_field_flag) { | 329 } else if (pic->field == H264Picture::FIELD_BOTTOM) { |
| 285 curr_pic_->bottom_field_order_cnt = temp_pic_order_cnt; | 330 pic->bottom_field_order_cnt = temp_pic_order_cnt; |
| 286 } else { | 331 } else { |
| 287 curr_pic_->top_field_order_cnt = temp_pic_order_cnt; | 332 pic->top_field_order_cnt = temp_pic_order_cnt; |
| 288 } | 333 } |
| 289 break; | 334 break; |
| 335 } | |
| 290 | 336 |
| 291 default: | 337 default: |
| 292 DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type; | 338 DVLOG(1) << "Invalid pic_order_cnt_type: " << sps->pic_order_cnt_type; |
| 293 return false; | 339 return false; |
| 294 } | 340 } |
| 295 | 341 |
| 296 switch (curr_pic_->field) { | 342 switch (pic->field) { |
| 297 case H264Picture::FIELD_NONE: | 343 case H264Picture::FIELD_NONE: |
| 298 curr_pic_->pic_order_cnt = std::min(curr_pic_->top_field_order_cnt, | 344 pic->pic_order_cnt = |
| 299 curr_pic_->bottom_field_order_cnt); | 345 std::min(pic->top_field_order_cnt, pic->bottom_field_order_cnt); |
| 300 break; | 346 break; |
| 301 case H264Picture::FIELD_TOP: | 347 case H264Picture::FIELD_TOP: |
| 302 curr_pic_->pic_order_cnt = curr_pic_->top_field_order_cnt; | 348 pic->pic_order_cnt = pic->top_field_order_cnt; |
| 303 break; | 349 break; |
| 304 case H264Picture::FIELD_BOTTOM: | 350 case H264Picture::FIELD_BOTTOM: |
| 305 curr_pic_->pic_order_cnt = curr_pic_->bottom_field_order_cnt; | 351 pic->pic_order_cnt = pic->bottom_field_order_cnt; |
| 306 break; | 352 break; |
| 307 } | 353 } |
| 308 | 354 |
| 309 return true; | 355 return true; |
| 310 } | 356 } |
| 311 | 357 |
| 312 void H264Decoder::UpdatePicNums() { | 358 void H264Decoder::UpdatePicNums(int frame_num) { |
| 313 for (auto& pic : dpb_) { | 359 for (auto& pic : dpb_) { |
| 314 if (!pic->ref) | 360 if (!pic->ref) |
| 315 continue; | 361 continue; |
| 316 | 362 |
| 317 // Below assumes non-interlaced stream. | 363 // 8.2.4.1. Assumes non-interlaced stream. |
| 318 DCHECK_EQ(pic->field, H264Picture::FIELD_NONE); | 364 DCHECK_EQ(pic->field, H264Picture::FIELD_NONE); |
| 319 if (pic->long_term) { | 365 if (pic->long_term) { |
| 320 pic->long_term_pic_num = pic->long_term_frame_idx; | 366 pic->long_term_pic_num = pic->long_term_frame_idx; |
| 321 } else { | 367 } else { |
| 322 if (pic->frame_num > frame_num_) | 368 if (pic->frame_num > frame_num) |
| 323 pic->frame_num_wrap = pic->frame_num - max_frame_num_; | 369 pic->frame_num_wrap = pic->frame_num - max_frame_num_; |
| 324 else | 370 else |
| 325 pic->frame_num_wrap = pic->frame_num; | 371 pic->frame_num_wrap = pic->frame_num; |
| 326 | 372 |
| 327 pic->pic_num = pic->frame_num_wrap; | 373 pic->pic_num = pic->frame_num_wrap; |
| 328 } | 374 } |
| 329 } | 375 } |
| 330 } | 376 } |
| 331 | 377 |
| 332 struct PicNumDescCompare { | 378 struct PicNumDescCompare { |
| 333 bool operator()(const scoped_refptr<H264Picture>& a, | 379 bool operator()(const scoped_refptr<H264Picture>& a, |
| 334 const scoped_refptr<H264Picture>& b) const { | 380 const scoped_refptr<H264Picture>& b) const { |
| 335 return a->pic_num > b->pic_num; | 381 return a->pic_num > b->pic_num; |
| 336 } | 382 } |
| 337 }; | 383 }; |
| 338 | 384 |
| 339 struct LongTermPicNumAscCompare { | 385 struct LongTermPicNumAscCompare { |
| 340 bool operator()(const scoped_refptr<H264Picture>& a, | 386 bool operator()(const scoped_refptr<H264Picture>& a, |
| 341 const scoped_refptr<H264Picture>& b) const { | 387 const scoped_refptr<H264Picture>& b) const { |
| 342 return a->long_term_pic_num < b->long_term_pic_num; | 388 return a->long_term_pic_num < b->long_term_pic_num; |
| 343 } | 389 } |
| 344 }; | 390 }; |
| 345 | 391 |
| 346 void H264Decoder::ConstructReferencePicListsP( | 392 void H264Decoder::ConstructReferencePicListsP( |
| 347 media::H264SliceHeader* slice_hdr) { | 393 const media::H264SliceHeader* slice_hdr) { |
| 348 // RefPicList0 (8.2.4.2.1) [[1] [2]], where: | 394 // RefPicList0 (8.2.4.2.1) [[1] [2]], where: |
| 349 // [1] shortterm ref pics sorted by descending pic_num, | 395 // [1] shortterm ref pics sorted by descending pic_num, |
| 350 // [2] longterm ref pics by ascending long_term_pic_num. | 396 // [2] longterm ref pics by ascending long_term_pic_num. |
| 351 ref_pic_list_p0_.clear(); | 397 ref_pic_list_p0_.clear(); |
| 352 | 398 |
| 353 // First get the short ref pics... | 399 // First get the short ref pics... |
| 354 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_p0_); | 400 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_p0_); |
| 355 size_t num_short_refs = ref_pic_list_p0_.size(); | 401 size_t num_short_refs = ref_pic_list_p0_.size(); |
| 356 | 402 |
| 357 // and sort them to get [1]. | 403 // and sort them to get [1]. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 372 }; | 418 }; |
| 373 | 419 |
| 374 struct POCDescCompare { | 420 struct POCDescCompare { |
| 375 bool operator()(const scoped_refptr<H264Picture>& a, | 421 bool operator()(const scoped_refptr<H264Picture>& a, |
| 376 const scoped_refptr<H264Picture>& b) const { | 422 const scoped_refptr<H264Picture>& b) const { |
| 377 return a->pic_order_cnt > b->pic_order_cnt; | 423 return a->pic_order_cnt > b->pic_order_cnt; |
| 378 } | 424 } |
| 379 }; | 425 }; |
| 380 | 426 |
| 381 void H264Decoder::ConstructReferencePicListsB( | 427 void H264Decoder::ConstructReferencePicListsB( |
| 382 media::H264SliceHeader* slice_hdr) { | 428 const media::H264SliceHeader* slice_hdr) { |
| 383 // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where: | 429 // RefPicList0 (8.2.4.2.3) [[1] [2] [3]], where: |
| 384 // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC, | 430 // [1] shortterm ref pics with POC < curr_pic's POC sorted by descending POC, |
| 385 // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC, | 431 // [2] shortterm ref pics with POC > curr_pic's POC by ascending POC, |
| 386 // [3] longterm ref pics by ascending long_term_pic_num. | 432 // [3] longterm ref pics by ascending long_term_pic_num. |
| 387 ref_pic_list_b0_.clear(); | 433 ref_pic_list_b0_.clear(); |
| 388 ref_pic_list_b1_.clear(); | 434 ref_pic_list_b1_.clear(); |
| 389 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_b0_); | 435 dpb_.GetShortTermRefPicsAppending(&ref_pic_list_b0_); |
| 390 size_t num_short_refs = ref_pic_list_b0_.size(); | 436 size_t num_short_refs = ref_pic_list_b0_.size(); |
| 391 | 437 |
| 392 // First sort ascending, this will put [1] in right place and finish [2]. | 438 // First sort ascending, this will put [1] in right place and finish [2]. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 (to + 2 == static_cast<int>(v->size()))); | 516 (to + 2 == static_cast<int>(v->size()))); |
| 471 | 517 |
| 472 v->resize(to + 2); | 518 v->resize(to + 2); |
| 473 | 519 |
| 474 for (int i = to + 1; i > from; --i) | 520 for (int i = to + 1; i > from; --i) |
| 475 (*v)[i] = (*v)[i - 1]; | 521 (*v)[i] = (*v)[i - 1]; |
| 476 | 522 |
| 477 (*v)[from] = pic; | 523 (*v)[from] = pic; |
| 478 } | 524 } |
| 479 | 525 |
| 480 bool H264Decoder::ModifyReferencePicList(media::H264SliceHeader* slice_hdr, | 526 bool H264Decoder::ModifyReferencePicList( |
| 481 int list, | 527 const media::H264SliceHeader* slice_hdr, |
| 482 H264Picture::Vector* ref_pic_listx) { | 528 int list, |
| 529 H264Picture::Vector* ref_pic_listx) { | |
| 483 bool ref_pic_list_modification_flag_lX; | 530 bool ref_pic_list_modification_flag_lX; |
| 484 int num_ref_idx_lX_active_minus1; | 531 int num_ref_idx_lX_active_minus1; |
| 485 media::H264ModificationOfPicNum* list_mod; | 532 const media::H264ModificationOfPicNum* list_mod; |
| 486 | 533 |
| 487 // This can process either ref_pic_list0 or ref_pic_list1, depending on | 534 // This can process either ref_pic_list0 or ref_pic_list1, depending on |
| 488 // the list argument. Set up pointers to proper list to be processed here. | 535 // the list argument. Set up pointers to proper list to be processed here. |
| 489 if (list == 0) { | 536 if (list == 0) { |
| 490 ref_pic_list_modification_flag_lX = | 537 ref_pic_list_modification_flag_lX = |
| 491 slice_hdr->ref_pic_list_modification_flag_l0; | 538 slice_hdr->ref_pic_list_modification_flag_l0; |
| 492 num_ref_idx_lX_active_minus1 = | 539 num_ref_idx_lX_active_minus1 = |
| 493 slice_hdr->num_ref_idx_l0_active_minus1; | 540 slice_hdr->num_ref_idx_l0_active_minus1; |
| 494 list_mod = slice_hdr->ref_list_l0_modifications; | 541 list_mod = slice_hdr->ref_list_l0_modifications; |
| 495 } else { | 542 } else { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 // Resize the list back to its required size. | 658 // Resize the list back to its required size. |
| 612 ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1); | 659 ref_pic_listx->resize(num_ref_idx_lX_active_minus1 + 1); |
| 613 | 660 |
| 614 return true; | 661 return true; |
| 615 } | 662 } |
| 616 | 663 |
| 617 void H264Decoder::OutputPic(scoped_refptr<H264Picture> pic) { | 664 void H264Decoder::OutputPic(scoped_refptr<H264Picture> pic) { |
| 618 DCHECK(!pic->outputted); | 665 DCHECK(!pic->outputted); |
| 619 pic->outputted = true; | 666 pic->outputted = true; |
| 620 | 667 |
| 668 if (pic->nonexisting) { | |
| 669 DVLOG(4) << "Skipping output, non-existing frame_num: " << pic->frame_num; | |
| 670 return; | |
| 671 } | |
| 672 | |
| 621 DVLOG_IF(1, pic->pic_order_cnt < last_output_poc_) | 673 DVLOG_IF(1, pic->pic_order_cnt < last_output_poc_) |
| 622 << "Outputting out of order, likely a broken stream"; | 674 << "Outputting out of order, likely a broken stream: " |
| 675 << last_output_poc_ << " -> " << pic->pic_order_cnt; | |
| 623 last_output_poc_ = pic->pic_order_cnt; | 676 last_output_poc_ = pic->pic_order_cnt; |
| 624 | 677 |
| 625 DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt; | 678 DVLOG(4) << "Posting output task for POC: " << pic->pic_order_cnt; |
| 626 accelerator_->OutputPicture(pic); | 679 accelerator_->OutputPicture(pic); |
| 627 } | 680 } |
| 628 | 681 |
| 629 void H264Decoder::ClearDPB() { | 682 void H264Decoder::ClearDPB() { |
| 630 // Clear DPB contents, marking the pictures as unused first. | 683 // Clear DPB contents, marking the pictures as unused first. |
| 631 dpb_.Clear(); | 684 dpb_.Clear(); |
| 632 last_output_poc_ = std::numeric_limits<int>::min(); | 685 last_output_poc_ = std::numeric_limits<int>::min(); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 650 DVLOG(2) << "Decoder flush"; | 703 DVLOG(2) << "Decoder flush"; |
| 651 | 704 |
| 652 if (!OutputAllRemainingPics()) | 705 if (!OutputAllRemainingPics()) |
| 653 return false; | 706 return false; |
| 654 | 707 |
| 655 ClearDPB(); | 708 ClearDPB(); |
| 656 DVLOG(2) << "Decoder flush finished"; | 709 DVLOG(2) << "Decoder flush finished"; |
| 657 return true; | 710 return true; |
| 658 } | 711 } |
| 659 | 712 |
| 660 bool H264Decoder::StartNewFrame(media::H264SliceHeader* slice_hdr) { | 713 bool H264Decoder::StartNewFrame(const media::H264SliceHeader* slice_hdr) { |
| 661 // TODO posciak: add handling of max_num_ref_frames per spec. | 714 // TODO posciak: add handling of max_num_ref_frames per spec. |
| 662 CHECK(curr_pic_.get()); | 715 CHECK(curr_pic_.get()); |
| 716 DCHECK(slice_hdr); | |
| 717 | |
| 718 curr_pps_id_ = slice_hdr->pic_parameter_set_id; | |
| 719 const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_); | |
| 720 if (!pps) | |
| 721 return false; | |
| 722 | |
| 723 curr_sps_id_ = pps->seq_parameter_set_id; | |
| 724 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); | |
| 725 if (!sps) | |
| 726 return false; | |
| 727 | |
| 728 max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4); | |
| 729 int frame_num = slice_hdr->frame_num; | |
| 730 if (slice_hdr->idr_pic_flag) | |
| 731 prev_ref_frame_num_ = 0; | |
| 732 | |
| 733 // 7.4.3 | |
| 734 if (frame_num != prev_ref_frame_num_ && | |
| 735 frame_num != (prev_ref_frame_num_ + 1) % max_frame_num_) { | |
| 736 if (!HandleFrameNumGap(frame_num)) | |
| 737 return false; | |
| 738 } | |
| 663 | 739 |
| 664 if (!InitCurrPicture(slice_hdr)) | 740 if (!InitCurrPicture(slice_hdr)) |
| 665 return false; | 741 return false; |
| 666 | 742 |
| 667 DCHECK_GT(max_frame_num_, 0); | 743 UpdatePicNums(frame_num); |
| 668 | |
| 669 UpdatePicNums(); | |
| 670 DCHECK(slice_hdr); | |
| 671 PrepareRefPicLists(slice_hdr); | 744 PrepareRefPicLists(slice_hdr); |
| 672 | 745 |
| 673 const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_); | |
| 674 DCHECK(pps); | |
| 675 const media::H264SPS* sps = parser_.GetSPS(pps->seq_parameter_set_id); | |
| 676 DCHECK(sps); | |
| 677 | |
| 678 if (!accelerator_->SubmitFrameMetadata(sps, pps, dpb_, ref_pic_list_p0_, | 746 if (!accelerator_->SubmitFrameMetadata(sps, pps, dpb_, ref_pic_list_p0_, |
| 679 ref_pic_list_b0_, ref_pic_list_b1_, | 747 ref_pic_list_b0_, ref_pic_list_b1_, |
| 680 curr_pic_.get())) | 748 curr_pic_.get())) |
| 681 return false; | 749 return false; |
| 682 | 750 |
| 683 return true; | 751 return true; |
| 684 } | 752 } |
| 685 | 753 |
| 686 bool H264Decoder::HandleMemoryManagementOps() { | 754 bool H264Decoder::HandleMemoryManagementOps(scoped_refptr<H264Picture> pic) { |
| 687 // 8.2.5.4 | 755 // 8.2.5.4 |
| 688 for (unsigned int i = 0; i < arraysize(curr_pic_->ref_pic_marking); ++i) { | 756 for (size_t i = 0; i < arraysize(pic->ref_pic_marking); ++i) { |
| 689 // Code below does not support interlaced stream (per-field pictures). | 757 // Code below does not support interlaced stream (per-field pictures). |
| 690 media::H264DecRefPicMarking* ref_pic_marking = | 758 media::H264DecRefPicMarking* ref_pic_marking = &pic->ref_pic_marking[i]; |
| 691 &curr_pic_->ref_pic_marking[i]; | |
| 692 scoped_refptr<H264Picture> to_mark; | 759 scoped_refptr<H264Picture> to_mark; |
| 693 int pic_num_x; | 760 int pic_num_x; |
| 694 | 761 |
| 695 switch (ref_pic_marking->memory_mgmnt_control_operation) { | 762 switch (ref_pic_marking->memory_mgmnt_control_operation) { |
| 696 case 0: | 763 case 0: |
| 697 // Normal end of operations' specification. | 764 // Normal end of operations' specification. |
| 698 return true; | 765 return true; |
| 699 | 766 |
| 700 case 1: | 767 case 1: |
| 701 // Mark a short term reference picture as unused so it can be removed | 768 // Mark a short term reference picture as unused so it can be removed |
| 702 // if outputted. | 769 // if outputted. |
| 703 pic_num_x = curr_pic_->pic_num - | 770 pic_num_x = |
| 704 (ref_pic_marking->difference_of_pic_nums_minus1 + 1); | 771 pic->pic_num - (ref_pic_marking->difference_of_pic_nums_minus1 + 1); |
| 705 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x); | 772 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x); |
| 706 if (to_mark) { | 773 if (to_mark) { |
| 707 to_mark->ref = false; | 774 to_mark->ref = false; |
| 708 } else { | 775 } else { |
| 709 DVLOG(1) << "Invalid short ref pic num to unmark"; | 776 DVLOG(1) << "Invalid short ref pic num to unmark"; |
| 710 return false; | 777 return false; |
| 711 } | 778 } |
| 712 break; | 779 break; |
| 713 | 780 |
| 714 case 2: | 781 case 2: |
| 715 // Mark a long term reference picture as unused so it can be removed | 782 // Mark a long term reference picture as unused so it can be removed |
| 716 // if outputted. | 783 // if outputted. |
| 717 to_mark = dpb_.GetLongRefPicByLongTermPicNum( | 784 to_mark = dpb_.GetLongRefPicByLongTermPicNum( |
| 718 ref_pic_marking->long_term_pic_num); | 785 ref_pic_marking->long_term_pic_num); |
| 719 if (to_mark) { | 786 if (to_mark) { |
| 720 to_mark->ref = false; | 787 to_mark->ref = false; |
| 721 } else { | 788 } else { |
| 722 DVLOG(1) << "Invalid long term ref pic num to unmark"; | 789 DVLOG(1) << "Invalid long term ref pic num to unmark"; |
| 723 return false; | 790 return false; |
| 724 } | 791 } |
| 725 break; | 792 break; |
| 726 | 793 |
| 727 case 3: | 794 case 3: |
| 728 // Mark a short term reference picture as long term reference. | 795 // Mark a short term reference picture as long term reference. |
| 729 pic_num_x = curr_pic_->pic_num - | 796 pic_num_x = |
| 730 (ref_pic_marking->difference_of_pic_nums_minus1 + 1); | 797 pic->pic_num - (ref_pic_marking->difference_of_pic_nums_minus1 + 1); |
| 731 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x); | 798 to_mark = dpb_.GetShortRefPicByPicNum(pic_num_x); |
| 732 if (to_mark) { | 799 if (to_mark) { |
| 733 DCHECK(to_mark->ref && !to_mark->long_term); | 800 DCHECK(to_mark->ref && !to_mark->long_term); |
| 734 to_mark->long_term = true; | 801 to_mark->long_term = true; |
| 735 to_mark->long_term_frame_idx = ref_pic_marking->long_term_frame_idx; | 802 to_mark->long_term_frame_idx = ref_pic_marking->long_term_frame_idx; |
| 736 } else { | 803 } else { |
| 737 DVLOG(1) << "Invalid short term ref pic num to mark as long ref"; | 804 DVLOG(1) << "Invalid short term ref pic num to mark as long ref"; |
| 738 return false; | 805 return false; |
| 739 } | 806 } |
| 740 break; | 807 break; |
| 741 | 808 |
| 742 case 4: { | 809 case 4: { |
| 743 // Unmark all reference pictures with long_term_frame_idx over new max. | 810 // Unmark all reference pictures with long_term_frame_idx over new max. |
| 744 max_long_term_frame_idx_ = | 811 max_long_term_frame_idx_ = |
| 745 ref_pic_marking->max_long_term_frame_idx_plus1 - 1; | 812 ref_pic_marking->max_long_term_frame_idx_plus1 - 1; |
| 746 H264Picture::Vector long_terms; | 813 H264Picture::Vector long_terms; |
| 747 dpb_.GetLongTermRefPicsAppending(&long_terms); | 814 dpb_.GetLongTermRefPicsAppending(&long_terms); |
| 748 for (size_t i = 0; i < long_terms.size(); ++i) { | 815 for (size_t i = 0; i < long_terms.size(); ++i) { |
| 749 scoped_refptr<H264Picture>& pic = long_terms[i]; | 816 scoped_refptr<H264Picture>& long_term_pic = long_terms[i]; |
| 750 DCHECK(pic->ref && pic->long_term); | 817 DCHECK(long_term_pic->ref && long_term_pic->long_term); |
| 751 // Ok to cast, max_long_term_frame_idx is much smaller than 16bit. | 818 // Ok to cast, max_long_term_frame_idx is much smaller than 16bit. |
| 752 if (pic->long_term_frame_idx > | 819 if (long_term_pic->long_term_frame_idx > |
| 753 static_cast<int>(max_long_term_frame_idx_)) | 820 static_cast<int>(max_long_term_frame_idx_)) |
| 754 pic->ref = false; | 821 long_term_pic->ref = false; |
| 755 } | 822 } |
| 756 break; | 823 break; |
| 757 } | 824 } |
| 758 | 825 |
| 759 case 5: | 826 case 5: |
| 760 // Unmark all reference pictures. | 827 // Unmark all reference pictures. |
| 761 dpb_.MarkAllUnusedForRef(); | 828 dpb_.MarkAllUnusedForRef(); |
| 762 max_long_term_frame_idx_ = -1; | 829 max_long_term_frame_idx_ = -1; |
| 763 curr_pic_->mem_mgmt_5 = true; | 830 pic->mem_mgmt_5 = true; |
| 764 break; | 831 break; |
| 765 | 832 |
| 766 case 6: { | 833 case 6: { |
| 767 // Replace long term reference pictures with current picture. | 834 // Replace long term reference pictures with current picture. |
| 768 // First unmark if any existing with this long_term_frame_idx... | 835 // First unmark if any existing with this long_term_frame_idx... |
| 769 H264Picture::Vector long_terms; | 836 H264Picture::Vector long_terms; |
| 770 dpb_.GetLongTermRefPicsAppending(&long_terms); | 837 dpb_.GetLongTermRefPicsAppending(&long_terms); |
| 771 for (size_t i = 0; i < long_terms.size(); ++i) { | 838 for (size_t i = 0; i < long_terms.size(); ++i) { |
| 772 scoped_refptr<H264Picture>& pic = long_terms[i]; | 839 scoped_refptr<H264Picture>& long_term_pic = long_terms[i]; |
| 773 DCHECK(pic->ref && pic->long_term); | 840 DCHECK(long_term_pic->ref && long_term_pic->long_term); |
| 774 // Ok to cast, long_term_frame_idx is much smaller than 16bit. | 841 // Ok to cast, long_term_frame_idx is much smaller than 16bit. |
| 775 if (pic->long_term_frame_idx == | 842 if (long_term_pic->long_term_frame_idx == |
| 776 static_cast<int>(ref_pic_marking->long_term_frame_idx)) | 843 static_cast<int>(ref_pic_marking->long_term_frame_idx)) |
| 777 pic->ref = false; | 844 long_term_pic->ref = false; |
| 778 } | 845 } |
| 779 | 846 |
| 780 // and mark the current one instead. | 847 // and mark the current one instead. |
| 781 curr_pic_->ref = true; | 848 pic->ref = true; |
| 782 curr_pic_->long_term = true; | 849 pic->long_term = true; |
| 783 curr_pic_->long_term_frame_idx = ref_pic_marking->long_term_frame_idx; | 850 pic->long_term_frame_idx = ref_pic_marking->long_term_frame_idx; |
| 784 break; | 851 break; |
| 785 } | 852 } |
| 786 | 853 |
| 787 default: | 854 default: |
| 788 // Would indicate a bug in parser. | 855 // Would indicate a bug in parser. |
| 789 NOTREACHED(); | 856 NOTREACHED(); |
| 790 } | 857 } |
| 791 } | 858 } |
| 792 | 859 |
| 793 return true; | 860 return true; |
| 794 } | 861 } |
| 795 | 862 |
| 796 // This method ensures that DPB does not overflow, either by removing | 863 // This method ensures that DPB does not overflow, either by removing |
| 797 // reference pictures as specified in the stream, or using a sliding window | 864 // reference pictures as specified in the stream, or using a sliding window |
| 798 // procedure to remove the oldest one. | 865 // procedure to remove the oldest one. |
| 799 // It also performs marking and unmarking pictures as reference. | 866 // It also performs marking and unmarking pictures as reference. |
| 800 // See spac 8.2.5.1. | 867 // See spac 8.2.5.1. |
| 801 void H264Decoder::ReferencePictureMarking() { | 868 bool H264Decoder::ReferencePictureMarking(scoped_refptr<H264Picture> pic) { |
| 802 if (curr_pic_->idr) { | 869 // If the current picture is an IDR, all reference pictures are unmarked. |
| 803 // If current picture is an IDR, all reference pictures are unmarked. | 870 if (pic->idr) { |
| 804 dpb_.MarkAllUnusedForRef(); | 871 dpb_.MarkAllUnusedForRef(); |
| 805 | 872 |
| 806 if (curr_pic_->long_term_reference_flag) { | 873 if (pic->long_term_reference_flag) { |
| 807 curr_pic_->long_term = true; | 874 pic->long_term = true; |
| 808 curr_pic_->long_term_frame_idx = 0; | 875 pic->long_term_frame_idx = 0; |
| 809 max_long_term_frame_idx_ = 0; | 876 max_long_term_frame_idx_ = 0; |
| 810 } else { | 877 } else { |
| 811 curr_pic_->long_term = false; | 878 pic->long_term = false; |
| 812 max_long_term_frame_idx_ = -1; | 879 max_long_term_frame_idx_ = -1; |
| 813 } | 880 } |
| 881 | |
| 882 return true; | |
| 883 } | |
| 884 | |
| 885 // Not an IDR. If the stream contains instructions on how to discard pictures | |
| 886 // from DPB and how to mark/unmark existing reference pictures, do so. | |
| 887 // Otherwise, fall back to default sliding window process. | |
| 888 if (pic->adaptive_ref_pic_marking_mode_flag) { | |
| 889 DCHECK(!pic->nonexisting); | |
| 890 return HandleMemoryManagementOps(pic); | |
| 814 } else { | 891 } else { |
| 815 if (!curr_pic_->adaptive_ref_pic_marking_mode_flag) { | 892 return SlidingWindowPictureMarking(); |
| 816 // If non-IDR, and the stream does not indicate what we should do to | |
| 817 // ensure DPB doesn't overflow, discard oldest picture. | |
| 818 // See spec 8.2.5.3. | |
| 819 if (curr_pic_->field == H264Picture::FIELD_NONE) { | |
| 820 DCHECK_LE( | |
| 821 dpb_.CountRefPics(), | |
| 822 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames, 1)); | |
| 823 if (dpb_.CountRefPics() == | |
| 824 std::max<int>(parser_.GetSPS(curr_sps_id_)->max_num_ref_frames, | |
| 825 1)) { | |
| 826 // Max number of reference pics reached, | |
| 827 // need to remove one of the short term ones. | |
| 828 // Find smallest frame_num_wrap short reference picture and mark | |
| 829 // it as unused. | |
| 830 scoped_refptr<H264Picture> to_unmark = | |
| 831 dpb_.GetLowestFrameNumWrapShortRefPic(); | |
| 832 if (to_unmark == NULL) { | |
| 833 DVLOG(1) << "Couldn't find a short ref picture to unmark"; | |
| 834 return; | |
| 835 } | |
| 836 to_unmark->ref = false; | |
| 837 } | |
| 838 } else { | |
| 839 // Shouldn't get here. | |
| 840 DVLOG(1) << "Interlaced video not supported."; | |
| 841 } | |
| 842 } else { | |
| 843 // Stream has instructions how to discard pictures from DPB and how | |
| 844 // to mark/unmark existing reference pictures. Do it. | |
| 845 // Spec 8.2.5.4. | |
| 846 if (curr_pic_->field == H264Picture::FIELD_NONE) { | |
| 847 HandleMemoryManagementOps(); | |
| 848 } else { | |
| 849 // Shouldn't get here. | |
| 850 DVLOG(1) << "Interlaced video not supported."; | |
| 851 } | |
| 852 } | |
| 853 } | 893 } |
| 854 } | 894 } |
| 855 | 895 |
| 856 bool H264Decoder::FinishPicture() { | 896 bool H264Decoder::SlidingWindowPictureMarking() { |
| 857 DCHECK(curr_pic_.get()); | 897 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); |
| 898 if (!sps) | |
| 899 return false; | |
| 858 | 900 |
| 859 // Finish processing previous picture. | 901 // 8.2.5.3. Ensure the DPB doesn't overflow by discarding the oldest picture. |
| 860 // Start by storing previous reference picture data for later use, | 902 int num_ref_pics = dpb_.CountRefPics(); |
| 861 // if picture being finished is a reference picture. | 903 DCHECK_LE(num_ref_pics, std::max<int>(sps->max_num_ref_frames, 1)); |
| 862 if (curr_pic_->ref) { | 904 if (num_ref_pics == std::max<int>(sps->max_num_ref_frames, 1)) { |
| 863 ReferencePictureMarking(); | 905 // Max number of reference pics reached, need to remove one of the short |
| 864 prev_ref_has_memmgmnt5_ = curr_pic_->mem_mgmt_5; | 906 // term ones. Find smallest frame_num_wrap short reference picture and mark |
| 865 prev_ref_top_field_order_cnt_ = curr_pic_->top_field_order_cnt; | 907 // it as unused. |
| 866 prev_ref_pic_order_cnt_msb_ = curr_pic_->pic_order_cnt_msb; | 908 scoped_refptr<H264Picture> to_unmark = |
| 867 prev_ref_pic_order_cnt_lsb_ = curr_pic_->pic_order_cnt_lsb; | 909 dpb_.GetLowestFrameNumWrapShortRefPic(); |
| 868 prev_ref_field_ = curr_pic_->field; | 910 if (!to_unmark) { |
| 911 DVLOG(1) << "Couldn't find a short ref picture to unmark"; | |
| 912 return false; | |
| 913 } | |
| 914 | |
| 915 to_unmark->ref = false; | |
| 869 } | 916 } |
| 870 prev_has_memmgmnt5_ = curr_pic_->mem_mgmt_5; | 917 |
| 871 prev_frame_num_offset_ = curr_pic_->frame_num_offset; | 918 return true; |
| 919 } | |
| 920 | |
| 921 bool H264Decoder::FinishPicture(scoped_refptr<H264Picture> pic) { | |
| 922 // Finish processing the picture. | |
| 923 // Start by storing previous picture data for later use. | |
| 924 if (pic->ref) { | |
| 925 ReferencePictureMarking(pic); | |
| 926 prev_ref_has_memmgmnt5_ = pic->mem_mgmt_5; | |
| 927 prev_ref_top_field_order_cnt_ = pic->top_field_order_cnt; | |
| 928 prev_ref_pic_order_cnt_msb_ = pic->pic_order_cnt_msb; | |
| 929 prev_ref_pic_order_cnt_lsb_ = pic->pic_order_cnt_lsb; | |
| 930 prev_ref_field_ = pic->field; | |
| 931 prev_ref_frame_num_ = pic->frame_num; | |
| 932 } | |
| 933 prev_frame_num_ = pic->frame_num; | |
| 934 prev_has_memmgmnt5_ = pic->mem_mgmt_5; | |
| 935 prev_frame_num_offset_ = pic->frame_num_offset; | |
| 872 | 936 |
| 873 // Remove unused (for reference or later output) pictures from DPB, marking | 937 // Remove unused (for reference or later output) pictures from DPB, marking |
| 874 // them as such. | 938 // them as such. |
| 875 dpb_.DeleteUnused(); | 939 dpb_.DeleteUnused(); |
| 876 | 940 |
| 877 DVLOG(4) << "Finishing picture, entries in DPB: " << dpb_.size(); | 941 DVLOG(4) << "Finishing picture frame_num: " << pic->frame_num |
| 942 << ", entries in DPB: " << dpb_.size(); | |
| 878 | 943 |
| 879 // Whatever happens below, curr_pic_ will stop managing the pointer to the | 944 // The ownership of pic will either be transferred to DPB - if the picture is |
| 880 // picture after this. The ownership will either be transferred to DPB, if | 945 // still needed (for output and/or reference) - or we will release it |
| 881 // the image is still needed (for output and/or reference), or the memory | 946 // immediately if we manage to output it here and won't have to store it for |
| 882 // will be released if we manage to output it here without having to store | 947 // future reference. |
| 883 // it for future reference. | |
| 884 scoped_refptr<H264Picture> pic = curr_pic_; | |
| 885 curr_pic_ = nullptr; | |
| 886 | 948 |
| 887 // Get all pictures that haven't been outputted yet. | 949 // Get all pictures that haven't been outputted yet. |
| 888 H264Picture::Vector not_outputted; | 950 H264Picture::Vector not_outputted; |
| 889 dpb_.GetNotOutputtedPicsAppending(¬_outputted); | 951 dpb_.GetNotOutputtedPicsAppending(¬_outputted); |
| 890 // Include the one we've just decoded. | 952 // Include the one we've just decoded. |
| 891 not_outputted.push_back(pic); | 953 not_outputted.push_back(pic); |
| 892 | 954 |
| 893 // Sort in output order. | 955 // Sort in output order. |
| 894 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); | 956 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); |
| 895 | 957 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 997 break; | 1059 break; |
| 998 } | 1060 } |
| 999 } else { | 1061 } else { |
| 1000 max_num_reorder_frames_ = dpb_.max_num_pics(); | 1062 max_num_reorder_frames_ = dpb_.max_num_pics(); |
| 1001 } | 1063 } |
| 1002 | 1064 |
| 1003 return true; | 1065 return true; |
| 1004 } | 1066 } |
| 1005 | 1067 |
| 1006 bool H264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { | 1068 bool H264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { |
| 1069 DVLOG(4) << "Processing SPS id:" << sps_id; | |
| 1070 | |
| 1007 const media::H264SPS* sps = parser_.GetSPS(sps_id); | 1071 const media::H264SPS* sps = parser_.GetSPS(sps_id); |
| 1008 DCHECK(sps); | 1072 if (!sps) |
| 1009 DVLOG(4) << "Processing SPS"; | 1073 return false; |
|
xhwang
2015/10/12 18:01:17
In what case could this fail? (wondering why we re
Pawel Osciak
2015/10/13 01:23:22
Previously we were using std::map::operator[], whi
| |
| 1010 | 1074 |
| 1011 *need_new_buffers = false; | 1075 *need_new_buffers = false; |
| 1012 | 1076 |
| 1013 if (sps->frame_mbs_only_flag == 0) { | 1077 if (sps->frame_mbs_only_flag == 0) { |
| 1014 DVLOG(1) << "frame_mbs_only_flag != 1 not supported"; | 1078 DVLOG(1) << "frame_mbs_only_flag != 1 not supported"; |
| 1015 return false; | 1079 return false; |
| 1016 } | 1080 } |
| 1017 | 1081 |
| 1018 if (sps->gaps_in_frame_num_value_allowed_flag) { | |
| 1019 DVLOG(1) << "Gaps in frame numbers not supported"; | |
| 1020 return false; | |
| 1021 } | |
| 1022 | |
| 1023 curr_sps_id_ = sps->seq_parameter_set_id; | |
| 1024 | |
| 1025 // Calculate picture height/width in macroblocks and pixels | 1082 // Calculate picture height/width in macroblocks and pixels |
| 1026 // (spec 7.4.2.1.1, 7.4.3). | 1083 // (spec 7.4.2.1.1, 7.4.3). |
| 1027 int width_mb = sps->pic_width_in_mbs_minus1 + 1; | 1084 int width_mb = sps->pic_width_in_mbs_minus1 + 1; |
| 1028 int height_mb = (2 - sps->frame_mbs_only_flag) * | 1085 int height_mb = (2 - sps->frame_mbs_only_flag) * |
| 1029 (sps->pic_height_in_map_units_minus1 + 1); | 1086 (sps->pic_height_in_map_units_minus1 + 1); |
| 1030 | 1087 |
| 1031 gfx::Size new_pic_size(16 * width_mb, 16 * height_mb); | 1088 gfx::Size new_pic_size(16 * width_mb, 16 * height_mb); |
| 1032 if (new_pic_size.IsEmpty()) { | 1089 if (new_pic_size.IsEmpty()) { |
| 1033 DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString(); | 1090 DVLOG(1) << "Invalid picture size: " << new_pic_size.ToString(); |
| 1034 return false; | 1091 return false; |
| 1035 } | 1092 } |
| 1036 | 1093 |
| 1037 if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) { | 1094 if (!pic_size_.IsEmpty() && new_pic_size == pic_size_) { |
| 1038 // Already have surfaces and this SPS keeps the same resolution, | 1095 // Already have surfaces and this SPS keeps the same resolution, |
| 1039 // no need to request a new set. | 1096 // no need to request a new set. |
| 1040 return true; | 1097 return true; |
| 1041 } | 1098 } |
| 1042 | 1099 |
| 1043 pic_size_ = new_pic_size; | 1100 pic_size_ = new_pic_size; |
| 1044 DVLOG(1) << "New picture size: " << pic_size_.ToString(); | 1101 DVLOG(1) << "New picture size: " << pic_size_.ToString(); |
| 1045 | 1102 |
| 1046 max_pic_order_cnt_lsb_ = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); | |
| 1047 max_frame_num_ = 1 << (sps->log2_max_frame_num_minus4 + 4); | |
| 1048 | |
| 1049 int level = sps->level_idc; | 1103 int level = sps->level_idc; |
| 1050 int max_dpb_mbs = LevelToMaxDpbMbs(level); | 1104 int max_dpb_mbs = LevelToMaxDpbMbs(level); |
| 1051 if (max_dpb_mbs == 0) | 1105 if (max_dpb_mbs == 0) |
| 1052 return false; | 1106 return false; |
| 1053 | 1107 |
| 1054 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb), | 1108 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb), |
| 1055 static_cast<int>(H264DPB::kDPBMaxSize)); | 1109 static_cast<int>(H264DPB::kDPBMaxSize)); |
| 1056 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size; | 1110 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size; |
| 1057 if (max_dpb_size == 0) { | 1111 if (max_dpb_size == 0) { |
| 1058 DVLOG(1) << "Invalid DPB Size"; | 1112 DVLOG(1) << "Invalid DPB Size"; |
| 1059 return false; | 1113 return false; |
| 1060 } | 1114 } |
| 1061 | 1115 |
| 1062 dpb_.set_max_num_pics(max_dpb_size); | 1116 dpb_.set_max_num_pics(max_dpb_size); |
| 1063 | 1117 |
| 1064 if (!UpdateMaxNumReorderFrames(sps)) | 1118 if (!UpdateMaxNumReorderFrames(sps)) |
| 1065 return false; | 1119 return false; |
| 1066 DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_; | 1120 DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_; |
| 1067 | 1121 |
| 1068 *need_new_buffers = true; | 1122 *need_new_buffers = true; |
| 1069 return true; | 1123 return true; |
| 1070 } | 1124 } |
| 1071 | 1125 |
| 1072 bool H264Decoder::ProcessPPS(int pps_id) { | |
| 1073 const media::H264PPS* pps = parser_.GetPPS(pps_id); | |
| 1074 DCHECK(pps); | |
| 1075 | |
| 1076 curr_pps_id_ = pps->pic_parameter_set_id; | |
| 1077 | |
| 1078 return true; | |
| 1079 } | |
| 1080 | |
| 1081 bool H264Decoder::FinishPrevFrameIfPresent() { | 1126 bool H264Decoder::FinishPrevFrameIfPresent() { |
| 1082 // If we already have a frame waiting to be decoded, decode it and finish. | 1127 // If we already have a frame waiting to be decoded, decode it and finish. |
| 1083 if (curr_pic_ != NULL) { | 1128 if (curr_pic_ != NULL) { |
| 1084 if (!DecodePicture()) | 1129 if (!DecodePicture()) |
| 1085 return false; | 1130 return false; |
| 1086 return FinishPicture(); | 1131 |
| 1132 scoped_refptr<H264Picture> pic = curr_pic_; | |
| 1133 curr_pic_ = nullptr; | |
| 1134 return FinishPicture(pic); | |
| 1087 } | 1135 } |
| 1088 | 1136 |
| 1089 return true; | 1137 return true; |
| 1090 } | 1138 } |
| 1091 | 1139 |
| 1092 bool H264Decoder::PreprocessSlice(media::H264SliceHeader* slice_hdr) { | 1140 bool H264Decoder::HandleFrameNumGap(int frame_num) { |
| 1093 prev_frame_num_ = frame_num_; | 1141 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); |
| 1094 frame_num_ = slice_hdr->frame_num; | 1142 if (!sps) |
| 1143 return false; | |
| 1095 | 1144 |
| 1096 if (prev_frame_num_ > 0 && prev_frame_num_ < frame_num_ - 1) { | 1145 if (!sps->gaps_in_frame_num_value_allowed_flag) { |
| 1097 DVLOG(1) << "Gap in frame_num!"; | 1146 DVLOG(1) << "Invalid frame_num: " << frame_num; |
| 1098 return false; | 1147 return false; |
| 1099 } | 1148 } |
| 1100 | 1149 |
| 1150 DVLOG(2) << "Handling frame_num gap: " << prev_ref_frame_num_ << "->" | |
| 1151 << frame_num; | |
| 1152 | |
| 1153 // 7.4.3/7-23 | |
| 1154 int unused_short_term_frame_num = (prev_ref_frame_num_ + 1) % max_frame_num_; | |
| 1155 while (unused_short_term_frame_num != frame_num) { | |
| 1156 scoped_refptr<H264Picture> pic = new H264Picture(); | |
| 1157 if (!InitNonexistingPicture(pic, unused_short_term_frame_num)) | |
|
xhwang
2015/10/12 18:01:17
Can we follow the RAII (https://en.wikipedia.org/w
Pawel Osciak
2015/10/13 01:23:22
My intention with H264Picture was to keep it as PO
| |
| 1158 return false; | |
| 1159 | |
| 1160 UpdatePicNums(unused_short_term_frame_num); | |
| 1161 | |
| 1162 if (!FinishPicture(pic)) | |
| 1163 return false; | |
| 1164 | |
| 1165 unused_short_term_frame_num++; | |
| 1166 unused_short_term_frame_num %= max_frame_num_; | |
| 1167 } | |
| 1168 | |
| 1169 return true; | |
| 1170 } | |
| 1171 | |
| 1172 bool H264Decoder::IsNewPrimaryCodedPicture( | |
| 1173 const media::H264SliceHeader* slice_hdr) const { | |
| 1174 if (!curr_pic_) | |
| 1175 return true; | |
| 1176 | |
| 1177 // 7.4.1.2.4, assumes non-interlaced. | |
| 1178 if (slice_hdr->frame_num != curr_pic_->frame_num || | |
| 1179 slice_hdr->pic_parameter_set_id != curr_pps_id_ || | |
| 1180 slice_hdr->nal_ref_idc != curr_pic_->nal_ref_idc || | |
| 1181 slice_hdr->idr_pic_flag != curr_pic_->idr || | |
| 1182 (slice_hdr->idr_pic_flag && | |
| 1183 slice_hdr->idr_pic_id != curr_pic_->idr_pic_id)) | |
| 1184 return true; | |
| 1185 | |
| 1186 const media::H264SPS* sps = parser_.GetSPS(curr_sps_id_); | |
| 1187 if (!sps) | |
| 1188 return false; | |
| 1189 | |
| 1190 if (sps->pic_order_cnt_type == curr_pic_->pic_order_cnt_type) { | |
| 1191 if (curr_pic_->pic_order_cnt_type == 0) { | |
| 1192 if (slice_hdr->pic_order_cnt_lsb != curr_pic_->pic_order_cnt_lsb || | |
| 1193 slice_hdr->delta_pic_order_cnt_bottom != | |
| 1194 curr_pic_->delta_pic_order_cnt_bottom) | |
| 1195 return true; | |
| 1196 } else if (curr_pic_->pic_order_cnt_type == 1) { | |
| 1197 if (slice_hdr->delta_pic_order_cnt0 != curr_pic_->delta_pic_order_cnt0 || | |
| 1198 slice_hdr->delta_pic_order_cnt1 != curr_pic_->delta_pic_order_cnt1) | |
| 1199 return true; | |
| 1200 } | |
| 1201 } | |
| 1202 | |
| 1203 return false; | |
| 1204 } | |
| 1205 | |
| 1206 bool H264Decoder::PreprocessCurrentSlice() { | |
| 1207 const media::H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); | |
| 1208 DCHECK(slice_hdr); | |
| 1209 | |
| 1210 if (IsNewPrimaryCodedPicture(slice_hdr)) { | |
| 1211 // New picture, so first finish the previous one before processing it. | |
| 1212 if (!FinishPrevFrameIfPresent()) | |
| 1213 return false; | |
| 1214 | |
| 1215 DCHECK(!curr_pic_); | |
| 1216 | |
| 1217 if (slice_hdr->first_mb_in_slice != 0) { | |
| 1218 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " | |
| 1219 << slice_hdr->first_mb_in_slice; | |
| 1220 return false; | |
| 1221 } | |
| 1222 | |
| 1223 // If the new picture is an IDR, flush DPB. | |
| 1224 if (slice_hdr->idr_pic_flag) { | |
| 1225 // Output all remaining pictures, unless we are explicitly instructed | |
| 1226 // not to do so. | |
| 1227 if (!slice_hdr->no_output_of_prior_pics_flag) { | |
| 1228 if (!Flush()) | |
| 1229 return false; | |
| 1230 } | |
| 1231 dpb_.Clear(); | |
| 1232 last_output_poc_ = std::numeric_limits<int>::min(); | |
| 1233 } | |
| 1234 } | |
| 1235 | |
| 1236 return true; | |
| 1237 } | |
| 1238 | |
| 1239 bool H264Decoder::ProcessCurrentSlice() { | |
| 1240 DCHECK(curr_pic_); | |
| 1241 | |
| 1242 const media::H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); | |
| 1243 DCHECK(slice_hdr); | |
| 1244 | |
| 1101 if (slice_hdr->field_pic_flag == 0) | 1245 if (slice_hdr->field_pic_flag == 0) |
| 1102 max_pic_num_ = max_frame_num_; | 1246 max_pic_num_ = max_frame_num_; |
| 1103 else | 1247 else |
| 1104 max_pic_num_ = 2 * max_frame_num_; | 1248 max_pic_num_ = 2 * max_frame_num_; |
| 1105 | 1249 |
| 1106 // TODO posciak: switch to new picture detection per 7.4.1.2.4. | |
| 1107 if (curr_pic_ != NULL && slice_hdr->first_mb_in_slice != 0) { | |
| 1108 // More slice data of the current picture. | |
| 1109 return true; | |
| 1110 } else { | |
| 1111 // A new frame, so first finish the previous one before processing it... | |
| 1112 if (!FinishPrevFrameIfPresent()) | |
| 1113 return false; | |
| 1114 } | |
| 1115 | |
| 1116 // If the new frame is an IDR, output what's left to output and clear DPB | |
| 1117 if (slice_hdr->idr_pic_flag) { | |
| 1118 // (unless we are explicitly instructed not to do so). | |
| 1119 if (!slice_hdr->no_output_of_prior_pics_flag) { | |
| 1120 // Output DPB contents. | |
| 1121 if (!Flush()) | |
| 1122 return false; | |
| 1123 } | |
| 1124 dpb_.Clear(); | |
| 1125 last_output_poc_ = std::numeric_limits<int>::min(); | |
| 1126 } | |
| 1127 | |
| 1128 return true; | |
| 1129 } | |
| 1130 | |
| 1131 bool H264Decoder::ProcessSlice(media::H264SliceHeader* slice_hdr) { | |
| 1132 DCHECK(curr_pic_.get()); | |
| 1133 H264Picture::Vector ref_pic_list0, ref_pic_list1; | 1250 H264Picture::Vector ref_pic_list0, ref_pic_list1; |
| 1134 | |
| 1135 if (!ModifyReferencePicLists(slice_hdr, &ref_pic_list0, &ref_pic_list1)) | 1251 if (!ModifyReferencePicLists(slice_hdr, &ref_pic_list0, &ref_pic_list1)) |
| 1136 return false; | 1252 return false; |
| 1137 | 1253 |
| 1138 const media::H264PPS* pps = parser_.GetPPS(slice_hdr->pic_parameter_set_id); | 1254 const media::H264PPS* pps = parser_.GetPPS(curr_pps_id_); |
| 1139 DCHECK(pps); | 1255 if (!pps) |
| 1256 return false; | |
| 1140 | 1257 |
| 1141 if (!accelerator_->SubmitSlice(pps, slice_hdr, ref_pic_list0, ref_pic_list1, | 1258 if (!accelerator_->SubmitSlice(pps, slice_hdr, ref_pic_list0, ref_pic_list1, |
| 1142 curr_pic_.get(), slice_hdr->nalu_data, | 1259 curr_pic_.get(), slice_hdr->nalu_data, |
| 1143 slice_hdr->nalu_size)) | 1260 slice_hdr->nalu_size)) |
| 1144 return false; | 1261 return false; |
| 1145 | 1262 |
| 1146 curr_slice_hdr_.reset(); | |
| 1147 return true; | 1263 return true; |
| 1148 } | 1264 } |
| 1149 | 1265 |
| 1150 #define SET_ERROR_AND_RETURN() \ | 1266 #define SET_ERROR_AND_RETURN() \ |
| 1151 do { \ | 1267 do { \ |
| 1152 DVLOG(1) << "Error during decode"; \ | 1268 DVLOG(1) << "Error during decode"; \ |
| 1153 state_ = kError; \ | 1269 state_ = kError; \ |
| 1154 return H264Decoder::kDecodeError; \ | 1270 return H264Decoder::kDecodeError; \ |
| 1155 } while (0) | 1271 } while (0) |
| 1156 | 1272 |
| 1157 void H264Decoder::SetStream(const uint8_t* ptr, size_t size) { | 1273 void H264Decoder::SetStream(const uint8_t* ptr, size_t size) { |
| 1158 DCHECK(ptr); | 1274 DCHECK(ptr); |
| 1159 DCHECK(size); | 1275 DCHECK(size); |
| 1160 | 1276 |
| 1161 DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size; | 1277 DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size; |
| 1162 parser_.SetStream(ptr, size); | 1278 parser_.SetStream(ptr, size); |
| 1163 } | 1279 } |
| 1164 | 1280 |
| 1165 H264Decoder::DecodeResult H264Decoder::Decode() { | 1281 H264Decoder::DecodeResult H264Decoder::Decode() { |
| 1166 DCHECK_NE(state_, kError); | 1282 if (state_ == kError) { |
| 1283 DVLOG(1) << "Decoder in error state"; | |
| 1284 return kDecodeError; | |
| 1285 } | |
| 1167 | 1286 |
| 1168 while (1) { | 1287 while (1) { |
| 1169 media::H264Parser::Result par_res; | 1288 media::H264Parser::Result par_res; |
| 1170 | 1289 |
| 1171 if (!curr_nalu_) { | 1290 if (!curr_nalu_) { |
| 1172 curr_nalu_.reset(new media::H264NALU()); | 1291 curr_nalu_.reset(new media::H264NALU()); |
| 1173 par_res = parser_.AdvanceToNextNALU(curr_nalu_.get()); | 1292 par_res = parser_.AdvanceToNextNALU(curr_nalu_.get()); |
| 1174 if (par_res == media::H264Parser::kEOStream) | 1293 if (par_res == media::H264Parser::kEOStream) |
| 1175 return kRanOutOfStreamData; | 1294 return kRanOutOfStreamData; |
| 1176 else if (par_res != media::H264Parser::kOk) | 1295 else if (par_res != media::H264Parser::kOk) |
| 1177 SET_ERROR_AND_RETURN(); | 1296 SET_ERROR_AND_RETURN(); |
| 1297 | |
| 1298 DVLOG(4) << "New NALU: " << static_cast<int>(curr_nalu_->nal_unit_type); | |
| 1178 } | 1299 } |
| 1179 | 1300 |
| 1180 DVLOG(4) << "NALU found: " << static_cast<int>(curr_nalu_->nal_unit_type); | |
| 1181 | |
| 1182 switch (curr_nalu_->nal_unit_type) { | 1301 switch (curr_nalu_->nal_unit_type) { |
| 1183 case media::H264NALU::kNonIDRSlice: | 1302 case media::H264NALU::kNonIDRSlice: |
| 1184 // We can't resume from a non-IDR slice. | 1303 // We can't resume from a non-IDR slice. |
| 1185 if (state_ != kDecoding) | 1304 if (state_ != kDecoding) |
| 1186 break; | 1305 break; |
| 1187 // else fallthrough | 1306 // else fallthrough |
| 1188 case media::H264NALU::kIDRSlice: { | 1307 case media::H264NALU::kIDRSlice: { |
| 1189 // TODO(posciak): the IDR may require an SPS that we don't have | 1308 // TODO(posciak): the IDR may require an SPS that we don't have |
| 1190 // available. For now we'd fail if that happens, but ideally we'd like | 1309 // available. For now we'd fail if that happens, but ideally we'd like |
| 1191 // to keep going until the next SPS in the stream. | 1310 // to keep going until the next SPS in the stream. |
| 1192 if (state_ == kNeedStreamMetadata) { | 1311 if (state_ == kNeedStreamMetadata) { |
| 1193 // We need an SPS, skip this IDR and keep looking. | 1312 // We need an SPS, skip this IDR and keep looking. |
| 1194 break; | 1313 break; |
| 1195 } | 1314 } |
| 1196 | 1315 |
| 1197 // If after reset, we should be able to recover from an IDR. | 1316 // If after reset, we should be able to recover from an IDR. |
| 1317 state_ = kDecoding; | |
| 1318 | |
| 1198 if (!curr_slice_hdr_) { | 1319 if (!curr_slice_hdr_) { |
| 1199 curr_slice_hdr_.reset(new media::H264SliceHeader()); | 1320 curr_slice_hdr_.reset(new media::H264SliceHeader()); |
| 1200 par_res = | 1321 par_res = |
| 1201 parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get()); | 1322 parser_.ParseSliceHeader(*curr_nalu_, curr_slice_hdr_.get()); |
| 1202 if (par_res != media::H264Parser::kOk) | 1323 if (par_res != media::H264Parser::kOk) |
| 1203 SET_ERROR_AND_RETURN(); | 1324 SET_ERROR_AND_RETURN(); |
| 1204 | 1325 |
| 1205 if (!PreprocessSlice(curr_slice_hdr_.get())) | 1326 if (!PreprocessCurrentSlice()) |
| 1206 SET_ERROR_AND_RETURN(); | 1327 SET_ERROR_AND_RETURN(); |
| 1207 } | 1328 } |
| 1208 | 1329 |
| 1209 if (!curr_pic_) { | 1330 if (!curr_pic_) { |
| 1210 // New picture/finished previous one, try to start a new one | 1331 // New picture/finished previous one, try to start a new one |
| 1211 // or tell the client we need more surfaces. | 1332 // or tell the client we need more surfaces. |
| 1212 curr_pic_ = accelerator_->CreateH264Picture(); | 1333 curr_pic_ = accelerator_->CreateH264Picture(); |
| 1213 if (!curr_pic_) | 1334 if (!curr_pic_) |
| 1214 return kRanOutOfSurfaces; | 1335 return kRanOutOfSurfaces; |
| 1215 | 1336 |
| 1216 if (!StartNewFrame(curr_slice_hdr_.get())) | 1337 if (!StartNewFrame(curr_slice_hdr_.get())) |
| 1217 SET_ERROR_AND_RETURN(); | 1338 SET_ERROR_AND_RETURN(); |
| 1218 } | 1339 } |
| 1219 | 1340 |
| 1220 if (!ProcessSlice(curr_slice_hdr_.get())) | 1341 if (!ProcessCurrentSlice()) |
| 1221 SET_ERROR_AND_RETURN(); | 1342 SET_ERROR_AND_RETURN(); |
| 1222 | 1343 |
| 1223 state_ = kDecoding; | 1344 curr_slice_hdr_.reset(); |
| 1224 break; | 1345 break; |
| 1225 } | 1346 } |
| 1226 | 1347 |
| 1227 case media::H264NALU::kSPS: { | 1348 case media::H264NALU::kSPS: { |
| 1228 int sps_id; | 1349 int sps_id; |
| 1229 | 1350 |
| 1230 if (!FinishPrevFrameIfPresent()) | 1351 if (!FinishPrevFrameIfPresent()) |
| 1231 SET_ERROR_AND_RETURN(); | 1352 SET_ERROR_AND_RETURN(); |
| 1232 | 1353 |
| 1233 par_res = parser_.ParseSPS(&sps_id); | 1354 par_res = parser_.ParseSPS(&sps_id); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1261 | 1382 |
| 1262 int pps_id; | 1383 int pps_id; |
| 1263 | 1384 |
| 1264 if (!FinishPrevFrameIfPresent()) | 1385 if (!FinishPrevFrameIfPresent()) |
| 1265 SET_ERROR_AND_RETURN(); | 1386 SET_ERROR_AND_RETURN(); |
| 1266 | 1387 |
| 1267 par_res = parser_.ParsePPS(&pps_id); | 1388 par_res = parser_.ParsePPS(&pps_id); |
| 1268 if (par_res != media::H264Parser::kOk) | 1389 if (par_res != media::H264Parser::kOk) |
| 1269 SET_ERROR_AND_RETURN(); | 1390 SET_ERROR_AND_RETURN(); |
| 1270 | 1391 |
| 1271 if (!ProcessPPS(pps_id)) | |
| 1272 SET_ERROR_AND_RETURN(); | |
| 1273 break; | 1392 break; |
| 1274 } | 1393 } |
| 1275 | 1394 |
| 1276 default: | 1395 default: |
| 1277 DVLOG(4) << "Skipping NALU type: " << curr_nalu_->nal_unit_type; | 1396 DVLOG(4) << "Skipping NALU type: " << curr_nalu_->nal_unit_type; |
| 1278 break; | 1397 break; |
| 1279 } | 1398 } |
| 1280 | 1399 |
| 1281 DVLOG(4) << "Dropping nalu"; | 1400 DVLOG(4) << "NALU done"; |
| 1282 curr_nalu_.reset(); | 1401 curr_nalu_.reset(); |
| 1283 } | 1402 } |
| 1284 } | 1403 } |
| 1285 | 1404 |
| 1286 gfx::Size H264Decoder::GetPicSize() const { | 1405 gfx::Size H264Decoder::GetPicSize() const { |
| 1287 return pic_size_; | 1406 return pic_size_; |
| 1288 } | 1407 } |
| 1289 | 1408 |
| 1290 size_t H264Decoder::GetRequiredNumOfPictures() const { | 1409 size_t H264Decoder::GetRequiredNumOfPictures() const { |
| 1291 return dpb_.max_num_pics() + kPicsInPipeline; | 1410 return dpb_.max_num_pics() + kPicsInPipeline; |
| 1292 } | 1411 } |
| 1293 | 1412 |
| 1294 } // namespace content | 1413 } // namespace content |
| OLD | NEW |