| 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)
|
|
|