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

Side by Side Diff: content/common/gpu/media/mac_video_decode_accelerator.mm

Issue 10411085: Build AVC decoder configuration record (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comment 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
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 "content/common/gpu/media/mac_video_decode_accelerator.h" 5 #include "content/common/gpu/media/mac_video_decode_accelerator.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_path.h" 8 #include "base/file_path.h"
9 #import "base/mac/foundation_util.h" 9 #import "base/mac/foundation_util.h"
10 #import "base/memory/ref_counted_memory.h" 10 #import "base/memory/ref_counted_memory.h"
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 0) != kCGLNoError) { 76 0) != kCGLNoError) {
77 DLOG(ERROR) << "Failed to bind image to texture."; 77 DLOG(ERROR) << "Failed to bind image to texture.";
78 return false; 78 return false;
79 } 79 }
80 return glGetError() == GL_NO_ERROR; 80 return glGetError() == GL_NO_ERROR;
81 } 81 }
82 82
83 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator( 83 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator(
84 media::VideoDecodeAccelerator::Client* client) 84 media::VideoDecodeAccelerator::Client* client)
85 : client_(client), 85 : client_(client),
86 cgl_context_(NULL), 86 cgl_context_(NULL) {
87 nalu_len_field_size_(0),
88 did_request_pictures_(false) {
89 } 87 }
90 88
91 void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) { 89 void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) {
92 DCHECK(CalledOnValidThread()); 90 DCHECK(CalledOnValidThread());
93 cgl_context_ = static_cast<CGLContextObj>(gl_context); 91 cgl_context_ = static_cast<CGLContextObj>(gl_context);
94 } 92 }
95 93
96 bool MacVideoDecodeAccelerator::SetConfigInfo(
97 uint32_t frame_width,
98 uint32_t frame_height,
99 const std::vector<uint8_t>& avc_data) {
100 DCHECK(CalledOnValidThread());
101 frame_size_ = gfx::Size(frame_width, frame_height);
102 nalu_len_field_size_ = (avc_data[4] & 0x03) + 1;
103
104 DCHECK(!vda_support_.get());
105 vda_support_ = new gfx::VideoDecodeAccelerationSupport();
106 return vda_support_->Create(frame_size_.width(), frame_size_.height(),
107 kCVPixelFormatType_422YpCbCr8, &avc_data.front(), avc_data.size()) ==
108 gfx::VideoDecodeAccelerationSupport::SUCCESS;
109 }
110
111 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { 94 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
112 DCHECK(CalledOnValidThread()); 95 DCHECK(CalledOnValidThread());
113 96
114 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); 97 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
115 if (!io_surface_support) 98 if (!io_surface_support)
116 return false; 99 return false;
117 100
118 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 101 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
119 &MacVideoDecodeAccelerator::NotifyInitializeDone, this)); 102 &MacVideoDecodeAccelerator::NotifyInitializeDone, this));
120 return true; 103 return true;
121 } 104 }
122 105
123 void MacVideoDecodeAccelerator::Decode( 106 void MacVideoDecodeAccelerator::Decode(
124 const media::BitstreamBuffer& bitstream_buffer) { 107 const media::BitstreamBuffer& bitstream_buffer) {
125 DCHECK(CalledOnValidThread()); 108 DCHECK(CalledOnValidThread());
126 base::SharedMemory memory(bitstream_buffer.handle(), true); 109 base::SharedMemory memory(bitstream_buffer.handle(), true);
127 if (!memory.Map(bitstream_buffer.size())) { 110 if (!memory.Map(bitstream_buffer.size())) {
128 LOG(ERROR) << "Failed to SharedMemory::Map()."; 111 LOG(ERROR) << "Failed to SharedMemory::Map().";
129 if (client_) 112 if (client_)
130 client_->NotifyError(UNREADABLE_INPUT); 113 client_->NotifyError(UNREADABLE_INPUT);
131 return; 114 return;
132 } 115 }
133 116
134 size_t buffer_size = bitstream_buffer.size(); 117 h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()),
135 if (buffer_size < nalu_len_field_size_ + 1) { 118 bitstream_buffer.size());
136 LOG(ERROR) << "Bitstream contains invalid data."; 119 while (true) {
137 if (client_) 120 content::H264NALU nalu;
138 client_->NotifyError(INVALID_ARGUMENT); 121 content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu);
139 return; 122 if (result == content::H264Parser::kEOStream) {
140 } 123 if (client_)
141 124 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id());
142 // The decoder can only handle slice types 1-5. 125 return;
143 const uint8_t* buffer = static_cast<const uint8_t*>(memory.memory()); 126 }
144 uint8_t nalu_type = buffer[nalu_len_field_size_] & 0x1f; 127 if (result != content::H264Parser::kOk) {
145 if (nalu_type < 1 || nalu_type > 5) { 128 if (client_)
146 if (client_) 129 client_->NotifyError(UNREADABLE_INPUT);
147 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); 130 return;
148 return; 131 }
149 } 132 if (!did_build_config_record_) {
150 133 bool did_consume_nalu = false;
151 // Keep a ref counted copy of the buffer. 134 std::vector<uint8_t> config_record;
152 std::vector<uint8_t> vbuffer(buffer, buffer + buffer_size); 135 if (!config_record_builder_.ProcessNALU(
153 scoped_refptr<base::RefCountedBytes> bytes( 136 &h264_parser_, nalu, &config_record)) {
154 base::RefCountedBytes::TakeVector(&vbuffer)); 137 if (client_)
155 138 client_->NotifyError(UNREADABLE_INPUT);
156 // Store the buffer size at the beginning of the buffer as the decoder 139 return;
157 // expects. 140 }
158 size_t frame_buffer_size = buffer_size - nalu_len_field_size_; 141 if (!config_record.empty()) {
159 DCHECK(nalu_len_field_size_ <= 4); 142 did_build_config_record_ = true;
160 uint64_t max_frame_buffer_size = (1llu << (nalu_len_field_size_ * 8)) - 1; 143 CreateDecoder(config_record);
161 if (frame_buffer_size > max_frame_buffer_size) { 144 }
162 LOG(ERROR) << "Bitstream is too large."; 145 if (did_consume_nalu)
163 if (client_) 146 continue;
164 client_->NotifyError(INVALID_ARGUMENT); 147 }
165 return; 148 // If the decoder has been created and this is a slice type then pass it
166 } 149 // to the decoder.
167 for (size_t i = 0; i < nalu_len_field_size_; ++i) { 150 if (vda_support_.get() && nalu.nal_unit_type >= 1 &&
168 size_t shift = nalu_len_field_size_ * 8 - (i + 1) * 8; 151 nalu.nal_unit_type <= 5) {
169 bytes->data()[i] = (frame_buffer_size >> shift) & 0xff; 152 DecodeNALU(nalu, bitstream_buffer.id());
170 } 153 }
171
172 if (vda_support_) {
173 vda_support_->Decode(bytes->front(), bytes->size(),
174 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
175 this, bitstream_buffer.id(), bytes));
176 }
177
178 if (!did_request_pictures_) {
179 did_request_pictures_ = true;
180 if (client_)
181 client_->ProvidePictureBuffers(kNumPictureBuffers, frame_size_);
182 } 154 }
183 } 155 }
184 156
185 void MacVideoDecodeAccelerator::AssignPictureBuffers( 157 void MacVideoDecodeAccelerator::AssignPictureBuffers(
186 const std::vector<media::PictureBuffer>& buffers) { 158 const std::vector<media::PictureBuffer>& buffers) {
187 DCHECK(CalledOnValidThread()); 159 DCHECK(CalledOnValidThread());
188 available_pictures_.insert( 160 available_pictures_.insert(
189 available_pictures_.end(), buffers.begin(), buffers.end()); 161 available_pictures_.end(), buffers.begin(), buffers.end());
190 SendImages(); 162 SendImages();
191 } 163 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 if (client_) 258 if (client_)
287 client_->NotifyFlushDone(); 259 client_->NotifyFlushDone();
288 } 260 }
289 261
290 void MacVideoDecodeAccelerator::NotifyResetDone() { 262 void MacVideoDecodeAccelerator::NotifyResetDone() {
291 decoded_images_.clear(); 263 decoded_images_.clear();
292 if (client_) 264 if (client_)
293 client_->NotifyResetDone(); 265 client_->NotifyResetDone();
294 } 266 }
295 267
268 void MacVideoDecodeAccelerator::CreateDecoder(
269 const std::vector<uint8_t>& extra_data) {
270 vda_support_ = new gfx::VideoDecodeAccelerationSupport();
271 gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create(
272 config_record_builder_.coded_width(),
273 config_record_builder_.coded_height(),
274 kCVPixelFormatType_422YpCbCr8,
275 &extra_data[0], extra_data.size());
276 if (status != gfx::VideoDecodeAccelerationSupport::SUCCESS) {
277 if (client_)
278 client_->NotifyError(PLATFORM_FAILURE);
279 return;
280 }
281
282 if (client_) {
283 client_->ProvidePictureBuffers(
284 kNumPictureBuffers,
285 gfx::Size(config_record_builder_.coded_width(),
286 config_record_builder_.coded_height()));
287 }
288 }
289
290 void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu,
291 int32 bitstream_buffer_id) {
292 // Assume the NALU length field size is 4 bytes.
293 const int kNALULengthFieldSize = 4;
294 std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size);
295
296 // Store the buffer size at the beginning of the buffer as the decoder
297 // expects.
298 for (size_t i = 0; i < kNALULengthFieldSize; ++i) {
299 size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8;
300 data[i] = (nalu.size >> shift) & 0xff;
301 }
302
303 // Copy the NALU data.
304 memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size);
305
306 // Keep a ref counted copy of the buffer.
307 scoped_refptr<base::RefCountedBytes> bytes(
308 base::RefCountedBytes::TakeVector(&data));
309 vda_support_->Decode(bytes->front(), bytes->size(),
310 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
311 this, bitstream_buffer_id, bytes));
312 }
313
296 MacVideoDecodeAccelerator::UsedPictureInfo::UsedPictureInfo( 314 MacVideoDecodeAccelerator::UsedPictureInfo::UsedPictureInfo(
297 const media::PictureBuffer& pic, 315 const media::PictureBuffer& pic,
298 const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image) 316 const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image)
299 : picture_buffer(pic), 317 : picture_buffer(pic),
300 image(image, base::mac::RETAIN) { 318 image(image, base::mac::RETAIN) {
301 } 319 }
302 320
303 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() { 321 MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() {
304 } 322 }
305 323
306 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { 324 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() {
307 } 325 }
308 326
309 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { 327 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() {
310 } 328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698