summaryrefslogtreecommitdiffstats
path: root/chrome/gpu
diff options
context:
space:
mode:
authorjiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-17 16:07:36 +0000
committerjiesun@google.com <jiesun@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-17 16:07:36 +0000
commite9a7fe502718d74531d6d1d31be83339f1757ded (patch)
tree15487c63e6387007c3da65fe9690c6db09e95b96 /chrome/gpu
parent1a03607bd3e686d79e327a714b819f56daf18586 (diff)
downloadchromium_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')
-rw-r--r--chrome/gpu/DEPS2
-rw-r--r--chrome/gpu/gpu_video_decoder.cc223
-rw-r--r--chrome/gpu/gpu_video_decoder.h66
-rw-r--r--chrome/gpu/gpu_video_service.cc9
4 files changed, 261 insertions, 39 deletions
diff --git a/chrome/gpu/DEPS b/chrome/gpu/DEPS
index f071f77..03e6502 100644
--- a/chrome/gpu/DEPS
+++ b/chrome/gpu/DEPS
@@ -1,5 +1,7 @@
include_rules = [
"+chrome/app",
"+gpu/command_buffer",
+ "+media/base",
+ "+media/filters",
]
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_,
+ &param.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_,
+ &param.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(
diff --git a/chrome/gpu/gpu_video_decoder.h b/chrome/gpu/gpu_video_decoder.h
index 62170fe..caed871 100644
--- a/chrome/gpu/gpu_video_decoder.h
+++ b/chrome/gpu/gpu_video_decoder.h
@@ -10,13 +10,21 @@
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "chrome/common/gpu_video_common.h"
+#include "media/filters/video_decode_engine.h"
#include "ipc/ipc_channel.h"
class GpuChannel;
+using media::VideoCodecConfig;
+using media::VideoCodecInfo;
+using media::VideoStreamInfo;
+using media::VideoFrame;
+using media::Buffer;
+
class GpuVideoDecoder
: public IPC::Channel::Listener,
- public base::RefCountedThreadSafe<GpuVideoDecoder> {
+ public base::RefCountedThreadSafe<GpuVideoDecoder>,
+ public media::VideoDecodeEngine::EventHandler {
public:
// IPC::Channel::Listener.
@@ -24,43 +32,47 @@ class GpuVideoDecoder
virtual void OnChannelError();
virtual void OnMessageReceived(const IPC::Message& message);
- virtual bool DoInitialize(const GpuVideoDecoderInitParam& init_param,
- GpuVideoDecoderInitDoneParam* done_param) = 0;
- virtual bool DoUninitialize() = 0;
- virtual void DoFlush() = 0;
- virtual void DoEmptyThisBuffer(
- const GpuVideoDecoderInputBufferParam& buffer) = 0;
- virtual void DoFillThisBuffer(
- const GpuVideoDecoderOutputBufferParam& frame) = 0;
- virtual void DoFillThisBufferDoneACK() = 0;
+ // VideoDecodeEngine::EventHandler.
+ virtual void OnInitializeComplete(const VideoCodecInfo& info);
+ virtual void OnUninitializeComplete();
+ virtual void OnFlushComplete();
+ virtual void OnSeekComplete();
+ virtual void OnError();
+ virtual void OnFormatChange(VideoStreamInfo stream_info);
+ virtual void OnEmptyBufferCallback(scoped_refptr<Buffer> buffer);
+ virtual void OnFillBufferCallback(scoped_refptr<VideoFrame> frame);
GpuVideoDecoder(const GpuVideoDecoderInfoParam* param,
GpuChannel* channel_,
base::ProcessHandle handle);
virtual ~GpuVideoDecoder() {}
- protected:
- // Output message helper.
- void SendInitializeDone(const GpuVideoDecoderInitDoneParam& param);
- void SendUninitializeDone();
- void SendFlushDone();
- void SendEmptyBufferDone();
- void SendEmptyBufferACK();
- void SendFillBufferDone(const GpuVideoDecoderOutputBufferParam& frame);
-
+ private:
int32 route_id() { return decoder_host_route_id_; }
+ bool CreateInputTransferBuffer(uint32 size,
+ base::SharedMemoryHandle* handle);
+ bool CreateOutputTransferBuffer(uint32 size,
+ base::SharedMemoryHandle* handle);
+ void CreateVideoFrameOnTransferBuffer();
+
int32 decoder_host_route_id_;
+
+ // Used only in system memory path. i.e. Remove this later.
+ scoped_refptr<VideoFrame> frame_;
+ bool output_transfer_buffer_busy_;
+ int32 pending_output_requests_;
+
GpuChannel* channel_;
base::ProcessHandle renderer_handle_;
- GpuVideoDecoderInitParam init_param_;
- GpuVideoDecoderInitDoneParam done_param_;
-
scoped_ptr<base::SharedMemory> input_transfer_buffer_;
scoped_ptr<base::SharedMemory> output_transfer_buffer_;
- private:
+ scoped_ptr<media::VideoDecodeEngine> decode_engine_;
+ media::VideoCodecConfig config_;
+ media::VideoCodecInfo info_;
+
// Input message handler.
void OnInitialize(const GpuVideoDecoderInitParam& param);
void OnUninitialize();
@@ -69,6 +81,14 @@ class GpuVideoDecoder
void OnFillThisBuffer(const GpuVideoDecoderOutputBufferParam& frame);
void OnFillThisBufferDoneACK();
+ // Output message helper.
+ void SendInitializeDone(const GpuVideoDecoderInitDoneParam& param);
+ void SendUninitializeDone();
+ void SendFlushDone();
+ void SendEmptyBufferDone();
+ void SendEmptyBufferACK();
+ void SendFillBufferDone(const GpuVideoDecoderOutputBufferParam& frame);
+
DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder);
};
diff --git a/chrome/gpu/gpu_video_service.cc b/chrome/gpu/gpu_video_service.cc
index 78b95fd..bc95936 100644
--- a/chrome/gpu/gpu_video_service.cc
+++ b/chrome/gpu/gpu_video_service.cc
@@ -4,6 +4,7 @@
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_channel.h"
+#include "chrome/gpu/gpu_video_decoder.h"
#include "chrome/gpu/gpu_video_service.h"
GpuVideoService::GpuVideoService() : next_available_decoder_id_(0) {
@@ -43,22 +44,16 @@ bool GpuVideoService::CreateVideoDecoder(
GpuChannel* channel,
MessageRouter* router,
GpuVideoDecoderInfoParam* param) {
- // TODO(jiesun): find a better way to determine which GpuVideoDecoder
- // to return on current platform.
-#if defined(ENABLE_MFT_DECODER)
GpuVideoDecoderInfo decoder_info;
int32 decoder_id = GetNextAvailableDecoderID();
param->decoder_id_ = decoder_id;
base::ProcessHandle handle = channel->renderer_handle();
- decoder_info.decoder_ = new GpuVideoDecoderMFT(param, channel, handle);
+ decoder_info.decoder_ = new GpuVideoDecoder(param, channel, handle);
decoder_info.channel_ = channel;
decoder_info.param = *param;
decoder_map_[decoder_id] = decoder_info;
router->AddRoute(param->decoder_route_id_, decoder_info.decoder_);
return true;
-#else
- return false;
-#endif
}
void GpuVideoService::DestroyVideoDecoder(