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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/media/mac_video_decode_accelerator.mm
diff --git a/content/common/gpu/media/mac_video_decode_accelerator.mm b/content/common/gpu/media/mac_video_decode_accelerator.mm
index 8d572c8af1cd7954fa4051b09f9edd8733f13c72..be0aab841fa34ba8e4da930a28955f5bdba79b1b 100644
--- a/content/common/gpu/media/mac_video_decode_accelerator.mm
+++ b/content/common/gpu/media/mac_video_decode_accelerator.mm
@@ -83,9 +83,7 @@ static bool BindImageToTexture(CGLContextObj context,
MacVideoDecodeAccelerator::MacVideoDecodeAccelerator(
media::VideoDecodeAccelerator::Client* client)
: client_(client),
- cgl_context_(NULL),
- nalu_len_field_size_(0),
- did_request_pictures_(false) {
+ cgl_context_(NULL) {
}
void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) {
@@ -93,21 +91,6 @@ void MacVideoDecodeAccelerator::SetGLContext(void* gl_context) {
cgl_context_ = static_cast<CGLContextObj>(gl_context);
}
-bool MacVideoDecodeAccelerator::SetConfigInfo(
- uint32_t frame_width,
- uint32_t frame_height,
- const std::vector<uint8_t>& avc_data) {
- DCHECK(CalledOnValidThread());
- frame_size_ = gfx::Size(frame_width, frame_height);
- nalu_len_field_size_ = (avc_data[4] & 0x03) + 1;
-
- DCHECK(!vda_support_.get());
- vda_support_ = new gfx::VideoDecodeAccelerationSupport();
- return vda_support_->Create(frame_size_.width(), frame_size_.height(),
- kCVPixelFormatType_422YpCbCr8, &avc_data.front(), avc_data.size()) ==
- gfx::VideoDecodeAccelerationSupport::SUCCESS;
-}
-
bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
DCHECK(CalledOnValidThread());
@@ -131,54 +114,43 @@ void MacVideoDecodeAccelerator::Decode(
return;
}
- size_t buffer_size = bitstream_buffer.size();
- if (buffer_size < nalu_len_field_size_ + 1) {
- LOG(ERROR) << "Bitstream contains invalid data.";
- if (client_)
- client_->NotifyError(INVALID_ARGUMENT);
- return;
- }
-
- // The decoder can only handle slice types 1-5.
- const uint8_t* buffer = static_cast<const uint8_t*>(memory.memory());
- uint8_t nalu_type = buffer[nalu_len_field_size_] & 0x1f;
- if (nalu_type < 1 || nalu_type > 5) {
- if (client_)
- client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id());
- return;
- }
-
- // Keep a ref counted copy of the buffer.
- std::vector<uint8_t> vbuffer(buffer, buffer + buffer_size);
- scoped_refptr<base::RefCountedBytes> bytes(
- base::RefCountedBytes::TakeVector(&vbuffer));
-
- // Store the buffer size at the beginning of the buffer as the decoder
- // expects.
- size_t frame_buffer_size = buffer_size - nalu_len_field_size_;
- DCHECK(nalu_len_field_size_ <= 4);
- uint64_t max_frame_buffer_size = (1llu << (nalu_len_field_size_ * 8)) - 1;
- if (frame_buffer_size > max_frame_buffer_size) {
- LOG(ERROR) << "Bitstream is too large.";
- if (client_)
- client_->NotifyError(INVALID_ARGUMENT);
- return;
- }
- for (size_t i = 0; i < nalu_len_field_size_; ++i) {
- size_t shift = nalu_len_field_size_ * 8 - (i + 1) * 8;
- bytes->data()[i] = (frame_buffer_size >> shift) & 0xff;
- }
-
- if (vda_support_) {
- vda_support_->Decode(bytes->front(), bytes->size(),
- base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
- this, bitstream_buffer.id(), bytes));
- }
-
- if (!did_request_pictures_) {
- did_request_pictures_ = true;
- if (client_)
- client_->ProvidePictureBuffers(kNumPictureBuffers, frame_size_);
+ h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()),
+ bitstream_buffer.size());
+ while (true) {
+ content::H264NALU nalu;
+ content::H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu);
+ if (result == content::H264Parser::kEOStream) {
+ if (client_)
+ client_->NotifyEndOfBitstreamBuffer(bitstream_buffer.id());
+ return;
+ }
+ if (result != content::H264Parser::kOk) {
+ if (client_)
+ client_->NotifyError(UNREADABLE_INPUT);
+ return;
+ }
+ if (!did_build_config_record_) {
+ bool did_consume_nalu = false;
+ std::vector<uint8_t> config_record;
+ if (!config_record_builder_.ProcessNALU(
+ &h264_parser_, nalu, &config_record)) {
+ if (client_)
+ client_->NotifyError(UNREADABLE_INPUT);
+ return;
+ }
+ if (!config_record.empty()) {
+ did_build_config_record_ = true;
+ CreateDecoder(config_record);
+ }
+ if (did_consume_nalu)
+ continue;
+ }
+ // If the decoder has been created and this is a slice type then pass it
+ // to the decoder.
+ if (vda_support_.get() && nalu.nal_unit_type >= 1 &&
+ nalu.nal_unit_type <= 5) {
+ DecodeNALU(nalu, bitstream_buffer.id());
+ }
}
}
@@ -293,6 +265,52 @@ void MacVideoDecodeAccelerator::NotifyResetDone() {
client_->NotifyResetDone();
}
+void MacVideoDecodeAccelerator::CreateDecoder(
+ const std::vector<uint8_t>& extra_data) {
+ vda_support_ = new gfx::VideoDecodeAccelerationSupport();
+ gfx::VideoDecodeAccelerationSupport::Status status = vda_support_->Create(
+ config_record_builder_.coded_width(),
+ config_record_builder_.coded_height(),
+ kCVPixelFormatType_422YpCbCr8,
+ &extra_data[0], extra_data.size());
+ if (status != gfx::VideoDecodeAccelerationSupport::SUCCESS) {
+ if (client_)
+ client_->NotifyError(PLATFORM_FAILURE);
+ return;
+ }
+
+ if (client_) {
+ client_->ProvidePictureBuffers(
+ kNumPictureBuffers,
+ gfx::Size(config_record_builder_.coded_width(),
+ config_record_builder_.coded_height()));
+ }
+}
+
+void MacVideoDecodeAccelerator::DecodeNALU(const content::H264NALU& nalu,
+ int32 bitstream_buffer_id) {
+ // Assume the NALU length field size is 4 bytes.
+ const int kNALULengthFieldSize = 4;
+ std::vector<uint8_t> data(kNALULengthFieldSize + nalu.size);
+
+ // Store the buffer size at the beginning of the buffer as the decoder
+ // expects.
+ for (size_t i = 0; i < kNALULengthFieldSize; ++i) {
+ size_t shift = kNALULengthFieldSize * 8 - (i + 1) * 8;
+ data[i] = (nalu.size >> shift) & 0xff;
+ }
+
+ // Copy the NALU data.
+ memcpy(&data[kNALULengthFieldSize], nalu.data, nalu.size);
+
+ // Keep a ref counted copy of the buffer.
+ scoped_refptr<base::RefCountedBytes> bytes(
+ base::RefCountedBytes::TakeVector(&data));
+ vda_support_->Decode(bytes->front(), bytes->size(),
+ base::Bind(&MacVideoDecodeAccelerator::OnFrameReady,
+ this, bitstream_buffer_id, bytes));
+}
+
MacVideoDecodeAccelerator::UsedPictureInfo::UsedPictureInfo(
const media::PictureBuffer& pic,
const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image)

Powered by Google App Engine
This is Rietveld 408576698