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 |