Chromium Code Reviews| Index: content/common/gpu/media/avc_config_record_builder.cc |
| diff --git a/content/common/gpu/media/avc_config_record_builder.cc b/content/common/gpu/media/avc_config_record_builder.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..28bc770c466694a63f3396e499af0fb016dbfa3e |
| --- /dev/null |
| +++ b/content/common/gpu/media/avc_config_record_builder.cc |
| @@ -0,0 +1,152 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/common/gpu/media/avc_config_record_builder.h" |
| + |
| +#include "base/logging.h" |
| +#include "content/common/gpu/media/h264_parser.h" |
| + |
| +namespace content { |
| + |
| +AVCConfigRecordBuilder::AVCConfigRecordBuilder() |
| + : sps_profile_idc_(0), |
| + sps_constraint_setx_flag_(0), |
| + sps_level_idc_(0), |
| + coded_width_(0), |
| + coded_height_(0), |
| + can_build_record_(false) { |
| +} |
| + |
| +AVCConfigRecordBuilder::~AVCConfigRecordBuilder() { |
| +} |
| + |
| +bool AVCConfigRecordBuilder::ProcessNextNALU(H264Parser* parser, |
| + const H264NALU* nalu, |
| + bool* did_consume_nalu) { |
| + DCHECK(!can_build_record_); |
| + *did_consume_nalu = true; |
| + |
| + if (nalu->nal_unit_type == H264NALU::kSPS) { |
| + return ProcessSPS(parser, nalu); |
| + } else if (nalu->nal_unit_type == H264NALU::kPPS) { |
| + return ProcessPPS(parser, nalu); |
| + } else if (nalu->nal_unit_type >= 1 && nalu->nal_unit_type <= 5) { |
| + // Ready to build the AVC decoder configuration record once the first slice |
| + // type is encountered. |
| + *did_consume_nalu = false; |
| + can_build_record_ = true; |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
The fact that the previous two variables are only
sail
2012/05/28 21:45:46
Done.
|
| + return true; |
| + } |
| + // Skip this NALU. |
| + return true; |
| +} |
| + |
| +std::vector<uint8_t> AVCConfigRecordBuilder::BuildConfigRecord() { |
| + DCHECK(can_build_record_); |
| + |
| + // 5 bytes for AVC record header. 1 byte for the number of SPS units. |
| + // 1 byte for the number of PPS units. |
| + int record_size = 7; |
| + for (NALUVector::const_iterator it = sps_nalus_.begin(); |
| + it != sps_nalus_.end(); ++it) { |
| + // Plus 2 bytes to store the SPS size. |
| + record_size += (*it)->size() + 2; |
| + } |
| + for (NALUVector::const_iterator it = pps_nalus_.begin(); |
| + it != pps_nalus_.end(); ++it) { |
| + // Plus 2 bytes to store the PPS size. |
| + record_size += (*it)->size() + 2; |
| + } |
| + std::vector<uint8_t> extra_data(record_size, 0); |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
, 0
unnecessary
sail
2012/05/28 21:45:46
Done.
|
| + |
| + // AVC decoder configuration record version. |
| + extra_data[0] = 0x01; |
| + // Profile. |
| + extra_data[1] = sps_profile_idc_ & 0xff; |
| + // Profile compatibility, must match the byte between profile IDC |
| + // and level IDC in the SPS. |
| + extra_data[2] = sps_constraint_setx_flag_; |
| + // AVC level. |
| + extra_data[3] = sps_level_idc_ & 0xff; |
| + |
| + // TODO(sail): There's no way to get the NALU field size from the |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
s/NALU/NALU length/
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
posciak: do you have thoughts about this?
sail
2012/05/28 21:45:46
Done.
Pawel Osciak
2012/05/30 00:28:40
From what I discussed with Sailesh and saw in the
|
| + // SPS and PPS data. Just assume 4 for now. |
| + const int kNALULengthFieldSize = 4; |
| + |
| + // The first 6 bits are reserved and must be 1. Last two bits are the |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
s/and must/and must/
sail
2012/05/28 21:45:46
Done.
|
| + // NALU field size minus 1. |
| + extra_data[4] = 0xfc | ((kNALULengthFieldSize - 1) & 0x03); |
| + |
| + // The first 3 bits are reserved and must be 1. Last 5 bits are the |
| + // number of SPS units. |
| + extra_data[5] = 0xe0 | (sps_nalus_.size() & 0x1f); |
| + int index = 6; |
| + for (NALUVector::const_iterator it = sps_nalus_.begin(); |
| + it != sps_nalus_.end(); ++it) { |
| + // High byte of the SPS unit size. |
| + extra_data[index++] = ((*it)->size() >> 8) & 0xff; |
| + // Low byte of the SPS unit size. |
| + extra_data[index++] = (*it)->size() & 0xff; |
| + // The SPS data. |
| + memcpy(&extra_data[index], (*it)->front(), (*it)->size()); |
| + index += (*it)->size(); |
| + } |
| + |
| + // The number of PPS units. |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
Seems like l.83-94 & l.97-107 are near-copies of e
sail
2012/05/28 21:45:46
Done.
|
| + extra_data[index++] = pps_nalus_.size() & 0xff; |
| + for (NALUVector::const_iterator it = pps_nalus_.begin(); |
| + it != pps_nalus_.end(); ++it) { |
| + // High byte of the PPS unit size. |
| + extra_data[index++] = ((*it)->size() >> 8) & 0xff; |
| + // Low byte of the PPS unit size. |
| + extra_data[index++] = (*it)->size() & 0xff; |
| + // The PPS data. |
| + memcpy(&extra_data[index], (*it)->front(), (*it)->size()); |
| + index += (*it)->size(); |
| + } |
| + |
| + return extra_data; |
| +} |
| + |
| +bool AVCConfigRecordBuilder::ProcessSPS(H264Parser* parser, |
| + const H264NALU* nalu) { |
| + int sps_id = 0; |
| + H264Parser::Result result = parser->ParseSPS(&sps_id); |
| + if (result != H264Parser::kOk) |
| + return false; |
| + |
| + std::vector<uint8_t> bytes(nalu->data, nalu->data + nalu->size); |
| + sps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes)); |
| + |
| + const H264SPS* sps = parser->GetSPS(sps_id); |
| + |
| + // Use the last width and height that are encountered. |
| + coded_width_ = (sps->pic_width_in_mbs_minus1 + 1) * 16; |
| + if (sps->frame_mbs_only_flag) |
| + coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 16; |
| + else |
| + coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 32; |
| + |
| + // Use the last video profile and flags that are encountered. |
| + sps_profile_idc_ = sps->profile_idc; |
| + sps_constraint_setx_flag_ = sps->constraint_setx_flag; |
| + // Use the largest AVC level that's encountered. |
| + sps_level_idc_ = std::max(sps_level_idc_, sps->level_idc); |
| + |
| + return true; |
| +} |
| + |
| +bool AVCConfigRecordBuilder::ProcessPPS(H264Parser* parser, |
| + const H264NALU* nalu) { |
| + int pps_id = 0; |
| + H264Parser::Result result = parser->ParsePPS(&pps_id); |
| + if (result != H264Parser::kOk) |
| + return false; |
| + |
| + std::vector<uint8_t> bytes(nalu->data, nalu->data + nalu->size); |
| + pps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes)); |
| + return true; |
| +} |
| + |
| +} // namespace content |