diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 15:53:30 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-13 15:53:30 +0000 |
commit | 768708171bb6c8dec34509c11460d3bc355a3e81 (patch) | |
tree | 0759c4e4c4fc9bd6d115e5e4ade74f81225756ff /chrome/gpu | |
parent | 8f8b6b856f85ec92504ca3e48ea4e0d0886ac7b2 (diff) | |
download | chromium_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.cc | 14 | ||||
-rw-r--r-- | chrome/gpu/gpu_video_decoder.cc | 122 | ||||
-rw-r--r-- | chrome/gpu/gpu_video_decoder.h | 7 | ||||
-rw-r--r-- | chrome/gpu/media/fake_gl_video_decode_engine.cc | 88 | ||||
-rw-r--r-- | chrome/gpu/media/fake_gl_video_decode_engine.h | 39 |
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_, - ¶m.input_buffer_handle_)) { + 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) { + 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_, - ¶m.output_buffer_handle_)) { + if (!CreateOutputTransferBuffer(param.output_buffer_size, + ¶m.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_ |