blob: e9abe182cf8fe2683abc4e61b0b44c18f53b2568 [file] [log] [blame]
// Copyright 2016 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 "media/gpu/ipc/service/media_gpu_channel.h"
#include "base/unguessable_token.h"
#include "gpu/ipc/service/gpu_channel.h"
#include "ipc/message_filter.h"
#include "media/gpu/ipc/common/media_messages.h"
#include "media/gpu/ipc/service/gpu_video_decode_accelerator.h"
#include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
namespace media {
namespace {
void SendCreateJpegDecoderResult(
std::unique_ptr<IPC::Message> reply_message,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
base::WeakPtr<gpu::GpuChannel> channel,
scoped_refptr<gpu::GpuChannelMessageFilter> filter,
bool result) {
GpuChannelMsg_CreateJpegDecoder::WriteReplyParams(reply_message.get(),
result);
if (io_task_runner->BelongsToCurrentThread()) {
filter->Send(reply_message.release());
} else if (channel) {
channel->Send(reply_message.release());
}
}
} // namespace
class MediaGpuChannelDispatchHelper {
public:
MediaGpuChannelDispatchHelper(MediaGpuChannel* channel, int32_t routing_id)
: channel_(channel), routing_id_(routing_id) {}
bool Send(IPC::Message* msg) { return channel_->Send(msg); }
void OnCreateVideoDecoder(const VideoDecodeAccelerator::Config& config,
int32_t decoder_route_id,
IPC::Message* reply_message) {
channel_->OnCreateVideoDecoder(routing_id_, config, decoder_route_id,
reply_message);
}
void OnCreateVideoEncoder(const CreateVideoEncoderParams& params,
IPC::Message* reply_message) {
channel_->OnCreateVideoEncoder(routing_id_, params, reply_message);
}
private:
MediaGpuChannel* const channel_;
const int32_t routing_id_;
DISALLOW_COPY_AND_ASSIGN(MediaGpuChannelDispatchHelper);
};
// Filter to respond to GetChannelToken on the IO thread.
class MediaGpuChannelFilter : public IPC::MessageFilter {
public:
explicit MediaGpuChannelFilter(const base::UnguessableToken& channel_token)
: channel_token_(channel_token) {}
void OnFilterAdded(IPC::Channel* channel) override { channel_ = channel; }
bool Send(IPC::Message* msg) { return channel_->Send(msg); }
bool OnMessageReceived(const IPC::Message& msg) override {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaGpuChannelFilter, msg)
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_GetChannelToken,
OnGetChannelToken)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void OnGetChannelToken(IPC::Message* reply_message) {
GpuCommandBufferMsg_GetChannelToken::WriteReplyParams(reply_message,
channel_token_);
Send(reply_message);
}
private:
~MediaGpuChannelFilter() override {}
IPC::Channel* channel_;
base::UnguessableToken channel_token_;
};
MediaGpuChannel::MediaGpuChannel(gpu::GpuChannel* channel,
const base::UnguessableToken& channel_token)
: channel_(channel) {
channel_->AddFilter(new MediaGpuChannelFilter(channel_token));
}
MediaGpuChannel::~MediaGpuChannel() {}
bool MediaGpuChannel::Send(IPC::Message* msg) {
return channel_->Send(msg);
}
bool MediaGpuChannel::OnMessageReceived(const IPC::Message& message) {
MediaGpuChannelDispatchHelper helper(this, message.routing_id());
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(MediaGpuChannel, message)
IPC_MESSAGE_FORWARD_DELAY_REPLY(
GpuCommandBufferMsg_CreateVideoDecoder, &helper,
MediaGpuChannelDispatchHelper::OnCreateVideoDecoder)
IPC_MESSAGE_FORWARD_DELAY_REPLY(
GpuCommandBufferMsg_CreateVideoEncoder, &helper,
MediaGpuChannelDispatchHelper::OnCreateVideoEncoder)
IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateJpegDecoder,
OnCreateJpegDecoder)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void MediaGpuChannel::OnCreateJpegDecoder(int32_t route_id,
IPC::Message* reply_msg) {
std::unique_ptr<IPC::Message> msg(reply_msg);
if (!jpeg_decoder_) {
jpeg_decoder_.reset(
new GpuJpegDecodeAccelerator(channel_, channel_->io_task_runner()));
}
jpeg_decoder_->AddClient(
route_id, base::Bind(&SendCreateJpegDecoderResult, base::Passed(&msg),
channel_->io_task_runner(), channel_->AsWeakPtr(),
make_scoped_refptr(channel_->filter())));
}
void MediaGpuChannel::OnCreateVideoDecoder(
int32_t command_buffer_route_id,
const VideoDecodeAccelerator::Config& config,
int32_t decoder_route_id,
IPC::Message* reply_message) {
TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoDecoder");
gpu::GpuCommandBufferStub* stub =
channel_->LookupCommandBuffer(command_buffer_route_id);
if (!stub) {
reply_message->set_reply_error();
Send(reply_message);
return;
}
GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
decoder_route_id, stub, stub->channel()->io_task_runner());
bool succeeded = decoder->Initialize(config);
GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(reply_message,
succeeded);
Send(reply_message);
// decoder is registered as a DestructionObserver of this stub and will
// self-delete during destruction of this stub.
}
void MediaGpuChannel::OnCreateVideoEncoder(
int32_t command_buffer_route_id,
const CreateVideoEncoderParams& params,
IPC::Message* reply_message) {
TRACE_EVENT0("gpu", "MediaGpuChannel::OnCreateVideoEncoder");
gpu::GpuCommandBufferStub* stub =
channel_->LookupCommandBuffer(command_buffer_route_id);
if (!stub) {
reply_message->set_reply_error();
Send(reply_message);
return;
}
GpuVideoEncodeAccelerator* encoder = new GpuVideoEncodeAccelerator(
params.encoder_route_id, stub, stub->channel()->io_task_runner());
bool succeeded =
encoder->Initialize(params.input_format, params.input_visible_size,
params.output_profile, params.initial_bitrate);
GpuCommandBufferMsg_CreateVideoEncoder::WriteReplyParams(reply_message,
succeeded);
Send(reply_message);
// encoder is registered as a DestructionObserver of this stub and will
// self-delete during destruction of this stub.
}
} // namespace media