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/numerics/safe_conversions.h" |
10 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
11 #include "content/common/gpu/media/vaapi_h264_decoder.h" | 12 #include "content/common/gpu/media/vaapi_h264_decoder.h" |
12 | 13 |
13 namespace content { | 14 namespace content { |
14 | 15 |
15 // Decode surface, used for decoding and reference. input_id comes from client | 16 // Decode surface, used for decoding and reference. input_id comes from client |
16 // and is associated with the surface that was produced as the result | 17 // and is associated with the surface that was produced as the result |
17 // of decoding a bitstream buffer with that id. | 18 // of decoding a bitstream buffer with that id. |
18 class VaapiH264Decoder::DecodeSurface { | 19 class VaapiH264Decoder::DecodeSurface { |
19 public: | 20 public: |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 } | 56 } |
56 | 57 |
57 VaapiH264Decoder::VaapiH264Decoder( | 58 VaapiH264Decoder::VaapiH264Decoder( |
58 VaapiWrapper* vaapi_wrapper, | 59 VaapiWrapper* vaapi_wrapper, |
59 const OutputPicCB& output_pic_cb, | 60 const OutputPicCB& output_pic_cb, |
60 const ReportErrorToUmaCB& report_error_to_uma_cb) | 61 const ReportErrorToUmaCB& report_error_to_uma_cb) |
61 : max_pic_order_cnt_lsb_(0), | 62 : max_pic_order_cnt_lsb_(0), |
62 max_frame_num_(0), | 63 max_frame_num_(0), |
63 max_pic_num_(0), | 64 max_pic_num_(0), |
64 max_long_term_frame_idx_(0), | 65 max_long_term_frame_idx_(0), |
| 66 max_num_reorder_frames_(0), |
65 curr_sps_id_(-1), | 67 curr_sps_id_(-1), |
66 curr_pps_id_(-1), | 68 curr_pps_id_(-1), |
67 vaapi_wrapper_(vaapi_wrapper), | 69 vaapi_wrapper_(vaapi_wrapper), |
68 output_pic_cb_(output_pic_cb), | 70 output_pic_cb_(output_pic_cb), |
69 report_error_to_uma_cb_(report_error_to_uma_cb) { | 71 report_error_to_uma_cb_(report_error_to_uma_cb) { |
70 Reset(); | 72 Reset(); |
71 state_ = kNeedStreamMetadata; | 73 state_ = kNeedStreamMetadata; |
72 } | 74 } |
73 | 75 |
74 VaapiH264Decoder::~VaapiH264Decoder() { | 76 VaapiH264Decoder::~VaapiH264Decoder() { |
(...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1322 // reference), or the memory will be released if we manage to output it here | 1324 // reference), or the memory will be released if we manage to output it here |
1323 // without having to store it for future reference. | 1325 // without having to store it for future reference. |
1324 scoped_ptr<H264Picture> pic(curr_pic_.release()); | 1326 scoped_ptr<H264Picture> pic(curr_pic_.release()); |
1325 | 1327 |
1326 // Get all pictures that haven't been outputted yet. | 1328 // Get all pictures that haven't been outputted yet. |
1327 H264Picture::PtrVector not_outputted; | 1329 H264Picture::PtrVector not_outputted; |
1328 // TODO(posciak): pass as pointer, not reference (violates coding style). | 1330 // TODO(posciak): pass as pointer, not reference (violates coding style). |
1329 dpb_.GetNotOutputtedPicsAppending(not_outputted); | 1331 dpb_.GetNotOutputtedPicsAppending(not_outputted); |
1330 // Include the one we've just decoded. | 1332 // Include the one we've just decoded. |
1331 not_outputted.push_back(pic.get()); | 1333 not_outputted.push_back(pic.get()); |
| 1334 |
1332 // Sort in output order. | 1335 // Sort in output order. |
1333 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); | 1336 std::sort(not_outputted.begin(), not_outputted.end(), POCAscCompare()); |
1334 | 1337 |
1335 // Try to output as many pictures as we can. A picture can be output | 1338 // Try to output as many pictures as we can. A picture can be output, |
1336 // if its POC is next after the previously outputted one (which means | 1339 // if the number of decoded and not yet outputted pictures that would remain |
1337 // last_output_poc_ + 2, because POCs are incremented by 2 to accommodate | 1340 // in DPB afterwards would at least be equal to max_num_reorder_frames. |
1338 // fields when decoding interleaved streams). POC can also be equal to | |
1339 // last outputted picture's POC when it wraps around back to 0. | |
1340 // If the outputted picture is not a reference picture, it doesn't have | 1341 // If the outputted picture is not a reference picture, it doesn't have |
1341 // to remain in the DPB and can be removed. | 1342 // to remain in the DPB and can be removed. |
1342 H264Picture::PtrVector::iterator output_candidate = not_outputted.begin(); | 1343 H264Picture::PtrVector::iterator output_candidate = not_outputted.begin(); |
1343 for (; output_candidate != not_outputted.end() && | 1344 size_t num_remaining = not_outputted.size(); |
1344 (*output_candidate)->pic_order_cnt <= last_output_poc_ + 2; | 1345 while (num_remaining > max_num_reorder_frames_) { |
1345 ++output_candidate) { | |
1346 int poc = (*output_candidate)->pic_order_cnt; | 1346 int poc = (*output_candidate)->pic_order_cnt; |
1347 DCHECK_GE(poc, last_output_poc_); | 1347 DCHECK_GE(poc, last_output_poc_); |
1348 if (!OutputPic(*output_candidate)) | 1348 if (!OutputPic(*output_candidate)) |
1349 return false; | 1349 return false; |
1350 | 1350 |
1351 if (!(*output_candidate)->ref) { | 1351 if (!(*output_candidate)->ref) { |
1352 // Current picture hasn't been inserted into DPB yet, so don't remove it | 1352 // Current picture hasn't been inserted into DPB yet, so don't remove it |
1353 // if we managed to output it immediately. | 1353 // if we managed to output it immediately. |
1354 if (*output_candidate != pic) | 1354 if (*output_candidate != pic) |
1355 dpb_.DeleteByPOC(poc); | 1355 dpb_.DeleteByPOC(poc); |
1356 // Mark as unused. | 1356 // Mark as unused. |
1357 UnassignSurfaceFromPoC(poc); | 1357 UnassignSurfaceFromPoC(poc); |
1358 } | 1358 } |
| 1359 |
| 1360 ++output_candidate; |
| 1361 --num_remaining; |
1359 } | 1362 } |
1360 | 1363 |
1361 // If we haven't managed to output the picture that we just decoded, or if | 1364 // If we haven't managed to output the picture that we just decoded, or if |
1362 // it's a reference picture, we have to store it in DPB. | 1365 // it's a reference picture, we have to store it in DPB. |
1363 if (!pic->outputted || pic->ref) { | 1366 if (!pic->outputted || pic->ref) { |
1364 if (dpb_.IsFull()) { | 1367 if (dpb_.IsFull()) { |
1365 // If we haven't managed to output anything to free up space in DPB | 1368 // If we haven't managed to output anything to free up space in DPB |
1366 // to store this picture, it's an error in the stream. | 1369 // to store this picture, it's an error in the stream. |
1367 DVLOG(1) << "Could not free up space in DPB!"; | 1370 DVLOG(1) << "Could not free up space in DPB!"; |
1368 return false; | 1371 return false; |
(...skipping 23 matching lines...) Expand all Loading... |
1392 case 42: return 34816; | 1395 case 42: return 34816; |
1393 case 50: return 110400; | 1396 case 50: return 110400; |
1394 case 51: // fallthrough | 1397 case 51: // fallthrough |
1395 case 52: return 184320; | 1398 case 52: return 184320; |
1396 default: | 1399 default: |
1397 DVLOG(1) << "Invalid codec level (" << level << ")"; | 1400 DVLOG(1) << "Invalid codec level (" << level << ")"; |
1398 return 0; | 1401 return 0; |
1399 } | 1402 } |
1400 } | 1403 } |
1401 | 1404 |
| 1405 bool VaapiH264Decoder::UpdateMaxNumReorderFrames(const media::H264SPS* sps) { |
| 1406 if (sps->vui_parameters_present_flag && sps->bitstream_restriction_flag) { |
| 1407 max_num_reorder_frames_ = |
| 1408 base::checked_cast<size_t>(sps->max_num_reorder_frames); |
| 1409 if (max_num_reorder_frames_ > dpb_.max_num_pics()) { |
| 1410 DVLOG(1) |
| 1411 << "max_num_reorder_frames present, but larger than MaxDpbFrames (" |
| 1412 << max_num_reorder_frames_ << " > " << dpb_.max_num_pics() << ")"; |
| 1413 max_num_reorder_frames_ = 0; |
| 1414 return false; |
| 1415 } |
| 1416 return true; |
| 1417 } |
| 1418 |
| 1419 // max_num_reorder_frames not present, infer from profile/constraints |
| 1420 // (see VUI semantics in spec). |
| 1421 if (sps->constraint_setx_flag[3]) { |
| 1422 switch (sps->profile_idc) { |
| 1423 case 44: |
| 1424 case 86: |
| 1425 case 100: |
| 1426 case 110: |
| 1427 case 122: |
| 1428 case 244: |
| 1429 max_num_reorder_frames_ = 0; |
| 1430 break; |
| 1431 default: |
| 1432 max_num_reorder_frames_ = dpb_.max_num_pics(); |
| 1433 break; |
| 1434 } |
| 1435 } else { |
| 1436 max_num_reorder_frames_ = dpb_.max_num_pics(); |
| 1437 } |
| 1438 |
| 1439 return true; |
| 1440 } |
| 1441 |
1402 bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { | 1442 bool VaapiH264Decoder::ProcessSPS(int sps_id, bool* need_new_buffers) { |
1403 const media::H264SPS* sps = parser_.GetSPS(sps_id); | 1443 const media::H264SPS* sps = parser_.GetSPS(sps_id); |
1404 DCHECK(sps); | 1444 DCHECK(sps); |
1405 DVLOG(4) << "Processing SPS"; | 1445 DVLOG(4) << "Processing SPS"; |
1406 | 1446 |
1407 *need_new_buffers = false; | 1447 *need_new_buffers = false; |
1408 | 1448 |
1409 if (sps->frame_mbs_only_flag == 0) { | 1449 if (sps->frame_mbs_only_flag == 0) { |
1410 DVLOG(1) << "frame_mbs_only_flag != 1 not supported"; | 1450 DVLOG(1) << "frame_mbs_only_flag != 1 not supported"; |
1411 report_error_to_uma_cb_.Run(FRAME_MBS_ONLY_FLAG_NOT_ONE); | 1451 report_error_to_uma_cb_.Run(FRAME_MBS_ONLY_FLAG_NOT_ONE); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1452 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb), | 1492 size_t max_dpb_size = std::min(max_dpb_mbs / (width_mb * height_mb), |
1453 static_cast<int>(H264DPB::kDPBMaxSize)); | 1493 static_cast<int>(H264DPB::kDPBMaxSize)); |
1454 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size; | 1494 DVLOG(1) << "Codec level: " << level << ", DPB size: " << max_dpb_size; |
1455 if (max_dpb_size == 0) { | 1495 if (max_dpb_size == 0) { |
1456 DVLOG(1) << "Invalid DPB Size"; | 1496 DVLOG(1) << "Invalid DPB Size"; |
1457 return false; | 1497 return false; |
1458 } | 1498 } |
1459 | 1499 |
1460 dpb_.set_max_num_pics(max_dpb_size); | 1500 dpb_.set_max_num_pics(max_dpb_size); |
1461 | 1501 |
| 1502 if (!UpdateMaxNumReorderFrames(sps)) |
| 1503 return false; |
| 1504 DVLOG(1) << "max_num_reorder_frames: " << max_num_reorder_frames_; |
| 1505 |
1462 *need_new_buffers = true; | 1506 *need_new_buffers = true; |
1463 return true; | 1507 return true; |
1464 } | 1508 } |
1465 | 1509 |
1466 bool VaapiH264Decoder::ProcessPPS(int pps_id) { | 1510 bool VaapiH264Decoder::ProcessPPS(int pps_id) { |
1467 const media::H264PPS* pps = parser_.GetPPS(pps_id); | 1511 const media::H264PPS* pps = parser_.GetPPS(pps_id); |
1468 DCHECK(pps); | 1512 DCHECK(pps); |
1469 | 1513 |
1470 curr_pps_id_ = pps->pic_parameter_set_id; | 1514 curr_pps_id_ = pps->pic_parameter_set_id; |
1471 | 1515 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1637 break; | 1681 break; |
1638 } | 1682 } |
1639 } | 1683 } |
1640 } | 1684 } |
1641 | 1685 |
1642 size_t VaapiH264Decoder::GetRequiredNumOfPictures() { | 1686 size_t VaapiH264Decoder::GetRequiredNumOfPictures() { |
1643 return dpb_.max_num_pics() + kPicsInPipeline; | 1687 return dpb_.max_num_pics() + kPicsInPipeline; |
1644 } | 1688 } |
1645 | 1689 |
1646 } // namespace content | 1690 } // namespace content |
OLD | NEW |