Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: content/common/gpu/media/fake_video_decode_accelerator.cc

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Squash and rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "content/common/gpu/media/fake_video_decode_accelerator.h"
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include <memory>
11
12 #include "base/bind.h"
13 #include "base/location.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "media/base/bitstream_buffer.h"
16 #include "media/base/limits.h"
17 #include "ui/gl/gl_context.h"
18 #include "ui/gl/gl_implementation.h"
19 #include "ui/gl/gl_surface.h"
20 #include "ui/gl/gl_surface_egl.h"
21 #include "ui/gl/gl_surface_glx.h"
22
23 namespace content {
24
25 static const uint32_t kDefaultTextureTarget = GL_TEXTURE_2D;
26 // Must be at least 2 since the rendering helper will switch between textures
27 // and if there is only one, it will wait for the next one that will never come.
28 // Must also be an even number as otherwise there won't be the same amount of
29 // white and black frames.
30 static const unsigned int kNumBuffers = media::limits::kMaxVideoFrames +
31 (media::limits::kMaxVideoFrames & 1u);
32
33 FakeVideoDecodeAccelerator::FakeVideoDecodeAccelerator(
34 const gfx::Size& size,
35 const MakeGLContextCurrentCallback& make_context_current_cb)
36 : child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
37 client_(NULL),
38 make_context_current_cb_(make_context_current_cb),
39 frame_buffer_size_(size),
40 flushing_(false),
41 weak_this_factory_(this) {}
42
43 FakeVideoDecodeAccelerator::~FakeVideoDecodeAccelerator() {
44 }
45
46 bool FakeVideoDecodeAccelerator::Initialize(const Config& config,
47 Client* client) {
48 DCHECK(child_task_runner_->BelongsToCurrentThread());
49 if (config.profile == media::VIDEO_CODEC_PROFILE_UNKNOWN) {
50 LOG(ERROR) << "unknown codec profile";
51 return false;
52 }
53 if (config.is_encrypted) {
54 NOTREACHED() << "encrypted streams are not supported";
55 return false;
56 }
57
58 // V4L2VideoDecodeAccelerator waits until first decode call to ask for buffers
59 // This class asks for it on initialization instead.
60 client_ = client;
61 client_->ProvidePictureBuffers(kNumBuffers, 1, frame_buffer_size_,
62 kDefaultTextureTarget);
63 return true;
64 }
65
66 void FakeVideoDecodeAccelerator::Decode(
67 const media::BitstreamBuffer& bitstream_buffer) {
68 // We won't really read from the bitstream_buffer, close the handle.
69 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
70 base::SharedMemory::CloseHandle(bitstream_buffer.handle());
71
72 if (bitstream_buffer.id() < 0) {
73 LOG(ERROR) << "Invalid bitstream: id=" << bitstream_buffer.id();
74 client_->NotifyError(INVALID_ARGUMENT);
75 return;
76 }
77
78 int bitstream_buffer_id = bitstream_buffer.id();
79 queued_bitstream_ids_.push(bitstream_buffer_id);
80 child_task_runner_->PostTask(
81 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
82 weak_this_factory_.GetWeakPtr()));
83 }
84
85 // Similar to UseOutputBitstreamBuffer for the encode accelerator.
86 void FakeVideoDecodeAccelerator::AssignPictureBuffers(
87 const std::vector<media::PictureBuffer>& buffers) {
88 DCHECK(buffers.size() == kNumBuffers);
89 DCHECK(!(buffers.size()%2));
90
91 // Save buffers and mark all buffers as ready for use.
92 std::unique_ptr<uint8_t[]> white_data(
93 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() *
94 4]);
95 memset(white_data.get(),
96 UINT8_MAX,
97 frame_buffer_size_.width() * frame_buffer_size_.height() * 4);
98 std::unique_ptr<uint8_t[]> black_data(
99 new uint8_t[frame_buffer_size_.width() * frame_buffer_size_.height() *
100 4]);
101 memset(black_data.get(),
102 0,
103 frame_buffer_size_.width() * frame_buffer_size_.height() * 4);
104 if (!make_context_current_cb_.Run()) {
105 LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
106 return;
107 }
108 for (size_t index = 0; index < buffers.size(); ++index) {
109 DCHECK_LE(1u, buffers[index].texture_ids().size());
110 glBindTexture(GL_TEXTURE_2D, buffers[index].texture_ids()[0]);
111 // Every other frame white and the rest black.
112 uint8_t* data = index % 2 ? white_data.get() : black_data.get();
113 glTexImage2D(GL_TEXTURE_2D,
114 0,
115 GL_RGBA,
116 frame_buffer_size_.width(),
117 frame_buffer_size_.height(),
118 0,
119 GL_RGBA,
120 GL_UNSIGNED_BYTE,
121 data);
122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
126 glBindTexture(GL_TEXTURE_2D, 0);
127 free_output_buffers_.push(buffers[index].id());
128 }
129 child_task_runner_->PostTask(
130 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
131 weak_this_factory_.GetWeakPtr()));
132 }
133
134 void FakeVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
135 free_output_buffers_.push(picture_buffer_id);
136 child_task_runner_->PostTask(
137 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
138 weak_this_factory_.GetWeakPtr()));
139 }
140
141 void FakeVideoDecodeAccelerator::Flush() {
142 flushing_ = true;
143 child_task_runner_->PostTask(
144 FROM_HERE, base::Bind(&FakeVideoDecodeAccelerator::DoPictureReady,
145 weak_this_factory_.GetWeakPtr()));
146 }
147
148 void FakeVideoDecodeAccelerator::Reset() {
149 while (!queued_bitstream_ids_.empty()) {
150 client_->NotifyEndOfBitstreamBuffer(queued_bitstream_ids_.front());
151 queued_bitstream_ids_.pop();
152 }
153 client_->NotifyResetDone();
154 }
155
156 void FakeVideoDecodeAccelerator::Destroy() {
157 while (!queued_bitstream_ids_.empty()) {
158 client_->NotifyEndOfBitstreamBuffer(queued_bitstream_ids_.front());
159 queued_bitstream_ids_.pop();
160 }
161 delete this;
162 }
163
164 bool FakeVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
165 const base::WeakPtr<Client>& decode_client,
166 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
167 return false;
168 }
169
170 void FakeVideoDecodeAccelerator::DoPictureReady() {
171 if (flushing_ && queued_bitstream_ids_.empty()) {
172 flushing_ = false;
173 client_->NotifyFlushDone();
174 }
175 while (!free_output_buffers_.empty() && !queued_bitstream_ids_.empty()) {
176 int bitstream_id = queued_bitstream_ids_.front();
177 queued_bitstream_ids_.pop();
178 int buffer_id = free_output_buffers_.front();
179 free_output_buffers_.pop();
180
181 const media::Picture picture =
182 media::Picture(buffer_id,
183 bitstream_id,
184 gfx::Rect(frame_buffer_size_),
185 false);
186 client_->PictureReady(picture);
187 // Bitstream no longer needed.
188 client_->NotifyEndOfBitstreamBuffer(bitstream_id);
189 if (flushing_ && queued_bitstream_ids_.empty()) {
190 flushing_ = false;
191 client_->NotifyFlushDone();
192 }
193 }
194 }
195
196 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698