Chromium Code Reviews| 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 "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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 if (glGetError() != GL_NO_ERROR) | 78 if (glGetError() != GL_NO_ERROR) |
| 79 return false; | 79 return false; |
| 80 | 80 |
| 81 return true; | 81 return true; |
| 82 } | 82 } |
| 83 | 83 |
| 84 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator( | 84 MacVideoDecodeAccelerator::MacVideoDecodeAccelerator( |
| 85 media::VideoDecodeAccelerator::Client* client) | 85 media::VideoDecodeAccelerator::Client* client) |
| 86 : client_(client), | 86 : client_(client), |
| 87 cgl_context_(NULL), | 87 cgl_context_(NULL), |
| 88 nalu_len_field_size_(0), | 88 did_build_config_record_(false) { |
| 89 frame_width_(0), | |
| 90 frame_height_(0), | |
| 91 did_request_pictures_(false) { | |
| 92 } | 89 } |
| 93 | 90 |
| 94 void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) { | 91 void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) { |
| 95 cgl_context_ = static_cast<CGLContextObj>(gl_context); | 92 cgl_context_ = static_cast<CGLContextObj>(gl_context); |
| 96 } | 93 } |
| 97 | 94 |
| 98 bool MacVideoDecodeAccelerator::SetConfigInfo( | |
| 99 uint32_t frame_width, | |
| 100 uint32_t frame_height, | |
| 101 const std::vector<uint8_t>& avc_data) { | |
| 102 frame_width_ = frame_width; | |
| 103 frame_height_ = frame_height; | |
| 104 nalu_len_field_size_ = (avc_data[4] & 0x03) + 1; | |
| 105 | |
| 106 DCHECK(!vda_.get()); | |
| 107 vda_ = new gfx::VideoDecodeAccelerationSupport(); | |
| 108 gfx::VideoDecodeAccelerationSupport::Status status = vda_->Create( | |
| 109 frame_width_, frame_height_, | |
| 110 kCVPixelFormatType_422YpCbCr8, &avc_data.front(), avc_data.size()); | |
| 111 if (status != gfx::VideoDecodeAccelerationSupport::VDA_SUCCESS) | |
| 112 return false; | |
| 113 return true; | |
| 114 } | |
| 115 | |
| 116 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { | 95 bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) { |
| 117 if (client_) | 96 if (client_) |
| 118 client_->NotifyInitializeDone(); | 97 client_->NotifyInitializeDone(); |
| 119 return true; | 98 return true; |
| 120 } | 99 } |
| 121 | 100 |
| 122 void MacVideoDecodeAccelerator::Decode( | 101 void MacVideoDecodeAccelerator::Decode( |
| 123 const media::BitstreamBuffer& bitstream_buffer) { | 102 const media::BitstreamBuffer& bitstream_buffer) { |
| 124 base::SharedMemory memory(bitstream_buffer.handle(), true); | 103 base::SharedMemory memory(bitstream_buffer.handle(), true); |
| 125 if (!memory.Map(bitstream_buffer.size())) { | 104 if (!memory.Map(bitstream_buffer.size())) { |
| 126 CHECK(false); | 105 CHECK(false); |
| 127 return; | 106 return; |
| 128 } | 107 } |
| 129 | 108 |
| 130 size_t buffer_size = bitstream_buffer.size(); | 109 h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()), |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
The fact that you feed all bitstreambuffers to the
sail
2012/05/28 21:45:46
I'd like to keep using the parser so that I can ha
| |
| 131 if (buffer_size < nalu_len_field_size_ + 1) { | 110 bitstream_buffer.size()); |
| 132 if (client_) | 111 while (true) { |
| 133 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); | 112 content::H264NALU nalu; |
| 134 return; | 113 content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu); |
| 135 } | 114 if (result == content::H264Parser::kEOStream) { |
| 115 if (client_) | |
| 116 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); | |
| 117 return; | |
| 118 } | |
| 119 if (result != content::H264Parser::kOk) { | |
| 120 if (client_) | |
| 121 client_->NotifyError(UNREADABLE_INPUT); | |
| 122 return; | |
| 123 } | |
| 136 | 124 |
| 137 // The decoder can only handle slice types (1-5). | 125 if (!did_build_config_record_) { |
| 138 const uint8_t* buffer = static_cast<const uint8_t*>(memory.memory()); | 126 bool did_consume_nalu = false; |
| 139 uint8_t nalu_type = buffer[nalu_len_field_size_] & 0x1f; | 127 if (!config_record_builder_.ProcessNextNALU( |
| 140 if (nalu_type < 1 || nalu_type > 5) { | 128 &h264_parser_, &nalu, &did_consume_nalu)) { |
| 141 if (client_) | 129 if (client_) |
| 142 client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id()); | 130 client_->NotifyError(UNREADABLE_INPUT); |
| 143 return; | 131 return; |
| 144 } | 132 } |
| 145 | 133 |
| 146 // Keep a ref counted copy of the buffer. | 134 if (config_record_builder_.can_build_record()) { |
| 147 std::vector<uint8_t> vector(buffer, buffer + buffer_size); | 135 did_build_config_record_ = true; |
| 148 scoped_refptr<base::RefCountedBytes> bytes( | 136 CreateDecoder(); |
| 149 base::RefCountedBytes::TakeVector(&vector)); | 137 } |
| 150 | 138 |
| 151 // Store the buffer size at the beginning of the buffer as the decoder | 139 if (did_consume_nalu) |
| 152 // expects. | 140 continue; |
| 153 size_t frame_buffer_size = buffer_size - nalu_len_field_size_; | 141 } |
| 154 for (size_t i = 0; i < nalu_len_field_size_; ++i) { | |
| 155 size_t shift = nalu_len_field_size_ * 8 - (i + 1) * 8; | |
| 156 bytes->data()[i] = (frame_buffer_size >> shift) & 0xff; | |
| 157 } | |
| 158 | 142 |
| 159 vda_->Decode(bytes->front(), bytes->size(), | 143 // If the decoder has been created and this is a slice type then pass it |
| 160 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady, this, | 144 // to the decoder. |
| 161 bitstream_buffer.id(), bytes)); | 145 if (vda_.get() && nalu.nal_unit_type >= 1 && nalu.nal_unit_type <= 5) |
| 162 | 146 DecodeNALU(&nalu, bitstream_buffer.id()); |
| 163 if (!did_request_pictures_) { | |
| 164 did_request_pictures_ = true; | |
| 165 if (client_) | |
| 166 client_->ProvidePictureBuffers( | |
| 167 kNumPictureBuffers, gfx::Size(frame_width_, frame_height_)); | |
| 168 } | 147 } |
| 169 } | 148 } |
| 170 | 149 |
| 171 void MacVideoDecodeAccelerator::AssignPictureBuffers( | 150 void MacVideoDecodeAccelerator::AssignPictureBuffers( |
| 172 const std::vector<media::PictureBuffer>& buffers) { | 151 const std::vector<media::PictureBuffer>& buffers) { |
| 173 available_pictures_.insert( | 152 available_pictures_.insert( |
| 174 available_pictures_.end(), buffers.begin(), buffers.end()); | 153 available_pictures_.end(), buffers.begin(), buffers.end()); |
| 175 SendImages(); | 154 SendImages(); |
| 176 } | 155 } |
| 177 | 156 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 if (client_) | 229 if (client_) |
| 251 client_->NotifyFlushDone(); | 230 client_->NotifyFlushDone(); |
| 252 } | 231 } |
| 253 | 232 |
| 254 void MacVideoDecodeAccelerator::NotifyResetDone() { | 233 void MacVideoDecodeAccelerator::NotifyResetDone() { |
| 255 decoded_images_.clear(); | 234 decoded_images_.clear(); |
| 256 if (client_) | 235 if (client_) |
| 257 client_->NotifyResetDone(); | 236 client_->NotifyResetDone(); |
| 258 } | 237 } |
| 259 | 238 |
| 239 void MacVideoDecodeAccelerator::CreateDecoder() { | |
| 240 std::vector<uint8_t> extra_data( | |
| 241 config_record_builder_.BuildConfigRecord()); | |
| 242 vda_ = new gfx::VideoDecodeAccelerationSupport(); | |
| 243 gfx::VideoDecodeAccelerationSupport::Status status = vda_->Create( | |
| 244 config_record_builder_.coded_width(), | |
| 245 config_record_builder_.coded_height(), | |
| 246 kCVPixelFormatType_422YpCbCr8, | |
| 247 &extra_data[0], extra_data.size()); | |
| 248 if (status != gfx::VideoDecodeAccelerationSupport::VDA_SUCCESS) { | |
| 249 if (client_) | |
| 250 client_->NotifyError(PLATFORM_FAILURE); | |
| 251 return; | |
| 252 } | |
| 253 | |
| 254 if (client_) { | |
| 255 client_->ProvidePictureBuffers( | |
| 256 kNumPictureBuffers, | |
| 257 gfx::Size(config_record_builder_.coded_width(), | |
| 258 config_record_builder_.coded_height())); | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU* nalu, | |
| 263 int32 bitstream_buffer_id) { | |
| 264 // Assume the NALU lenght field size is 4 bytes. | |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
typo: length
sail
2012/05/28 21:45:46
Done.
| |
| 265 const int kNALULengthFieldSize = 4; | |
| 266 std::vector<uint8_t> data(kNALULengthFieldSize + nalu->size, 0); | |
|
Ami GONE FROM CHROMIUM
2012/05/23 19:41:19
Why the ", 0"?
sail
2012/05/28 21:45:46
Done.
| |
| 267 | |
| 268 // Store the buffer size at the beginning of the buffer as the decoder | |
| 269 // expects. | |
| 270 for (size_t i = 0; i < kNALULengthFieldSize; ++i) { | |
| 271 size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8; | |
| 272 data[i] = (nalu->size >> shift) & 0xff; | |
| 273 } | |
| 274 | |
| 275 // Copy the NALU data. | |
| 276 memcpy(&data[kNALULengthFieldSize], nalu->data, nalu->size); | |
| 277 | |
| 278 // Keep a ref counted copy of the buffer. | |
| 279 scoped_refptr<base::RefCountedBytes> bytes( | |
| 280 base::RefCountedBytes::TakeVector(&data)); | |
| 281 vda_->Decode(bytes->front(), bytes->size(), | |
| 282 base::Bind(&MacVideoDecodeAccelerator::OnFrameReady, this, | |
| 283 bitstream_buffer_id, bytes)); | |
| 284 } | |
| 285 | |
| 260 MacVideoDecodeAccelerator::PendingPictureInfo::PendingPictureInfo( | 286 MacVideoDecodeAccelerator::PendingPictureInfo::PendingPictureInfo( |
| 261 media::PictureBuffer pic) | 287 media::PictureBuffer pic) |
| 262 : picture_buffer(pic.id(), pic.size(), pic.texture_id()) { | 288 : picture_buffer(pic.id(), pic.size(), pic.texture_id()) { |
| 263 } | 289 } |
| 264 | 290 |
| 265 MacVideoDecodeAccelerator::PendingPictureInfo::~PendingPictureInfo() { | 291 MacVideoDecodeAccelerator::PendingPictureInfo::~PendingPictureInfo() { |
| 266 } | 292 } |
| 267 | 293 |
| 268 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { | 294 MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() { |
| 269 } | 295 } |
| 270 | 296 |
| 271 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { | 297 MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() { |
| 272 } | 298 } |
| OLD | NEW |