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