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" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 pic->frame_num = pic->pic_num = frame_num; | 103 pic->frame_num = pic->pic_num = frame_num; |
104 pic->adaptive_ref_pic_marking_mode_flag = false; | 104 pic->adaptive_ref_pic_marking_mode_flag = false; |
105 pic->ref = true; | 105 pic->ref = true; |
106 pic->long_term_reference_flag = false; | 106 pic->long_term_reference_flag = false; |
107 pic->field = H264Picture::FIELD_NONE; | 107 pic->field = H264Picture::FIELD_NONE; |
108 | 108 |
109 return CalculatePicOrderCounts(pic); | 109 return CalculatePicOrderCounts(pic); |
110 } | 110 } |
111 | 111 |
112 bool H264Decoder::InitCurrPicture(const H264SliceHeader* slice_hdr) { | 112 bool H264Decoder::InitCurrPicture(const H264SliceHeader* slice_hdr) { |
113 DCHECK(curr_pic_.get()); | 113 curr_pic_ = CreateH264PictureFromSliceHeader(parser_.GetSPS(curr_sps_id_), |
114 | 114 *slice_hdr); |
115 curr_pic_->idr = slice_hdr->idr_pic_flag; | 115 if (!curr_pic_) |
116 if (curr_pic_->idr) | |
117 curr_pic_->idr_pic_id = slice_hdr->idr_pic_id; | |
118 | |
119 if (slice_hdr->field_pic_flag) { | |
120 curr_pic_->field = slice_hdr->bottom_field_flag ? H264Picture::FIELD_BOTTOM | |
121 : H264Picture::FIELD_TOP; | |
122 } else { | |
123 curr_pic_->field = H264Picture::FIELD_NONE; | |
124 } | |
125 | |
126 if (curr_pic_->field != H264Picture::FIELD_NONE) { | |
127 DVLOG(1) << "Interlaced video not supported."; | |
128 return false; | 116 return false; |
129 } | |
130 | |
131 curr_pic_->nal_ref_idc = slice_hdr->nal_ref_idc; | |
132 curr_pic_->ref = slice_hdr->nal_ref_idc != 0; | |
133 // This assumes non-interlaced stream. | |
134 curr_pic_->frame_num = curr_pic_->pic_num = slice_hdr->frame_num; | |
135 | |
136 DCHECK_NE(curr_sps_id_, -1); | |
137 const H264SPS* sps = parser_.GetSPS(curr_sps_id_); | |
138 if (!sps) | |
139 return false; | |
140 | |
141 curr_pic_->pic_order_cnt_type = sps->pic_order_cnt_type; | |
142 switch (curr_pic_->pic_order_cnt_type) { | |
143 case 0: | |
144 curr_pic_->pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; | |
145 curr_pic_->delta_pic_order_cnt_bottom = | |
146 slice_hdr->delta_pic_order_cnt_bottom; | |
147 break; | |
148 | |
149 case 1: | |
150 curr_pic_->delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt0; | |
151 curr_pic_->delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt1; | |
152 break; | |
153 | |
154 case 2: | |
155 break; | |
156 | |
157 default: | |
158 NOTREACHED(); | |
159 return false; | |
160 } | |
161 | 117 |
162 if (!CalculatePicOrderCounts(curr_pic_)) | 118 if (!CalculatePicOrderCounts(curr_pic_)) |
163 return false; | 119 return false; |
164 | 120 |
165 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; | 121 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; |
166 curr_pic_->adaptive_ref_pic_marking_mode_flag = | 122 curr_pic_->adaptive_ref_pic_marking_mode_flag = |
167 slice_hdr->adaptive_ref_pic_marking_mode_flag; | 123 slice_hdr->adaptive_ref_pic_marking_mode_flag; |
168 | 124 |
169 // If the slice header indicates we will have to perform reference marking | 125 // If the slice header indicates we will have to perform reference marking |
170 // process after this picture is decoded, store required data for that | 126 // process after this picture is decoded, store required data for that |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1173 if (!FinishPicture(pic)) | 1129 if (!FinishPicture(pic)) |
1174 return false; | 1130 return false; |
1175 | 1131 |
1176 unused_short_term_frame_num++; | 1132 unused_short_term_frame_num++; |
1177 unused_short_term_frame_num %= max_frame_num_; | 1133 unused_short_term_frame_num %= max_frame_num_; |
1178 } | 1134 } |
1179 | 1135 |
1180 return true; | 1136 return true; |
1181 } | 1137 } |
1182 | 1138 |
1183 bool H264Decoder::IsNewPrimaryCodedPicture( | |
1184 const H264SliceHeader* slice_hdr) const { | |
1185 if (!curr_pic_) | |
1186 return true; | |
1187 | |
1188 // 7.4.1.2.4, assumes non-interlaced. | |
1189 if (slice_hdr->frame_num != curr_pic_->frame_num || | |
1190 slice_hdr->pic_parameter_set_id != curr_pps_id_ || | |
1191 slice_hdr->nal_ref_idc != curr_pic_->nal_ref_idc || | |
1192 slice_hdr->idr_pic_flag != curr_pic_->idr || | |
1193 (slice_hdr->idr_pic_flag && | |
1194 (slice_hdr->idr_pic_id != curr_pic_->idr_pic_id || | |
1195 // If we have two consecutive IDR slices, and the second one has | |
1196 // first_mb_in_slice == 0, treat it as a new picture. | |
1197 // Per spec, idr_pic_id should not be equal in this case (and we should | |
1198 // have hit the condition above instead, see spec 7.4.3 on idr_pic_id), | |
1199 // but some encoders neglect changing idr_pic_id for two consecutive | |
1200 // IDRs. Work around this by checking if the next slice contains the | |
1201 // zeroth macroblock, i.e. data that belongs to the next picture. | |
1202 slice_hdr->first_mb_in_slice == 0))) | |
1203 return true; | |
1204 | |
1205 const H264SPS* sps = parser_.GetSPS(curr_sps_id_); | |
1206 if (!sps) | |
1207 return false; | |
1208 | |
1209 if (sps->pic_order_cnt_type == curr_pic_->pic_order_cnt_type) { | |
1210 if (curr_pic_->pic_order_cnt_type == 0) { | |
1211 if (slice_hdr->pic_order_cnt_lsb != curr_pic_->pic_order_cnt_lsb || | |
1212 slice_hdr->delta_pic_order_cnt_bottom != | |
1213 curr_pic_->delta_pic_order_cnt_bottom) | |
1214 return true; | |
1215 } else if (curr_pic_->pic_order_cnt_type == 1) { | |
1216 if (slice_hdr->delta_pic_order_cnt0 != curr_pic_->delta_pic_order_cnt0 || | |
1217 slice_hdr->delta_pic_order_cnt1 != curr_pic_->delta_pic_order_cnt1) | |
1218 return true; | |
1219 } | |
1220 } | |
1221 | |
1222 return false; | |
1223 } | |
1224 | |
1225 bool H264Decoder::PreprocessCurrentSlice() { | 1139 bool H264Decoder::PreprocessCurrentSlice() { |
1226 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); | 1140 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); |
1227 DCHECK(slice_hdr); | 1141 DCHECK(slice_hdr); |
1228 | 1142 |
1229 if (IsNewPrimaryCodedPicture(slice_hdr)) { | 1143 if (IsNewPrimaryCodedPicture(curr_pic_, curr_pps_id_, |
| 1144 parser_.GetSPS(curr_sps_id_), *slice_hdr)) { |
1230 // New picture, so first finish the previous one before processing it. | 1145 // New picture, so first finish the previous one before processing it. |
1231 if (!FinishPrevFrameIfPresent()) | 1146 if (!FinishPrevFrameIfPresent()) |
1232 return false; | 1147 return false; |
1233 | 1148 |
1234 DCHECK(!curr_pic_); | 1149 DCHECK(!curr_pic_); |
1235 | 1150 |
1236 if (slice_hdr->first_mb_in_slice != 0) { | 1151 if (slice_hdr->first_mb_in_slice != 0) { |
1237 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " | 1152 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " |
1238 << slice_hdr->first_mb_in_slice; | 1153 << slice_hdr->first_mb_in_slice; |
1239 return false; | 1154 return false; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1432 } | 1347 } |
1433 | 1348 |
1434 gfx::Size H264Decoder::GetPicSize() const { | 1349 gfx::Size H264Decoder::GetPicSize() const { |
1435 return pic_size_; | 1350 return pic_size_; |
1436 } | 1351 } |
1437 | 1352 |
1438 size_t H264Decoder::GetRequiredNumOfPictures() const { | 1353 size_t H264Decoder::GetRequiredNumOfPictures() const { |
1439 return dpb_.max_num_pics() + kPicsInPipeline; | 1354 return dpb_.max_num_pics() + kPicsInPipeline; |
1440 } | 1355 } |
1441 | 1356 |
| 1357 // static |
| 1358 scoped_refptr<H264Picture> H264Decoder::CreateH264PictureFromSliceHeader( |
| 1359 const H264SPS* sps, |
| 1360 const H264SliceHeader& slice_hdr) { |
| 1361 scoped_refptr<H264Picture> pic(new H264Picture()); |
| 1362 pic->idr = slice_hdr.idr_pic_flag; |
| 1363 if (pic->idr) |
| 1364 pic->idr_pic_id = slice_hdr.idr_pic_id; |
| 1365 |
| 1366 if (slice_hdr.field_pic_flag) { |
| 1367 pic->field = slice_hdr.bottom_field_flag ? H264Picture::FIELD_BOTTOM |
| 1368 : H264Picture::FIELD_TOP; |
| 1369 } else { |
| 1370 pic->field = H264Picture::FIELD_NONE; |
| 1371 } |
| 1372 |
| 1373 if (pic->field != H264Picture::FIELD_NONE) { |
| 1374 DVLOG(1) << "Interlaced video not supported."; |
| 1375 return nullptr; |
| 1376 } |
| 1377 |
| 1378 pic->nal_ref_idc = slice_hdr.nal_ref_idc; |
| 1379 pic->ref = slice_hdr.nal_ref_idc != 0; |
| 1380 // This assumes non-interlaced stream. |
| 1381 pic->frame_num = pic->pic_num = slice_hdr.frame_num; |
| 1382 |
| 1383 if (!sps) |
| 1384 return nullptr; |
| 1385 |
| 1386 pic->pic_order_cnt_type = sps->pic_order_cnt_type; |
| 1387 switch (pic->pic_order_cnt_type) { |
| 1388 case 0: |
| 1389 pic->pic_order_cnt_lsb = slice_hdr.pic_order_cnt_lsb; |
| 1390 pic->delta_pic_order_cnt_bottom = slice_hdr.delta_pic_order_cnt_bottom; |
| 1391 break; |
| 1392 |
| 1393 case 1: |
| 1394 pic->delta_pic_order_cnt0 = slice_hdr.delta_pic_order_cnt0; |
| 1395 pic->delta_pic_order_cnt1 = slice_hdr.delta_pic_order_cnt1; |
| 1396 break; |
| 1397 |
| 1398 case 2: |
| 1399 break; |
| 1400 |
| 1401 default: |
| 1402 NOTREACHED(); |
| 1403 return nullptr; |
| 1404 } |
| 1405 return pic; |
| 1406 } |
| 1407 |
| 1408 // static |
| 1409 bool H264Decoder::IsNewPrimaryCodedPicture(scoped_refptr<H264Picture> curr_pic, |
| 1410 int curr_pps_id, |
| 1411 const H264SPS* sps, |
| 1412 const H264SliceHeader& slice_hdr) { |
| 1413 if (!curr_pic) |
| 1414 return true; |
| 1415 |
| 1416 // 7.4.1.2.4, assumes non-interlaced. |
| 1417 if (slice_hdr.frame_num != curr_pic->frame_num || |
| 1418 slice_hdr.pic_parameter_set_id != curr_pps_id || |
| 1419 slice_hdr.nal_ref_idc != curr_pic->nal_ref_idc || |
| 1420 slice_hdr.idr_pic_flag != curr_pic->idr || |
| 1421 (slice_hdr.idr_pic_flag && |
| 1422 (slice_hdr.idr_pic_id != curr_pic->idr_pic_id || |
| 1423 // If we have two consecutive IDR slices, and the second one has |
| 1424 // first_mb_in_slice == 0, treat it as a new picture. |
| 1425 // Per spec, idr_pic_id should not be equal in this case (and we should |
| 1426 // have hit the condition above instead, see spec 7.4.3 on idr_pic_id), |
| 1427 // but some encoders neglect changing idr_pic_id for two consecutive |
| 1428 // IDRs. Work around this by checking if the next slice contains the |
| 1429 // zeroth macroblock, i.e. data that belongs to the next picture. |
| 1430 slice_hdr.first_mb_in_slice == 0))) |
| 1431 return true; |
| 1432 |
| 1433 if (!sps) |
| 1434 return false; |
| 1435 |
| 1436 if (sps->pic_order_cnt_type == curr_pic->pic_order_cnt_type) { |
| 1437 if (curr_pic->pic_order_cnt_type == 0) { |
| 1438 if (slice_hdr.pic_order_cnt_lsb != curr_pic->pic_order_cnt_lsb || |
| 1439 slice_hdr.delta_pic_order_cnt_bottom != |
| 1440 curr_pic->delta_pic_order_cnt_bottom) |
| 1441 return true; |
| 1442 } else if (curr_pic->pic_order_cnt_type == 1) { |
| 1443 if (slice_hdr.delta_pic_order_cnt0 != curr_pic->delta_pic_order_cnt0 || |
| 1444 slice_hdr.delta_pic_order_cnt1 != curr_pic->delta_pic_order_cnt1) |
| 1445 return true; |
| 1446 } |
| 1447 } |
| 1448 |
| 1449 return false; |
| 1450 } |
| 1451 |
1442 } // namespace media | 1452 } // namespace media |
OLD | NEW |