| 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
|
| deleted file mode 100644
|
| index 459aa263542ae2a5ecad054d645eea2d2659f15f..0000000000000000000000000000000000000000
|
| --- a/content/common/gpu/media/mac_video_decode_accelerator.mm
|
| +++ /dev/null
|
| @@ -1,390 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/common/gpu/media/mac_video_decode_accelerator.h"
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/location.h"
|
| -#import "base/mac/foundation_util.h"
|
| -#import "base/memory/ref_counted_memory.h"
|
| -#import "base/message_loop.h"
|
| -#include "base/native_library.h"
|
| -#include "ui/gfx/video_decode_acceleration_support_mac.h"
|
| -#include "ui/surface/io_surface_support_mac.h"
|
| -
|
| -namespace content {
|
| -
|
| -// Helper macros for dealing with failure. If |result| evaluates false, emit
|
| -// |log| to ERROR, register |error| with the decoder, and return |ret_val|
|
| -// (which may be omitted for functions that return void).
|
| -#define RETURN_ON_FAILURE(result, log, error, ret_val) \
|
| - do { \
|
| - if (!(result)) { \
|
| - DLOG(ERROR) << log; \
|
| - StopOnError(error); \
|
| - return ret_val; \
|
| - } \
|
| - } while (0)
|
| -
|
| -namespace {
|
| -
|
| -enum { kNumPictureBuffers = 4 };
|
| -
|
| -class ScopedContextSetter {
|
| - public:
|
| - ScopedContextSetter(CGLContextObj context)
|
| - : old_context_(NULL),
|
| - did_succeed_(false) {
|
| - old_context_ = CGLGetCurrentContext();
|
| - did_succeed_ = CGLSetCurrentContext(context) == kCGLNoError;
|
| - }
|
| -
|
| - ~ScopedContextSetter() {
|
| - if (did_succeed_)
|
| - CGLSetCurrentContext(old_context_);
|
| - }
|
| -
|
| - bool did_succeed() const {
|
| - return did_succeed_;
|
| - }
|
| -
|
| - private:
|
| - CGLContextObj old_context_;
|
| - bool did_succeed_;
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -static bool BindImageToTexture(CGLContextObj context,
|
| - CVImageBufferRef image,
|
| - uint32 texture_id) {
|
| - ScopedContextSetter scoped_context_setter(context);
|
| - if (!scoped_context_setter.did_succeed()) {
|
| - DVLOG(1) << "Unable to set OpenGL context.";
|
| - return false;
|
| - }
|
| -
|
| - IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
|
| - DCHECK(io_surface_support);
|
| -
|
| - CFTypeRef io_surface =
|
| - io_surface_support->CVPixelBufferGetIOSurface(image);
|
| - if (!io_surface) {
|
| - DVLOG(1) << "Unable to get IOSurface for CVPixelBuffer.";
|
| - return false;
|
| - }
|
| -
|
| - glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
| - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id);
|
| - if (io_surface_support->CGLTexImageIOSurface2D(
|
| - context,
|
| - GL_TEXTURE_RECTANGLE_ARB,
|
| - GL_RGB,
|
| - io_surface_support->IOSurfaceGetWidth(io_surface),
|
| - io_surface_support->IOSurfaceGetHeight(io_surface),
|
| - GL_YCBCR_422_APPLE,
|
| - GL_UNSIGNED_SHORT_8_8_APPLE,
|
| - io_surface,
|
| - 0) != kCGLNoError) {
|
| - DVLOG(1) << "Failed to bind image to texture.";
|
| - return false;
|
| - }
|
| - return glGetError() == GL_NO_ERROR;
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::MacVideoDecodeAccelerator(
|
| - CGLContextObj cgl_context, media::VideoDecodeAccelerator::Client* client)
|
| - : client_(client),
|
| - cgl_context_(cgl_context),
|
| - did_build_config_record_(false) {
|
| -}
|
| -
|
| -bool MacVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile) {
|
| - DCHECK(CalledOnValidThread());
|
| -
|
| - // MacVDA still fails on too many videos to be useful, even to users who
|
| - // ignore the GPU blacklist. Fail unconditionally here until enough of
|
| - // crbug.com/133828's blockers are resolved.
|
| - if (true)
|
| - return false;
|
| -
|
| - if (profile < media::H264PROFILE_MIN || profile > media::H264PROFILE_MAX)
|
| - return false;
|
| -
|
| - IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
|
| - if (!io_surface_support)
|
| - return false;
|
| -
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::NotifyInitializeDone, base::AsWeakPtr(this)));
|
| - return true;
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::Decode(
|
| - const media::BitstreamBuffer& bitstream_buffer) {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(client_,
|
| - "Call to Decode() during invalid state.", ILLEGAL_STATE,);
|
| -
|
| - base::SharedMemory memory(bitstream_buffer.handle(), true);
|
| - RETURN_ON_FAILURE(memory.Map(bitstream_buffer.size()),
|
| - "Failed to SharedMemory::Map().", UNREADABLE_INPUT,);
|
| -
|
| - h264_parser_.SetStream(static_cast<const uint8_t*>(memory.memory()),
|
| - bitstream_buffer.size());
|
| - while (true) {
|
| - H264NALU nalu;
|
| - H264Parser::Result result = h264_parser_.AdvanceToNextNALU(&nalu);
|
| - if (result == H264Parser::kEOStream) {
|
| - if (bitstream_nalu_count_.count(bitstream_buffer.id()) == 0) {
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::NotifyInputBufferRead,
|
| - base::AsWeakPtr(this), bitstream_buffer.id()));
|
| - }
|
| - return;
|
| - }
|
| - RETURN_ON_FAILURE(result == H264Parser::kOk,
|
| - "Unable to parse bitstream.", UNREADABLE_INPUT,);
|
| - if (!did_build_config_record_) {
|
| - std::vector<uint8_t> config_record;
|
| - RETURN_ON_FAILURE(config_record_builder_.ProcessNALU(&h264_parser_, nalu,
|
| - &config_record),
|
| - "Unable to build AVC configuraiton record.",
|
| - UNREADABLE_INPUT,);
|
| - if (!config_record.empty()) {
|
| - did_build_config_record_ = true;
|
| - if (!CreateDecoder(config_record))
|
| - return;
|
| - }
|
| - }
|
| - // 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) {
|
| - bitstream_nalu_count_[bitstream_buffer.id()]++;
|
| - DecodeNALU(nalu, bitstream_buffer.id());
|
| - }
|
| - }
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::AssignPictureBuffers(
|
| - const std::vector<media::PictureBuffer>& buffers) {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(client_,
|
| - "Call to AssignPictureBuffers() during invalid state.",
|
| - ILLEGAL_STATE,);
|
| - available_pictures_.insert(
|
| - available_pictures_.end(), buffers.begin(), buffers.end());
|
| - SendImages();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(client_,
|
| - "Call to ReusePictureBuffe() during invalid state.",
|
| - ILLEGAL_STATE,);
|
| -
|
| - std::map<int32, UsedPictureInfo>::iterator it =
|
| - used_pictures_.find(picture_buffer_id);
|
| - RETURN_ON_FAILURE(it != used_pictures_.end(),
|
| - "Missing picture buffer id: " << picture_buffer_id,
|
| - INVALID_ARGUMENT,);
|
| - UsedPictureInfo info = it->second;
|
| - used_pictures_.erase(it);
|
| - available_pictures_.push_back(info.picture_buffer);
|
| - SendImages();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::Flush() {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(vda_support_,
|
| - "Call to Flush() during invalid state.", ILLEGAL_STATE,);
|
| - vda_support_->Flush(true);
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::NotifyFlushDone, base::AsWeakPtr(this)));
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::Reset() {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(vda_support_,
|
| - "Call to Reset() during invalid state.", ILLEGAL_STATE,);
|
| - vda_support_->Flush(false);
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::NotifyResetDone, base::AsWeakPtr(this)));
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::Cleanup() {
|
| - DCHECK(CalledOnValidThread());
|
| - if (vda_support_) {
|
| - vda_support_->Destroy();
|
| - vda_support_ = NULL;
|
| - }
|
| - client_ = NULL;
|
| - decoded_images_.clear();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::Destroy() {
|
| - DCHECK(CalledOnValidThread());
|
| - Cleanup();
|
| - delete this;
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::~MacVideoDecodeAccelerator() {
|
| - DCHECK(CalledOnValidThread());
|
| - DCHECK(!vda_support_);
|
| - DCHECK(!client_);
|
| - DCHECK(decoded_images_.empty());
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::OnFrameReady(
|
| - int32 bitstream_buffer_id,
|
| - scoped_refptr<base::RefCountedBytes> bytes,
|
| - CVImageBufferRef image,
|
| - int status) {
|
| - DCHECK(CalledOnValidThread());
|
| - RETURN_ON_FAILURE(status == noErr,
|
| - "Decoding image failed with error code: " << status,
|
| - PLATFORM_FAILURE,);
|
| - if (!client_)
|
| - return;
|
| - if (image) {
|
| - DecodedImageInfo info;
|
| - info.image.reset(image, base::scoped_policy::RETAIN);
|
| - info.bitstream_buffer_id = bitstream_buffer_id;
|
| - decoded_images_.push_back(info);
|
| - SendImages();
|
| - }
|
| - std::map<int32, int>::iterator bitstream_count_it =
|
| - bitstream_nalu_count_.find(bitstream_buffer_id);
|
| - if (--bitstream_count_it->second == 0) {
|
| - bitstream_nalu_count_.erase(bitstream_count_it);
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::NotifyInputBufferRead,
|
| - base::AsWeakPtr(this), bitstream_buffer_id));
|
| - }
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::SendImages() {
|
| - if (!client_) {
|
| - DCHECK(decoded_images_.empty());
|
| - return;
|
| - }
|
| -
|
| - while (available_pictures_.size() && decoded_images_.size()) {
|
| - DecodedImageInfo info = decoded_images_.front();
|
| - decoded_images_.pop_front();
|
| - media::PictureBuffer picture_buffer = available_pictures_.front();
|
| - available_pictures_.pop_front();
|
| -
|
| - RETURN_ON_FAILURE(BindImageToTexture(
|
| - cgl_context_, info.image, picture_buffer.texture_id()),
|
| - "Error binding image to texture.", PLATFORM_FAILURE,);
|
| -
|
| - used_pictures_.insert(std::make_pair(
|
| - picture_buffer.id(), UsedPictureInfo(picture_buffer, info.image)));
|
| - client_->PictureReady(
|
| - media::Picture(picture_buffer.id(), info.bitstream_buffer_id));
|
| - }
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::StopOnError(
|
| - media::VideoDecodeAccelerator::Error error) {
|
| - if (client_)
|
| - client_->NotifyError(error);
|
| - Cleanup();
|
| -}
|
| -
|
| -bool MacVideoDecodeAccelerator::CreateDecoder(
|
| - const std::vector<uint8_t>& extra_data) {
|
| - DCHECK(client_);
|
| - DCHECK(!vda_support_.get());
|
| -
|
| - 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());
|
| - RETURN_ON_FAILURE(status == gfx::VideoDecodeAccelerationSupport::SUCCESS,
|
| - "Creating video decoder failed with error: " << status,
|
| - PLATFORM_FAILURE, false);
|
| -
|
| - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
|
| - &MacVideoDecodeAccelerator::RequestPictures, base::AsWeakPtr(this)));
|
| - return true;
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::DecodeNALU(const 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,
|
| - base::AsWeakPtr(this), bitstream_buffer_id, bytes));
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::NotifyInitializeDone() {
|
| - if (client_)
|
| - client_->NotifyInitializeDone();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::RequestPictures() {
|
| - if (client_) {
|
| - client_->ProvidePictureBuffers(
|
| - kNumPictureBuffers,
|
| - gfx::Size(config_record_builder_.coded_width(),
|
| - config_record_builder_.coded_height()),
|
| - GL_TEXTURE_RECTANGLE_ARB);
|
| - }
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::NotifyFlushDone() {
|
| - if (client_)
|
| - client_->NotifyFlushDone();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::NotifyResetDone() {
|
| - decoded_images_.clear();
|
| - if (client_)
|
| - client_->NotifyResetDone();
|
| -}
|
| -
|
| -void MacVideoDecodeAccelerator::NotifyInputBufferRead(int input_buffer_id) {
|
| - if (client_)
|
| - client_->NotifyEndOfBitstreamBuffer(input_buffer_id);
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::UsedPictureInfo::UsedPictureInfo(
|
| - const media::PictureBuffer& pic,
|
| - const base::mac::ScopedCFTypeRef<CVImageBufferRef>& image)
|
| - : picture_buffer(pic),
|
| - image(image, base::scoped_policy::RETAIN) {
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::UsedPictureInfo::~UsedPictureInfo() {
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::DecodedImageInfo::DecodedImageInfo() {
|
| -}
|
| -
|
| -MacVideoDecodeAccelerator::DecodedImageInfo::~DecodedImageInfo() {
|
| -}
|
| -
|
| -} // namespace content
|
|
|