diff options
author | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-17 16:07:36 +0000 |
---|---|---|
committer | jiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-17 16:07:36 +0000 |
commit | e9a7fe502718d74531d6d1d31be83339f1757ded (patch) | |
tree | 15487c63e6387007c3da65fe9690c6db09e95b96 /chrome/gpu/gpu_video_decoder.cc | |
parent | 1a03607bd3e686d79e327a714b819f56daf18586 (diff) | |
download | chromium_src-e9a7fe502718d74531d6d1d31be83339f1757ded.zip chromium_src-e9a7fe502718d74531d6d1d31be83339f1757ded.tar.gz chromium_src-e9a7fe502718d74531d6d1d31be83339f1757ded.tar.bz2 |
media: use VideoDecodeEngine interface in gpu_video_decoder abstraction.
some logics are moved into system memory path only. ( such as allocation of output buffer, and usage of FTBDoneACK messages.
Review URL: http://codereview.chromium.org/3141014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56358 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/gpu/gpu_video_decoder.cc')
-rw-r--r-- | chrome/gpu/gpu_video_decoder.cc | 223 |
1 files changed, 214 insertions, 9 deletions
diff --git a/chrome/gpu/gpu_video_decoder.cc b/chrome/gpu/gpu_video_decoder.cc index 42a7383..1a4a7f6 100644 --- a/chrome/gpu/gpu_video_decoder.cc +++ b/chrome/gpu/gpu_video_decoder.cc @@ -5,6 +5,7 @@ #include "chrome/common/gpu_messages.h" #include "chrome/gpu/gpu_channel.h" #include "chrome/gpu/gpu_video_decoder.h" +#include "media/base/data_buffer.h" void GpuVideoDecoder::OnChannelConnected(int32 peer_pid) { } @@ -30,41 +31,245 @@ void GpuVideoDecoder::OnMessageReceived(const IPC::Message& msg) { IPC_END_MESSAGE_MAP() } +bool GpuVideoDecoder::CreateInputTransferBuffer( + uint32 size, + base::SharedMemoryHandle* handle) { + input_transfer_buffer_.reset(new base::SharedMemory); + if (!input_transfer_buffer_.get()) + return false; + + if (!input_transfer_buffer_->Create(std::wstring(), false, false, size)) + return false; + + if (!input_transfer_buffer_->Map(size)) + return false; + + if (!input_transfer_buffer_->ShareToProcess(renderer_handle_, handle)) + return false; + + return true; +} + +bool GpuVideoDecoder::CreateOutputTransferBuffer( + uint32 size, + base::SharedMemoryHandle* handle) { + output_transfer_buffer_.reset(new base::SharedMemory); + if (!output_transfer_buffer_.get()) + return false; + + if (!output_transfer_buffer_->Create(std::wstring(), false, false, size)) + return false; + + if (!output_transfer_buffer_->Map(size)) + return false; + + if (!output_transfer_buffer_->ShareToProcess(renderer_handle_, handle)) + return false; + + return true; +} + +void GpuVideoDecoder::CreateVideoFrameOnTransferBuffer() { + const base::TimeDelta kZero; + uint8* data[media::VideoFrame::kMaxPlanes]; + int32 strides[media::VideoFrame::kMaxPlanes]; + memset(data, 0, sizeof(data)); + memset(strides, 0, sizeof(strides)); + data[0] = static_cast<uint8*>(output_transfer_buffer_->memory()); + data[1] = data[0] + config_.width_ * config_.height_; + data[2] = data[1] + config_.width_ * config_.height_ / 4; + strides[0] = config_.width_; + strides[1] = strides[2] = config_.width_ >> 1; + media::VideoFrame:: CreateFrameExternal( + media::VideoFrame::TYPE_SYSTEM_MEMORY, + media::VideoFrame::YV12, + config_.width_, config_.height_, 3, + data, strides, + kZero, kZero, + NULL, + &frame_); +} + +void GpuVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { + info_ = info; + GpuVideoDecoderInitDoneParam param; + param.success_ = false; + param.input_buffer_handle_ = base::SharedMemory::NULLHandle(); + param.output_buffer_handle_ = base::SharedMemory::NULLHandle(); + + if (!info.success_) { + SendInitializeDone(param); + return; + } + + // Translate surface type. + switch (info.stream_info_.surface_type_) { + case VideoFrame::TYPE_SYSTEM_MEMORY: + param.surface_type_ = + GpuVideoDecoderInitDoneParam::SurfaceTypeSystemMemory; + break; + case VideoFrame::TYPE_DIRECT3DSURFACE: + case VideoFrame::TYPE_EGL_IMAGE: + default: + NOTREACHED(); + } + + // Translate surface format. + switch (info.stream_info_.surface_format_) { + case VideoFrame::YV12: + param.format_ = GpuVideoDecoderInitDoneParam::SurfaceFormat_YV12; + break; + default: + NOTREACHED(); + } + + // TODO(jiesun): Check the assumption of input size < original size. + param.input_buffer_size_ = config_.width_ * config_.height_ * 3 / 2; + if (!CreateInputTransferBuffer(param.input_buffer_size_, + ¶m.input_buffer_handle_)) { + SendInitializeDone(param); + return; + } + + if (info.stream_info_.surface_type_ == VideoFrame::TYPE_SYSTEM_MEMORY) { + // TODO(jiesun): Allocate this according to the surface format. + // The format actually could change during streaming, we need to + // notify GpuVideoDecoderHost side when this happened and renegotiate + // the transfer buffer. + + switch (info.stream_info_.surface_format_) { + case VideoFrame::YV12: + // TODO(jiesun): take stride into account. + param.output_buffer_size_ = + config_.width_ * config_.height_ * 3 / 2; + break; + default: + NOTREACHED(); + } + + if (!CreateOutputTransferBuffer(param.output_buffer_size_, + ¶m.output_buffer_handle_)) { + SendInitializeDone(param); + return; + } + + CreateVideoFrameOnTransferBuffer(); + } + + param.success_ = true; + + SendInitializeDone(param); +} + +void GpuVideoDecoder::OnUninitializeComplete() { + SendUninitializeDone(); +} + +void GpuVideoDecoder::OnFlushComplete() { + SendFlushDone(); +} + +void GpuVideoDecoder::OnSeekComplete() { + NOTIMPLEMENTED(); +} + +void GpuVideoDecoder::OnError() { + NOTIMPLEMENTED(); +} + +void GpuVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { + NOTIMPLEMENTED(); +} + +void GpuVideoDecoder::OnEmptyBufferCallback(scoped_refptr<Buffer> buffer) { + SendEmptyBufferDone(); +} + +void GpuVideoDecoder::OnFillBufferCallback(scoped_refptr<VideoFrame> frame) { + GpuVideoDecoderOutputBufferParam output_param; + output_param.timestamp_ = frame->GetTimestamp().InMicroseconds(); + output_param.duration_ = frame->GetDuration().InMicroseconds(); + output_param.flags_ = frame->IsEndOfStream() ? + GpuVideoDecoderOutputBufferParam::kFlagsEndOfStream : 0; + SendFillBufferDone(output_param); +} + GpuVideoDecoder::GpuVideoDecoder( const GpuVideoDecoderInfoParam* param, GpuChannel* channel, base::ProcessHandle handle) : decoder_host_route_id_(param->decoder_host_route_id_), + output_transfer_buffer_busy_(false), + pending_output_requests_(0), channel_(channel), renderer_handle_(handle) { - memset(&init_param_, 0, sizeof(init_param_)); - memset(&done_param_, 0, sizeof(done_param_)); + memset(&config_, 0, sizeof(config_)); + memset(&info_, 0, sizeof(info_)); +#if defined(OS_WIN) && defined(ENABLE_GPU_DECODER) + // TODO(jiesun): find a better way to determine which GpuVideoDecoder + // to return on current platform. + decode_engine_.reset(new GpuVideoDecoderMFT()); +#else +#endif } void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) { - init_param_ = param; - done_param_.success_ = DoInitialize(init_param_, &done_param_); + // TODO(jiesun): codec id should come from |param|. + config_.codec_ = media::kCodecH264; + config_.width_ = param.width_; + config_.height_ = param.height_; + config_.opaque_context_ = NULL; + decode_engine_->Initialize(NULL, this, config_); } void GpuVideoDecoder::OnUninitialize() { - DoUninitialize(); + decode_engine_->Uninitialize(); } void GpuVideoDecoder::OnFlush() { - DoFlush(); + // TODO(jiesun): this is wrong?? + output_transfer_buffer_busy_ = false; + pending_output_requests_ = 0; + + decode_engine_->Flush(); } void GpuVideoDecoder::OnEmptyThisBuffer( const GpuVideoDecoderInputBufferParam& buffer) { - DoEmptyThisBuffer(buffer); + DCHECK(input_transfer_buffer_->memory()); + + uint8* src = static_cast<uint8*>(input_transfer_buffer_->memory()); + + scoped_refptr<Buffer> input_buffer; + uint8* dst = buffer.size_ ? new uint8[buffer.size_] : NULL; + input_buffer = new media::DataBuffer(dst, buffer.size_); + memcpy(dst, src, buffer.size_); + SendEmptyBufferACK(); + + decode_engine_->EmptyThisBuffer(input_buffer); } void GpuVideoDecoder::OnFillThisBuffer( const GpuVideoDecoderOutputBufferParam& frame) { - DoFillThisBuffer(frame); + if (info_.stream_info_.surface_type_ == VideoFrame::TYPE_SYSTEM_MEMORY) { + pending_output_requests_++; + if (!output_transfer_buffer_busy_) { + output_transfer_buffer_busy_ = true; + decode_engine_->FillThisBuffer(frame_); + } + } else { + decode_engine_->FillThisBuffer(frame_); + } } void GpuVideoDecoder::OnFillThisBufferDoneACK() { - DoFillThisBufferDoneACK(); + if (info_.stream_info_.surface_type_ == VideoFrame::TYPE_SYSTEM_MEMORY) { + output_transfer_buffer_busy_ = false; + pending_output_requests_--; + if (pending_output_requests_) { + output_transfer_buffer_busy_ = true; + decode_engine_->FillThisBuffer(frame_); + } + } } void GpuVideoDecoder::SendInitializeDone( |