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

Side by Side Diff: media/gpu/avda_codec_allocator.cc

Issue 2707703002: Group AVDA output surface into AVDASurfaceBundle. (Closed)
Patch Set: rebased Created 3 years, 9 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
« no previous file with comments | « media/gpu/avda_codec_allocator.h ('k') | media/gpu/avda_surface_bundle.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/avda_codec_allocator.h" 5 #include "media/gpu/avda_codec_allocator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 23 matching lines...) Expand all
34 base::TimeDelta::FromMilliseconds(800); 34 base::TimeDelta::FromMilliseconds(800);
35 35
36 // Delete |codec| and signal |done_event| if it's not null. 36 // Delete |codec| and signal |done_event| if it's not null.
37 void DeleteMediaCodecAndSignal(std::unique_ptr<MediaCodecBridge> codec, 37 void DeleteMediaCodecAndSignal(std::unique_ptr<MediaCodecBridge> codec,
38 base::WaitableEvent* done_event) { 38 base::WaitableEvent* done_event) {
39 codec.reset(); 39 codec.reset();
40 if (done_event) 40 if (done_event)
41 done_event->Signal(); 41 done_event->Signal();
42 } 42 }
43 43
44 void DropReferenceToSurfaceBundle(
45 scoped_refptr<AVDASurfaceBundle> surface_bundle) {
46 // Do nothing. Let |surface_bundle| go out of scope.
47 }
48
44 } // namespace 49 } // namespace
45 50
46 CodecConfig::CodecConfig() {} 51 CodecConfig::CodecConfig() {}
47 CodecConfig::~CodecConfig() {} 52 CodecConfig::~CodecConfig() {}
48 53
49 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock) 54 AVDACodecAllocator::HangDetector::HangDetector(base::TickClock* tick_clock)
50 : tick_clock_(tick_clock) {} 55 : tick_clock_(tick_clock) {}
51 56
52 void AVDACodecAllocator::HangDetector::WillProcessTask( 57 void AVDACodecAllocator::HangDetector::WillProcessTask(
53 const base::PendingTask& pending_task) { 58 const base::PendingTask& pending_task) {
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 codec_config->media_crypto ? codec_config->media_crypto->obj() : nullptr; 247 codec_config->media_crypto ? codec_config->media_crypto->obj() : nullptr;
243 248
244 // |needs_protected_surface| implies encrypted stream. 249 // |needs_protected_surface| implies encrypted stream.
245 DCHECK(!codec_config->needs_protected_surface || media_crypto); 250 DCHECK(!codec_config->needs_protected_surface || media_crypto);
246 251
247 const bool require_software_codec = codec_config->task_type == SW_CODEC; 252 const bool require_software_codec = codec_config->task_type == SW_CODEC;
248 std::unique_ptr<MediaCodecBridge> codec( 253 std::unique_ptr<MediaCodecBridge> codec(
249 MediaCodecBridgeImpl::CreateVideoDecoder( 254 MediaCodecBridgeImpl::CreateVideoDecoder(
250 codec_config->codec, codec_config->needs_protected_surface, 255 codec_config->codec, codec_config->needs_protected_surface,
251 codec_config->initial_expected_coded_size, 256 codec_config->initial_expected_coded_size,
252 codec_config->surface.j_surface().obj(), media_crypto, 257 codec_config->surface_bundle->surface.j_surface().obj(), media_crypto,
253 codec_config->csd0, codec_config->csd1, true, 258 codec_config->csd0, codec_config->csd1, true,
254 require_software_codec)); 259 require_software_codec));
255 260
256 return codec; 261 return codec;
257 } 262 }
258 263
259 void AVDACodecAllocator::CreateMediaCodecAsync( 264 void AVDACodecAllocator::CreateMediaCodecAsync(
260 base::WeakPtr<AVDACodecAllocatorClient> client, 265 base::WeakPtr<AVDACodecAllocatorClient> client,
261 scoped_refptr<CodecConfig> codec_config) { 266 scoped_refptr<CodecConfig> codec_config) {
267 // Allocate the codec on the appropriate thread, and reply to this one with
268 // the result. If |client| is gone by then, we handle cleanup.
262 base::PostTaskAndReplyWithResult( 269 base::PostTaskAndReplyWithResult(
263 TaskRunnerFor(codec_config->task_type).get(), FROM_HERE, 270 TaskRunnerFor(codec_config->task_type).get(), FROM_HERE,
264 base::Bind(&AVDACodecAllocator::CreateMediaCodecSync, 271 base::Bind(&AVDACodecAllocator::CreateMediaCodecSync,
265 base::Unretained(this), codec_config), 272 base::Unretained(this), codec_config),
266 base::Bind(&AVDACodecAllocatorClient::OnCodecConfigured, client)); 273 base::Bind(&AVDACodecAllocator::ForwardOrDropCodec,
274 base::Unretained(this), client, codec_config->task_type,
275 codec_config->surface_bundle));
276 }
277
278 void AVDACodecAllocator::ForwardOrDropCodec(
279 base::WeakPtr<AVDACodecAllocatorClient> client,
280 TaskType task_type,
281 scoped_refptr<AVDASurfaceBundle> surface_bundle,
282 std::unique_ptr<MediaCodecBridge> media_codec) {
283 if (!client) {
284 // |client| has been destroyed. Free |media_codec| on the right thread.
285 // Note that this also preserves |surface_bundle| until |media_codec| has
286 // been released, in case our ref to it is the last one.
287 ReleaseMediaCodec(std::move(media_codec), task_type, surface_bundle);
288 return;
289 }
290
291 client->OnCodecConfigured(std::move(media_codec));
267 } 292 }
268 293
269 void AVDACodecAllocator::ReleaseMediaCodec( 294 void AVDACodecAllocator::ReleaseMediaCodec(
270 std::unique_ptr<MediaCodecBridge> media_codec, 295 std::unique_ptr<MediaCodecBridge> media_codec,
271 TaskType task_type, 296 TaskType task_type,
272 int surface_id) { 297 const scoped_refptr<AVDASurfaceBundle>& surface_bundle) {
273 DCHECK(thread_checker_.CalledOnValidThread()); 298 DCHECK(thread_checker_.CalledOnValidThread());
274 DCHECK(media_codec); 299 DCHECK(media_codec);
275 300
276 // No need to track the release if it's a SurfaceTexture. 301 // No need to track the release if it's a SurfaceTexture. We still forward
277 if (surface_id == SurfaceManager::kNoSurfaceID) { 302 // the reference to |surface_bundle|, though, so that the SurfaceTexture
278 TaskRunnerFor(task_type)->PostTask( 303 // lasts at least as long as the codec.
279 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal, 304 if (surface_bundle->surface_id == SurfaceManager::kNoSurfaceID) {
280 base::Passed(std::move(media_codec)), nullptr)); 305 TaskRunnerFor(task_type)->PostTaskAndReply(
306 FROM_HERE,
307 base::Bind(&DeleteMediaCodecAndSignal,
308 base::Passed(std::move(media_codec)), nullptr),
309 base::Bind(&DropReferenceToSurfaceBundle, surface_bundle));
281 return; 310 return;
282 } 311 }
283 312
313 DCHECK(!surface_bundle->surface_texture);
284 pending_codec_releases_.emplace( 314 pending_codec_releases_.emplace(
285 std::piecewise_construct, std::forward_as_tuple(surface_id), 315 std::piecewise_construct,
316 std::forward_as_tuple(surface_bundle->surface_id),
286 std::forward_as_tuple(base::WaitableEvent::ResetPolicy::MANUAL, 317 std::forward_as_tuple(base::WaitableEvent::ResetPolicy::MANUAL,
287 base::WaitableEvent::InitialState::NOT_SIGNALED)); 318 base::WaitableEvent::InitialState::NOT_SIGNALED));
288 base::WaitableEvent* released = 319 base::WaitableEvent* released =
289 &pending_codec_releases_.find(surface_id)->second; 320 &pending_codec_releases_.find(surface_bundle->surface_id)->second;
290 321
322 // Note that we forward |surface_bundle|, too, so that the surface outlasts
323 // the codec. This doesn't matter so much for CVV surfaces, since they don't
324 // auto-release when they're dropped. However, for surface owners, this will
325 // become important, so we still handle it. Plus, it makes sense.
291 TaskRunnerFor(task_type)->PostTaskAndReply( 326 TaskRunnerFor(task_type)->PostTaskAndReply(
292 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal, 327 FROM_HERE,
293 base::Passed(std::move(media_codec)), released), 328 base::Bind(&DeleteMediaCodecAndSignal,
294 base::Bind(&AVDACodecAllocator::OnMediaCodecAndSurfaceReleased, 329 base::Passed(std::move(media_codec)), released),
295 base::Unretained(this), surface_id)); 330 base::Bind(&AVDACodecAllocator::OnMediaCodecReleased,
331 base::Unretained(this), surface_bundle));
296 } 332 }
297 333
298 void AVDACodecAllocator::OnMediaCodecAndSurfaceReleased(int surface_id) { 334 void AVDACodecAllocator::OnMediaCodecReleased(
335 scoped_refptr<AVDASurfaceBundle> surface_bundle) {
299 DCHECK(thread_checker_.CalledOnValidThread()); 336 DCHECK(thread_checker_.CalledOnValidThread());
300 337
301 pending_codec_releases_.erase(surface_id); 338 pending_codec_releases_.erase(surface_bundle->surface_id);
302 if (!surface_owners_.count(surface_id)) 339 if (!surface_owners_.count(surface_bundle->surface_id))
303 return; 340 return;
304 341
305 OwnerRecord& record = surface_owners_[surface_id]; 342 OwnerRecord& record = surface_owners_[surface_bundle->surface_id];
306 if (!record.owner && record.waiter) { 343 if (!record.owner && record.waiter) {
307 record.owner = record.waiter; 344 record.owner = record.waiter;
308 record.waiter = nullptr; 345 record.waiter = nullptr;
309 record.owner->OnSurfaceAvailable(true); 346 record.owner->OnSurfaceAvailable(true);
310 } 347 }
348
349 // Also note that |surface_bundle| lasted at least as long as the codec.
311 } 350 }
312 351
313 // Returns a hint about whether the construction thread has hung for 352 // Returns a hint about whether the construction thread has hung for
314 // |task_type|. Note that if a thread isn't started, then we'll just return 353 // |task_type|. Note that if a thread isn't started, then we'll just return
315 // "not hung", since it'll run on the current thread anyway. The hang 354 // "not hung", since it'll run on the current thread anyway. The hang
316 // detector will see no pending jobs in that case, so it's automatic. 355 // detector will see no pending jobs in that case, so it's automatic.
317 bool AVDACodecAllocator::IsThreadLikelyHung(TaskType task_type) { 356 bool AVDACodecAllocator::IsThreadLikelyHung(TaskType task_type) {
318 DCHECK(thread_checker_.CalledOnValidThread()); 357 DCHECK(thread_checker_.CalledOnValidThread());
319 return threads_[task_type]->hang_detector.IsThreadLikelyHung(); 358 return threads_[task_type]->hang_detector.IsThreadLikelyHung();
320 } 359 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 void AVDACodecAllocator::StopThreadTask(size_t index) { 399 void AVDACodecAllocator::StopThreadTask(size_t index) {
361 threads_[index]->thread.Stop(); 400 threads_[index]->thread.Stop();
362 // Signal the stop event after both threads are stopped. 401 // Signal the stop event after both threads are stopped.
363 if (stop_event_for_testing_ && !threads_[AUTO_CODEC]->thread.IsRunning() && 402 if (stop_event_for_testing_ && !threads_[AUTO_CODEC]->thread.IsRunning() &&
364 !threads_[SW_CODEC]->thread.IsRunning()) { 403 !threads_[SW_CODEC]->thread.IsRunning()) {
365 stop_event_for_testing_->Signal(); 404 stop_event_for_testing_->Signal();
366 } 405 }
367 } 406 }
368 407
369 } // namespace media 408 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/avda_codec_allocator.h ('k') | media/gpu/avda_surface_bundle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698