summaryrefslogtreecommitdiffstats
path: root/chrome/gpu
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-13 15:53:30 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-13 15:53:30 +0000
commit768708171bb6c8dec34509c11460d3bc355a3e81 (patch)
tree0759c4e4c4fc9bd6d115e5e4ade74f81225756ff /chrome/gpu
parent8f8b6b856f85ec92504ca3e48ea4e0d0886ac7b2 (diff)
downloadchromium_src-768708171bb6c8dec34509c11460d3bc355a3e81.zip
chromium_src-768708171bb6c8dec34509c11460d3bc355a3e81.tar.gz
chromium_src-768708171bb6c8dec34509c11460d3bc355a3e81.tar.bz2
Added FakeGlVideoDecodeEngine to exercise the IPC protocol for hardware video decoding
There are several things done in this patch: 1. Added FakeGlVideoDecodeEngine 2. Fixed style problem in VideoDecodeEngine and gpu_video_common.h 3. Added route to pass texture from gpu process to WebKit BUG=53714 TEST=Tree is green Review URL: http://codereview.chromium.org/3335014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59223 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/gpu')
-rw-r--r--chrome/gpu/gpu_channel.cc14
-rw-r--r--chrome/gpu/gpu_video_decoder.cc122
-rw-r--r--chrome/gpu/gpu_video_decoder.h7
-rw-r--r--chrome/gpu/media/fake_gl_video_decode_engine.cc88
-rw-r--r--chrome/gpu/media/fake_gl_video_decode_engine.h39
5 files changed, 205 insertions, 65 deletions
diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc
index ea20f22..56ba079 100644
--- a/chrome/gpu/gpu_channel.cc
+++ b/chrome/gpu/gpu_channel.cc
@@ -186,22 +186,18 @@ void GpuChannel::OnDestroyCommandBuffer(int32 route_id) {
}
void GpuChannel::OnGetVideoService(GpuVideoServiceInfoParam* info) {
- info->service_available_ = 0;
+ info->service_available = 0;
#if defined(ENABLE_GPU)
-#if defined(OS_WIN)
- // TODO(jiesun): Not every windows platforms will support our media
- // foundation implementation. Add more check here.
LOG(INFO) << "GpuChannel::OnGetVideoService";
GpuVideoService* service = GpuVideoService::get();
if (service == NULL)
return;
- info->video_service_host_route_id_ = GenerateRouteID();
- info->video_service_route_id_ = GenerateRouteID();
+ info->video_service_host_route_id = GenerateRouteID();
+ info->video_service_route_id = GenerateRouteID();
// TODO(jiesun): we could had multiple entries in this routing table.
- router_.AddRoute(info->video_service_route_id_, service);
- info->service_available_ = 1;
-#endif
+ router_.AddRoute(info->video_service_route_id, service);
+ info->service_available = 1;
#endif
}
diff --git a/chrome/gpu/gpu_video_decoder.cc b/chrome/gpu/gpu_video_decoder.cc
index 9c948aa..68d0dbd 100644
--- a/chrome/gpu/gpu_video_decoder.cc
+++ b/chrome/gpu/gpu_video_decoder.cc
@@ -6,6 +6,7 @@
#include "chrome/common/gpu_messages.h"
#include "chrome/gpu/gpu_channel.h"
+#include "chrome/gpu/media/fake_gl_video_decode_engine.h"
#include "media/base/data_buffer.h"
#include "media/base/video_frame.h"
@@ -78,14 +79,14 @@ void GpuVideoDecoder::CreateVideoFrameOnTransferBuffer() {
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;
+ 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,
+ config_.width, config_.height, 3,
data, strides,
kZero, kZero,
NULL,
@@ -95,68 +96,62 @@ void GpuVideoDecoder::CreateVideoFrameOnTransferBuffer() {
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();
+ param.success = false;
+ param.input_buffer_handle = base::SharedMemory::NULLHandle();
+ param.output_buffer_handle = base::SharedMemory::NULLHandle();
- if (!info.success_) {
+ 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;
- default:
- NOTREACHED();
- }
+ param.surface_type = static_cast<GpuVideoDecoderInitDoneParam::SurfaceType>(
+ info.stream_info.surface_type);
// Translate surface format.
- switch (info.stream_info_.surface_format_) {
+ switch (info.stream_info.surface_format) {
case VideoFrame::YV12:
- param.format_ = GpuVideoDecoderInitDoneParam::SurfaceFormat_YV12;
+ param.format = GpuVideoDecoderInitDoneParam::SurfaceFormat_YV12;
break;
+ case VideoFrame::RGBA:
+ param.format = GpuVideoDecoderInitDoneParam::SurfaceFormat_RGBA;
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_)) {
+ 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) {
+ 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_) {
+ 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;
+ param.output_buffer_size =
+ config_.width * config_.height * 3 / 2;
break;
default:
NOTREACHED();
}
- if (!CreateOutputTransferBuffer(param.output_buffer_size_,
- &param.output_buffer_handle_)) {
+ if (!CreateOutputTransferBuffer(param.output_buffer_size,
+ &param.output_buffer_handle)) {
SendInitializeDone(param);
return;
}
-
CreateVideoFrameOnTransferBuffer();
}
- param.success_ = true;
+ param.success = true;
SendInitializeDone(param);
}
@@ -187,10 +182,14 @@ void GpuVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) {
void GpuVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) {
GpuVideoDecoderOutputBufferParam output_param;
- output_param.timestamp_ = frame->GetTimestamp().InMicroseconds();
- output_param.duration_ = frame->GetDuration().InMicroseconds();
- output_param.flags_ = frame->IsEndOfStream() ?
+ output_param.timestamp = frame->GetTimestamp().InMicroseconds();
+ output_param.duration = frame->GetDuration().InMicroseconds();
+ output_param.flags = frame->IsEndOfStream() ?
GpuVideoDecoderOutputBufferParam::kFlagsEndOfStream : 0;
+ // TODO(hclam): We should have the conversion between VideoFrame and the
+ // IPC transport param done in GpuVideoDecodeContext.
+ // This is a hack to pass texture back as a param.
+ output_param.texture = frame->gl_texture(media::VideoFrame::kRGBPlane);
SendFillBufferDone(output_param);
}
@@ -207,20 +206,20 @@ GpuVideoDecoder::GpuVideoDecoder(
gles2_decoder_(decoder) {
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
+
+ // TODO(jiesun): find a better way to determine which VideoDecodeEngine
// to return on current platform.
- decode_engine_.reset(new GpuVideoDecoderMFT());
-#else
-#endif
+ decode_engine_.reset(new FakeGlVideoDecodeEngine());
}
void GpuVideoDecoder::OnInitialize(const GpuVideoDecoderInitParam& param) {
+ // TODO(hclam): Initialize the VideoDecodeContext first.
+
// TODO(jiesun): codec id should come from |param|.
- config_.codec_ = media::kCodecH264;
- config_.width_ = param.width_;
- config_.height_ = param.height_;
- config_.opaque_context_ = NULL;
+ config_.codec = media::kCodecH264;
+ config_.width = param.width;
+ config_.height = param.height;
+ config_.opaque_context = NULL;
decode_engine_->Initialize(NULL, this, config_);
}
@@ -243,28 +242,47 @@ void GpuVideoDecoder::OnEmptyThisBuffer(
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_);
+ 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_->ConsumeVideoSample(input_buffer);
}
+
void GpuVideoDecoder::OnFillThisBuffer(
- const GpuVideoDecoderOutputBufferParam& frame) {
- if (info_.stream_info_.surface_type_ == VideoFrame::TYPE_SYSTEM_MEMORY) {
+ const GpuVideoDecoderOutputBufferParam& param) {
+ // Switch context before calling to the decode engine.
+ // TODO(hclam): This is temporary to allow FakeGlVideoDecodeEngine to issue
+ // GL commands correctly.
+ bool ret = gles2_decoder_->MakeCurrent();
+ DCHECK(ret) << "Failed to switch context";
+
+ 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_->ProduceVideoFrame(frame_);
}
} else {
- decode_engine_->ProduceVideoFrame(frame_);
+ // TODO(hclam): I need to rethink how to delegate calls to
+ // VideoDecodeEngine, I may need to create a GpuVideoDecodeContext that
+ // provides a method for me to make calls to VideoDecodeEngine with the
+ // correct VideoFrame.
+ DCHECK_EQ(VideoFrame::TYPE_GL_TEXTURE, info_.stream_info.surface_type);
+
+ scoped_refptr<media::VideoFrame> frame;
+ VideoFrame::GlTexture textures[3] = { param.texture, 0, 0 };
+
+ media::VideoFrame:: CreateFrameGlTexture(
+ media::VideoFrame::RGBA, config_.width, config_.height, textures,
+ base::TimeDelta(), base::TimeDelta(), &frame);
+ decode_engine_->ProduceVideoFrame(frame);
}
}
void GpuVideoDecoder::OnFillThisBufferDoneACK() {
- if (info_.stream_info_.surface_type_ == VideoFrame::TYPE_SYSTEM_MEMORY) {
+ if (info_.stream_info.surface_type == VideoFrame::TYPE_SYSTEM_MEMORY) {
output_transfer_buffer_busy_ = false;
pending_output_requests_--;
if (pending_output_requests_) {
@@ -309,9 +327,9 @@ void GpuVideoDecoder::SendEmptyBufferACK() {
}
void GpuVideoDecoder::SendFillBufferDone(
- const GpuVideoDecoderOutputBufferParam& frame) {
+ const GpuVideoDecoderOutputBufferParam& param) {
if (!channel_->Send(
- new GpuVideoDecoderHostMsg_FillThisBufferDone(route_id(), frame))) {
+ new GpuVideoDecoderHostMsg_FillThisBufferDone(route_id(), param))) {
LOG(ERROR) << "GpuVideoDecoderMsg_FillThisBufferDone failed";
}
}
diff --git a/chrome/gpu/gpu_video_decoder.h b/chrome/gpu/gpu_video_decoder.h
index 728222c..9aba2b5 100644
--- a/chrome/gpu/gpu_video_decoder.h
+++ b/chrome/gpu/gpu_video_decoder.h
@@ -74,8 +74,7 @@ class GpuVideoDecoder
base::ProcessHandle renderer_handle_;
// The GLES2 decoder has the context associated with this decoder. This object
- // is used to switch GLES2 context and translate client texture ID to service
- // ID.
+ // is used to switch context and translate client texture ID to service ID.
gpu::gles2::GLES2Decoder* gles2_decoder_;
scoped_ptr<base::SharedMemory> input_transfer_buffer_;
@@ -90,7 +89,7 @@ class GpuVideoDecoder
void OnUninitialize();
void OnFlush();
void OnEmptyThisBuffer(const GpuVideoDecoderInputBufferParam& buffer);
- void OnFillThisBuffer(const GpuVideoDecoderOutputBufferParam& frame);
+ void OnFillThisBuffer(const GpuVideoDecoderOutputBufferParam& param);
void OnFillThisBufferDoneACK();
// Output message helper.
@@ -99,7 +98,7 @@ class GpuVideoDecoder
void SendFlushDone();
void SendEmptyBufferDone();
void SendEmptyBufferACK();
- void SendFillBufferDone(const GpuVideoDecoderOutputBufferParam& frame);
+ void SendFillBufferDone(const GpuVideoDecoderOutputBufferParam& param);
DISALLOW_COPY_AND_ASSIGN(GpuVideoDecoder);
};
diff --git a/chrome/gpu/media/fake_gl_video_decode_engine.cc b/chrome/gpu/media/fake_gl_video_decode_engine.cc
new file mode 100644
index 0000000..52e2dfd
--- /dev/null
+++ b/chrome/gpu/media/fake_gl_video_decode_engine.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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 "chrome/gpu/media/fake_gl_video_decode_engine.h"
+
+#include "app/gfx/gl/gl_bindings.h"
+
+FakeGlVideoDecodeEngine::FakeGlVideoDecodeEngine()
+ : width_(0),
+ height_(0),
+ handler_(NULL) {
+}
+
+FakeGlVideoDecodeEngine::~FakeGlVideoDecodeEngine() {
+}
+
+void FakeGlVideoDecodeEngine::Initialize(
+ MessageLoop* message_loop,
+ media::VideoDecodeEngine::EventHandler* event_handler,
+ const media::VideoCodecConfig& config) {
+ handler_ = event_handler;
+ width_ = config.width;
+ height_ = config.height;
+
+ media::VideoCodecInfo info;
+ info.success = true;
+ info.provides_buffers = true;
+ info.stream_info.surface_format = media::VideoFrame::RGBA;
+ info.stream_info.surface_type = media::VideoFrame::TYPE_GL_TEXTURE;
+ info.stream_info.surface_width = width_;
+ info.stream_info.surface_height = height_;
+
+ // TODO(hclam): When we have VideoDecodeContext we should use it to allocate
+ // video frames.
+ handler_->OnInitializeComplete(info);
+}
+
+void FakeGlVideoDecodeEngine::Uninitialize() {
+ handler_->OnUninitializeComplete();
+}
+
+void FakeGlVideoDecodeEngine::Flush() {
+ handler_->OnFlushComplete();
+}
+
+void FakeGlVideoDecodeEngine::Seek() {
+ handler_->OnSeekComplete();
+}
+
+void FakeGlVideoDecodeEngine::ConsumeVideoSample(
+ scoped_refptr<media::Buffer> buffer) {
+ // Don't care.
+}
+
+void FakeGlVideoDecodeEngine::ProduceVideoFrame(
+ scoped_refptr<media::VideoFrame> frame) {
+ // Fake that we need some buffer.
+ handler_->ProduceVideoSample(NULL);
+
+ int size = width_ * height_ * 4;
+ scoped_array<uint8> buffer(new uint8[size]);
+ memset(buffer.get(), 0, size);
+
+ uint8* row = buffer.get();
+ static int seed = 0;
+
+ for (int y = 0; y < height_; ++y) {
+ int offset = y % 3;
+ for (int x = 0; x < width_; ++x) {
+ row[x * 4 + offset] = seed++;
+ seed &= 255;
+ }
+ row += width_ * 4;
+ }
+ ++seed;
+
+ // Assume we are in the right context and then upload the content to the
+ // texture.
+ glBindTexture(GL_TEXTURE_2D,
+ frame->gl_texture(media::VideoFrame::kRGBPlane));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, buffer.get());
+
+ // We have done generating data to the frame so give it to the handler.
+ // TODO(hclam): Advance the timestamp every time we call this method.
+ handler_->ConsumeVideoFrame(frame);
+}
diff --git a/chrome/gpu/media/fake_gl_video_decode_engine.h b/chrome/gpu/media/fake_gl_video_decode_engine.h
new file mode 100644
index 0000000..c3eeb3e
--- /dev/null
+++ b/chrome/gpu/media/fake_gl_video_decode_engine.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2010 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.
+
+#ifndef CHROME_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_
+#define CHROME_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_
+
+#include "base/scoped_ptr.h"
+#include "media/video/video_decode_engine.h"
+
+namespace media {
+class VideoFrame;
+} // namespace media
+
+class FakeGlVideoDecodeEngine : public media::VideoDecodeEngine {
+ public:
+ FakeGlVideoDecodeEngine();
+ virtual ~FakeGlVideoDecodeEngine();
+
+ virtual void Initialize(
+ MessageLoop* message_loop,
+ media::VideoDecodeEngine::EventHandler* event_handler,
+ const media::VideoCodecConfig& config);
+
+ virtual void Uninitialize();
+ virtual void Flush();
+ virtual void Seek();
+ virtual void ConsumeVideoSample(scoped_refptr<media::Buffer> buffer);
+ virtual void ProduceVideoFrame(scoped_refptr<media::VideoFrame> frame);
+
+ private:
+ int width_;
+ int height_;
+ media::VideoDecodeEngine::EventHandler* handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeGlVideoDecodeEngine);
+};
+
+#endif // CHROME_GPU_MEDIA_FAKE_GL_VIDEO_DECODE_ENGINE_H_