Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / common / gpu / media / fake_video_decode_accelerator.cc
blobeff497f48e7fbad6bb33a02ca00774ab59628a71
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/gpu/media/fake_video_decode_accelerator.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "media/base/bitstream_buffer.h"
11 #include "media/base/limits.h"
12 #include "ui/gl/gl_context.h"
13 #include "ui/gl/gl_implementation.h"
14 #include "ui/gl/gl_surface.h"
15 #include "ui/gl/gl_surface_egl.h"
16 #include "ui/gl/gl_surface_glx.h"
18 namespace content {
20 static const uint32 kDefaultTextureTarget = GL_TEXTURE_2D;
21 // Must be at least 2 since the rendering helper will switch between textures
22 // and if there is only one, it will wait for the next one that will never come.
23 // Must also be an even number as otherwise there won't be the same amount of
24 // white and black frames.
25 static const unsigned int kNumBuffers = media::limits::kMaxVideoFrames +
26 (media::limits::kMaxVideoFrames & 1u);
28 FakeVideoDecodeAccelerator::FakeVideoDecodeAccelerator(
29 gfx::GLContext* gl,
30 gfx::Size size,
31 const base::Callback<bool(void)>& make_context_current)
32 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
33 client_(NULL),
34 make_context_current_(make_context_current),
35 gl_(gl),
36 frame_buffer_size_(size),
37 flushing_(false),
38 weak_this_factory_(this) {
41 FakeVideoDecodeAccelerator::~FakeVideoDecodeAccelerator() {
44 bool FakeVideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile,
45 Client* client) {
46 DCHECK(child_task_runner_->BelongsToCurrentThread());
47 if (profile == media::VIDEO_CODEC_PROFILE_UNKNOWN) {
48 LOG(ERROR) << "unknown codec profile";
49 return false;
51 // V4L2VideoDecodeAccelerator waits until first decode call to ask for buffers
52 // This class asks for it on initialization instead.
53 client_ = client;
54 client_->ProvidePictureBuffers(kNumBuffers,
55 frame_buffer_size_,
56 kDefaultTextureTarget);
57 return true;
60 void FakeVideoDecodeAccelerator::Decode(
61 const media::BitstreamBuffer& bitstream_buffer) {
62 int bitstream_buffer_id = bitstream_buffer.id();
63 queued_bitstream_ids_.push(bitstream_buffer_id);
64 child_task_runner_->PostTask(
65 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
66 weak_this_factory_.GetWeakPtr()));
69 // Similar to UseOutputBitstreamBuffer for the encode accelerator.
70 void FakeVideoDecodeAccelerator::AssignPictureBuffers(
71 const std::vector<media::PictureBuffer>& buffers) {
72 DCHECK(buffers.size() == kNumBuffers);
73 DCHECK(!(buffers.size()%2));
75 // Save buffers and mark all buffers as ready for use.
76 scoped_ptr<uint8[]> white_data(
77 new uint8[frame_buffer_size_.width() * frame_buffer_size_.height() * 4]);
78 memset(white_data.get(),
79 UINT8_MAX,
80 frame_buffer_size_.width() * frame_buffer_size_.height() * 4);
81 scoped_ptr<uint8[]> black_data(
82 new uint8[frame_buffer_size_.width() * frame_buffer_size_.height() * 4]);
83 memset(black_data.get(),
85 frame_buffer_size_.width() * frame_buffer_size_.height() * 4);
86 if (!make_context_current_.Run()) {
87 LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
88 return;
90 for (size_t index = 0; index < buffers.size(); ++index) {
91 glBindTexture(GL_TEXTURE_2D, buffers[index].texture_id());
92 // Every other frame white and the rest black.
93 uint8* data = index%2 ? white_data.get():black_data.get();
94 glTexImage2D(GL_TEXTURE_2D,
96 GL_RGBA,
97 frame_buffer_size_.width(),
98 frame_buffer_size_.height(),
100 GL_RGBA,
101 GL_UNSIGNED_BYTE,
102 data);
103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
107 glBindTexture(GL_TEXTURE_2D, 0);
108 free_output_buffers_.push(buffers[index].id());
110 child_task_runner_->PostTask(
111 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
112 weak_this_factory_.GetWeakPtr()));
115 void FakeVideoDecodeAccelerator::ReusePictureBuffer(int32 picture_buffer_id) {
116 free_output_buffers_.push(picture_buffer_id);
117 child_task_runner_->PostTask(
118 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
119 weak_this_factory_.GetWeakPtr()));
122 void FakeVideoDecodeAccelerator::Flush() {
123 flushing_ = true;
124 child_task_runner_->PostTask(
125 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
126 weak_this_factory_.GetWeakPtr()));
129 void FakeVideoDecodeAccelerator::Reset() {
130 while (!queued_bitstream_ids_.empty()) {
131 client_->NotifyEndOfBitstreamBuffer(queued_bitstream_ids_.front());
132 queued_bitstream_ids_.pop();
134 client_->NotifyResetDone();
137 void FakeVideoDecodeAccelerator::Destroy() {
138 while (!queued_bitstream_ids_.empty()) {
139 client_->NotifyEndOfBitstreamBuffer(queued_bitstream_ids_.front());
140 queued_bitstream_ids_.pop();
142 delete this;
145 bool FakeVideoDecodeAccelerator::CanDecodeOnIOThread() {
146 return true;
149 void FakeVideoDecodeAccelerator::DoPictureReady() {
150 if (flushing_ && queued_bitstream_ids_.empty()) {
151 flushing_ = false;
152 client_->NotifyFlushDone();
154 while (!free_output_buffers_.empty() && !queued_bitstream_ids_.empty()) {
155 int bitstream_id = queued_bitstream_ids_.front();
156 queued_bitstream_ids_.pop();
157 int buffer_id = free_output_buffers_.front();
158 free_output_buffers_.pop();
160 const media::Picture picture =
161 media::Picture(buffer_id,
162 bitstream_id,
163 gfx::Rect(frame_buffer_size_),
164 false);
165 client_->PictureReady(picture);
166 // Bitstream no longer needed.
167 client_->NotifyEndOfBitstreamBuffer(bitstream_id);
168 if (flushing_ && queued_bitstream_ids_.empty()) {
169 flushing_ = false;
170 client_->NotifyFlushDone();
175 } // namespace content