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 curr_pic_ = CreateH264PictureFromSliceHeader(parser_.GetSPS(curr_sps_id_), | 113 DCHECK(curr_pic_.get()); |
114 *slice_hdr); | 114 |
115 if (!curr_pic_) | 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."; |
116 return false; | 128 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 } |
117 | 161 |
118 if (!CalculatePicOrderCounts(curr_pic_)) | 162 if (!CalculatePicOrderCounts(curr_pic_)) |
119 return false; | 163 return false; |
120 | 164 |
121 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; | 165 curr_pic_->long_term_reference_flag = slice_hdr->long_term_reference_flag; |
122 curr_pic_->adaptive_ref_pic_marking_mode_flag = | 166 curr_pic_->adaptive_ref_pic_marking_mode_flag = |
123 slice_hdr->adaptive_ref_pic_marking_mode_flag; | 167 slice_hdr->adaptive_ref_pic_marking_mode_flag; |
124 | 168 |
125 // If the slice header indicates we will have to perform reference marking | 169 // If the slice header indicates we will have to perform reference marking |
126 // process after this picture is decoded, store required data for that | 170 // process after this picture is decoded, store required data for that |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 if (!FinishPicture(pic)) | 1173 if (!FinishPicture(pic)) |
1130 return false; | 1174 return false; |
1131 | 1175 |
1132 unused_short_term_frame_num++; | 1176 unused_short_term_frame_num++; |
1133 unused_short_term_frame_num %= max_frame_num_; | 1177 unused_short_term_frame_num %= max_frame_num_; |
1134 } | 1178 } |
1135 | 1179 |
1136 return true; | 1180 return true; |
1137 } | 1181 } |
1138 | 1182 |
| 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 |
1139 bool H264Decoder::PreprocessCurrentSlice() { | 1225 bool H264Decoder::PreprocessCurrentSlice() { |
1140 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); | 1226 const H264SliceHeader* slice_hdr = curr_slice_hdr_.get(); |
1141 DCHECK(slice_hdr); | 1227 DCHECK(slice_hdr); |
1142 | 1228 |
1143 if (IsNewPrimaryCodedPicture(curr_pic_, curr_pps_id_, | 1229 if (IsNewPrimaryCodedPicture(slice_hdr)) { |
1144 parser_.GetSPS(curr_sps_id_), *slice_hdr)) { | |
1145 // New picture, so first finish the previous one before processing it. | 1230 // New picture, so first finish the previous one before processing it. |
1146 if (!FinishPrevFrameIfPresent()) | 1231 if (!FinishPrevFrameIfPresent()) |
1147 return false; | 1232 return false; |
1148 | 1233 |
1149 DCHECK(!curr_pic_); | 1234 DCHECK(!curr_pic_); |
1150 | 1235 |
1151 if (slice_hdr->first_mb_in_slice != 0) { | 1236 if (slice_hdr->first_mb_in_slice != 0) { |
1152 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " | 1237 DVLOG(1) << "ASO/invalid stream, first_mb_in_slice: " |
1153 << slice_hdr->first_mb_in_slice; | 1238 << slice_hdr->first_mb_in_slice; |
1154 return false; | 1239 return false; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 } | 1432 } |
1348 | 1433 |
1349 gfx::Size H264Decoder::GetPicSize() const { | 1434 gfx::Size H264Decoder::GetPicSize() const { |
1350 return pic_size_; | 1435 return pic_size_; |
1351 } | 1436 } |
1352 | 1437 |
1353 size_t H264Decoder::GetRequiredNumOfPictures() const { | 1438 size_t H264Decoder::GetRequiredNumOfPictures() const { |
1354 return dpb_.max_num_pics() + kPicsInPipeline; | 1439 return dpb_.max_num_pics() + kPicsInPipeline; |
1355 } | 1440 } |
1356 | 1441 |
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 | |
1452 } // namespace media | 1442 } // namespace media |
OLD | NEW |