Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: content/common/gpu/media/avc_config_record_builder.cc

Issue 10411085: Build AVC decoder configuration record (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/common/gpu/media/avc_config_record_builder.h"
6
7 #include "base/logging.h"
8 #include "content/common/gpu/media/h264_parser.h"
9
10 namespace content {
11
12 AVCConfigRecordBuilder::AVCConfigRecordBuilder()
13 : sps_profile_idc_(0),
14 sps_constraint_setx_flag_(0),
15 sps_level_idc_(0),
16 coded_width_(0),
17 coded_height_(0) {
18 }
19
20 AVCConfigRecordBuilder::~AVCConfigRecordBuilder() {
21 }
22
23 bool AVCConfigRecordBuilder::ProcessNALU(
24 H264Parser* parser,
25 const H264NALU& nalu,
26 std::vector<uint8_t>* config_record) {
27 if (nalu.nal_unit_type == H264NALU::kSPS) {
28 return ProcessSPS(parser, nalu);
29 } else if (nalu.nal_unit_type == H264NALU::kPPS) {
30 return ProcessPPS(parser, nalu);
31 } else if (nalu.nal_unit_type >= 1 && nalu.nal_unit_type <= 5) {
32 // Ready to build the AVC decoder configuration record once the first slice
33 // type is encountered.
34 *config_record = BuildConfigRecord();
35 return true;
36 }
37 // Effectively skip this NALU by returning success.
38 return true;
39 }
40
41 std::vector<uint8_t> AVCConfigRecordBuilder::BuildConfigRecord() {
42 // 5 bytes for AVC record header. 1 byte for the number of SPS units.
43 // 1 byte for the number of PPS units.
44 int record_size = 7;
45 for (NALUVector::const_iterator it = sps_nalus_.begin();
46 it != sps_nalus_.end(); ++it) {
47 // Plus 2 bytes to store the SPS size.
48 record_size += (*it)->size() + 2;
49 }
50 for (NALUVector::const_iterator it = pps_nalus_.begin();
51 it != pps_nalus_.end(); ++it) {
52 // Plus 2 bytes to store the PPS size.
53 record_size += (*it)->size() + 2;
54 }
55 std::vector<uint8_t> extra_data(record_size);
56
57 // AVC decoder configuration record version.
58 extra_data[0] = 0x01;
59 // Profile.
60 extra_data[1] = sps_profile_idc_ & 0xff;
61 // Profile compatibility, must match the byte between profile IDC
62 // and level IDC in the SPS.
63 extra_data[2] = sps_constraint_setx_flag_;
64 // AVC level.
65 extra_data[3] = sps_level_idc_ & 0xff;
66
67 // TODO(sail): There's no way to get the NALU length field size from the
68 // SPS and PPS data. Just assume 4 for now.
69 const int kNALULengthFieldSize = 4;
70
71 // The first 6 bits are reserved and must be 1. Last two bits are the
72 // NALU field size minus 1.
73 extra_data[4] = 0xfc | ((kNALULengthFieldSize - 1) & 0x03);
74
75 // The first 3 bits are reserved and must be 1. Last 5 bits are the
76 // number of SPS units.
77 extra_data[5] = 0xe0 | (sps_nalus_.size() & 0x1f);
78 int index = 6;
79 index += CopyNALUsToConfigRecord(sps_nalus_, &extra_data[index]);
80
81 // The number of PPS units.
82 extra_data[index++] = pps_nalus_.size() & 0xff;
83 CopyNALUsToConfigRecord(pps_nalus_, &extra_data[index]);
84
85 return extra_data;
86 }
87
88 int AVCConfigRecordBuilder::CopyNALUsToConfigRecord(const NALUVector& nalus,
89 uint8_t* record_buffer) {
90 int index = 0;
91 for (NALUVector::const_iterator it = nalus.begin();
92 it != nalus.end(); ++it) {
93 // High byte of the NALU size.
94 record_buffer[index++] = ((*it)->size() >> 8) & 0xff;
95 // Low byte of the NALU size.
96 record_buffer[index++] = (*it)->size() & 0xff;
97 // The NALU data.
98 memcpy(record_buffer + index, (*it)->front(), (*it)->size());
99 index += (*it)->size();
100 }
101 return index;
102 }
103
104 bool AVCConfigRecordBuilder::ProcessSPS(H264Parser* parser,
105 const H264NALU& nalu) {
106 int sps_id = 0;
107 H264Parser::Result result = parser->ParseSPS(&sps_id);
108 if (result != H264Parser::kOk)
109 return false;
110
111 std::vector<uint8_t> bytes(nalu.data, nalu.data + nalu.size);
112 sps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes));
113
114 const H264SPS* sps = parser->GetSPS(sps_id);
115
116 // Use the last width and height that are encountered.
117 coded_width_ = (sps->pic_width_in_mbs_minus1 + 1) * 16;
118 if (sps->frame_mbs_only_flag)
119 coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 16;
120 else
121 coded_height_ = (sps->pic_height_in_map_units_minus1 + 1) * 32;
122
123 // Use the last video profile and flags that are encountered.
124 sps_profile_idc_ = sps->profile_idc;
125 sps_constraint_setx_flag_ = sps->constraint_setx_flag;
126 // Use the largest AVC level that's encountered.
127 sps_level_idc_ = std::max(sps_level_idc_, sps->level_idc);
128
129 return true;
130 }
131
132 bool AVCConfigRecordBuilder::ProcessPPS(H264Parser* parser,
133 const H264NALU& nalu) {
134 int pps_id = 0;
135 H264Parser::Result result = parser->ParsePPS(&pps_id);
136 if (result != H264Parser::kOk)
137 return false;
138
139 std::vector<uint8_t> bytes(nalu.data, nalu.data + nalu.size);
140 pps_nalus_.push_back(base::RefCountedBytes::TakeVector(&bytes));
141 return true;
142 }
143
144 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698