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" |
| (...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 if (!InitPictureFromSliceHeader(curr_sps_id_, parser_, slice_hdr, curr_pic_)) |
| 114 | |
| 115 curr_pic_->idr = slice_hdr->idr_pic_flag; | |
| 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; | 114 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 | 115 |
| 162 if (!CalculatePicOrderCounts(curr_pic_)) | 116 if (!CalculatePicOrderCounts(curr_pic_)) |
| 163 return false; | 117 return false; |
| 164 | 118 |
| 165 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; | 119 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; |
| 166 curr_pic_->adaptive_ref_pic_marking_mode_flag = | 120 curr_pic_->adaptive_ref_pic_marking_mode_flag = |
| 167 slice_hdr->adaptive_ref_pic_marking_mode_flag; | 121 slice_hdr->adaptive_ref_pic_marking_mode_flag; |
| 168 | 122 |
| 169 // If the slice header indicates we will have to perform reference marking | 123 // If the slice header indicates we will have to perform reference marking |
| 170 // process after this picture is decoded, store required data for that | 124 // 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)) | 1127 if (!FinishPicture(pic)) |
| 1174 return false; | 1128 return false; |
| 1175 | 1129 |
| 1176 unused_short_term_frame_num++; | 1130 unused_short_term_frame_num++; |
| 1177 unused_short_term_frame_num %= max_frame_num_; | 1131 unused_short_term_frame_num %= max_frame_num_; |
| 1178 } | 1132 } |
| 1179 | 1133 |
| 1180 return true; | 1134 return true; |
| 1181 } | 1135 } |
| 1182 | 1136 |
| 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() { | 1137 bool H264Decoder::PreprocessCurrentSlice() { |
| 1226 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); | 1138 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); |
| 1227 DCHECK(slice_hdr); | 1139 DCHECK(slice_hdr); |
| 1228 | 1140 |
| 1229 if (IsNewPrimaryCodedPicture(slice_hdr)) { | 1141 if (IsNewPrimaryCodedPicture(curr_pic_, curr_pps_id_, curr_sps_id_, parser_, |
| 1142 slice_hdr)) { | |
| 1230 // New picture, so first finish the previous one before processing it. | 1143 // New picture, so first finish the previous one before processing it. |
| 1231 if (!FinishPrevFrameIfPresent()) | 1144 if (!FinishPrevFrameIfPresent()) |
| 1232 return false; | 1145 return false; |
| 1233 | 1146 |
| 1234 DCHECK(!curr_pic_); | 1147 DCHECK(!curr_pic_); |
| 1235 | 1148 |
| 1236 if (slice_hdr->first_mb_in_slice != 0) { | 1149 if (slice_hdr->first_mb_in_slice != 0) { |
| 1237 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " | 1150 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " |
| 1238 << slice_hdr->first_mb_in_slice; | 1151 << slice_hdr->first_mb_in_slice; |
| 1239 return false; | 1152 return false; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1432 } | 1345 } |
| 1433 | 1346 |
| 1434 gfx::Size H264Decoder::GetPicSize() const { | 1347 gfx::Size H264Decoder::GetPicSize() const { |
| 1435 return pic_size_; | 1348 return pic_size_; |
| 1436 } | 1349 } |
| 1437 | 1350 |
| 1438 size_t H264Decoder::GetRequiredNumOfPictures() const { | 1351 size_t H264Decoder::GetRequiredNumOfPictures() const { |
| 1439 return dpb_.max_num_pics() + kPicsInPipeline; | 1352 return dpb_.max_num_pics() + kPicsInPipeline; |
| 1440 } | 1353 } |
| 1441 | 1354 |
| 1355 // static | |
| 1356 bool H264Decoder::InitPictureFromSliceHeader(int curr_sps_id, | |
|
Pawel Osciak
2016/12/20 08:34:22
Perhaps we could instead return a scoped_refptr<H2
emircan
2017/01/03 19:29:00
Done.
| |
| 1357 const H264Parser& parser, | |
|
Pawel Osciak
2016/12/20 08:34:22
Perhaps we could pass the SPS directly to the meth
emircan
2017/01/03 19:29:00
Done. Note that I kept param as |const H264SPS* sp
| |
| 1358 const H264SliceHeader* slice_hdr, | |
| 1359 scoped_refptr<H264Picture> pic) { | |
| 1360 DCHECK(pic.get()); | |
| 1361 | |
| 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 false; | |
| 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 DCHECK_NE(curr_sps_id, -1); | |
| 1384 const H264SPS* sps = parser.GetSPS(curr_sps_id); | |
| 1385 if (!sps) | |
| 1386 return false; | |
| 1387 | |
| 1388 pic->pic_order_cnt_type = sps->pic_order_cnt_type; | |
| 1389 switch (pic->pic_order_cnt_type) { | |
| 1390 case 0: | |
| 1391 pic->pic_order_cnt_lsb = slice_hdr->pic_order_cnt_lsb; | |
| 1392 pic->delta_pic_order_cnt_bottom = slice_hdr->delta_pic_order_cnt_bottom; | |
| 1393 break; | |
| 1394 | |
| 1395 case 1: | |
| 1396 pic->delta_pic_order_cnt0 = slice_hdr->delta_pic_order_cnt0; | |
| 1397 pic->delta_pic_order_cnt1 = slice_hdr->delta_pic_order_cnt1; | |
| 1398 break; | |
| 1399 | |
| 1400 case 2: | |
| 1401 break; | |
| 1402 | |
| 1403 default: | |
| 1404 NOTREACHED(); | |
| 1405 return false; | |
| 1406 } | |
| 1407 return true; | |
| 1408 } | |
| 1409 | |
| 1410 // static | |
| 1411 bool H264Decoder::IsNewPrimaryCodedPicture(scoped_refptr<H264Picture> curr_pic, | |
|
Pawel Osciak
2016/12/20 08:34:22
const scoped_refptr<>& ?
emircan
2017/01/03 19:29:00
I came across to this in an earlier review that pa
| |
| 1412 int curr_pps_id, | |
| 1413 int curr_sps_id, | |
| 1414 const H264Parser& parser, | |
|
Pawel Osciak
2016/12/20 08:34:22
Here we should be able to also pass an SPS only, w
emircan
2017/01/03 19:29:00
Done.
| |
| 1415 const H264SliceHeader* slice_hdr) { | |
|
Pawel Osciak
2016/12/20 08:34:22
Since we are not changing the structure, could we
emircan
2017/01/03 19:29:00
Done.
| |
| 1416 if (!curr_pic) | |
| 1417 return true; | |
| 1418 | |
| 1419 // 7.4.1.2.4, assumes non-interlaced. | |
| 1420 if (slice_hdr->frame_num != curr_pic->frame_num || | |
| 1421 slice_hdr->pic_parameter_set_id != curr_pps_id || | |
| 1422 slice_hdr->nal_ref_idc != curr_pic->nal_ref_idc || | |
| 1423 slice_hdr->idr_pic_flag != curr_pic->idr || | |
| 1424 (slice_hdr->idr_pic_flag && | |
| 1425 (slice_hdr->idr_pic_id != curr_pic->idr_pic_id || | |
| 1426 // If we have two consecutive IDR slices, and the second one has | |
| 1427 // first_mb_in_slice == 0, treat it as a new picture. | |
| 1428 // Per spec, idr_pic_id should not be equal in this case (and we should | |
| 1429 // have hit the condition above instead, see spec 7.4.3 on idr_pic_id), | |
| 1430 // but some encoders neglect changing idr_pic_id for two consecutive | |
| 1431 // IDRs. Work around this by checking if the next slice contains the | |
| 1432 // zeroth macroblock, i.e. data that belongs to the next picture. | |
| 1433 slice_hdr->first_mb_in_slice == 0))) | |
| 1434 return true; | |
| 1435 | |
| 1436 const H264SPS* sps = parser.GetSPS(curr_sps_id); | |
| 1437 if (!sps) | |
| 1438 return false; | |
| 1439 | |
| 1440 if (sps->pic_order_cnt_type == curr_pic->pic_order_cnt_type) { | |
| 1441 if (curr_pic->pic_order_cnt_type == 0) { | |
| 1442 if (slice_hdr->pic_order_cnt_lsb != curr_pic->pic_order_cnt_lsb || | |
| 1443 slice_hdr->delta_pic_order_cnt_bottom != | |
| 1444 curr_pic->delta_pic_order_cnt_bottom) | |
| 1445 return true; | |
| 1446 } else if (curr_pic->pic_order_cnt_type == 1) { | |
| 1447 if (slice_hdr->delta_pic_order_cnt0 != curr_pic->delta_pic_order_cnt0 || | |
| 1448 slice_hdr->delta_pic_order_cnt1 != curr_pic->delta_pic_order_cnt1) | |
| 1449 return true; | |
| 1450 } | |
| 1451 } | |
| 1452 | |
| 1453 return false; | |
| 1454 } | |
| 1455 | |
| 1442 } // namespace media | 1456 } // namespace media |
| OLD | NEW |