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

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

Issue 2707703002: Group AVDA output surface into AVDASurfaceBundle. (Closed)
Patch Set: minor fixes after testing Created 3 years, 10 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
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<VideoCodecBridge> codec, 37 void DeleteMediaCodecAndSignal(std::unique_ptr<VideoCodecBridge> 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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 jobject media_crypto = 246 jobject media_crypto =
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<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( 253 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder(
249 codec_config->codec, codec_config->needs_protected_surface, 254 codec_config->codec, codec_config->needs_protected_surface,
250 codec_config->initial_expected_coded_size, 255 codec_config->initial_expected_coded_size,
251 codec_config->surface.j_surface().obj(), media_crypto, codec_config->csd0, 256 codec_config->surface_bundle->surface.j_surface().obj(), media_crypto,
252 codec_config->csd1, true, require_software_codec)); 257 codec_config->csd0, codec_config->csd1, true, require_software_codec));
253 258
254 return codec; 259 return codec;
255 } 260 }
256 261
257 void AVDACodecAllocator::CreateMediaCodecAsync( 262 void AVDACodecAllocator::CreateMediaCodecAsync(
258 base::WeakPtr<AVDACodecAllocatorClient> client, 263 base::WeakPtr<AVDACodecAllocatorClient> client,
259 scoped_refptr<CodecConfig> codec_config) { 264 scoped_refptr<CodecConfig> codec_config) {
265 // Allocate the codec on the appropriate thread, and reply to this one with
266 // the result. If |client| is gone by then, we handle cleanup.
260 base::PostTaskAndReplyWithResult( 267 base::PostTaskAndReplyWithResult(
261 TaskRunnerFor(codec_config->task_type).get(), FROM_HERE, 268 TaskRunnerFor(codec_config->task_type).get(), FROM_HERE,
262 base::Bind(&AVDACodecAllocator::CreateMediaCodecSync, 269 base::Bind(&AVDACodecAllocator::CreateMediaCodecSync,
263 base::Unretained(this), codec_config), 270 base::Unretained(this), codec_config),
264 base::Bind(&AVDACodecAllocatorClient::OnCodecConfigured, client)); 271 base::Bind(&AVDACodecAllocator::ForwardOrDropCodec,
272 base::Unretained(this), client, codec_config->task_type,
273 codec_config->surface_bundle));
274 }
275
276 void AVDACodecAllocator::ForwardOrDropCodec(
277 base::WeakPtr<AVDACodecAllocatorClient> client,
278 TaskType task_type,
279 scoped_refptr<AVDASurfaceBundle> surface_bundle,
280 std::unique_ptr<VideoCodecBridge> media_codec) {
281 if (!client) {
282 // |client| has been destroyed. Free |media_codec| on the right thread.
283 // Note that this also preserves |surface_bundle| until |media_codec| has
284 // been released, in case our ref to it is the last one.
285 ReleaseMediaCodec(std::move(media_codec), task_type, surface_bundle);
286 return;
287 }
288
289 // The client is still around, so (presumably) it has a reference to
290 // |surface_bundle| already.
watk 2017/02/22 20:38:56 This comment seems out of place. It seems to be ju
liberato (no reviews please) 2017/02/23 18:18:46 Done.
291 client->OnCodecConfigured(std::move(media_codec));
265 } 292 }
266 293
267 void AVDACodecAllocator::ReleaseMediaCodec( 294 void AVDACodecAllocator::ReleaseMediaCodec(
268 std::unique_ptr<VideoCodecBridge> media_codec, 295 std::unique_ptr<VideoCodecBridge> media_codec,
269 TaskType task_type, 296 TaskType task_type,
270 int surface_id) { 297 const scoped_refptr<AVDASurfaceBundle>& surface_bundle) {
271 DCHECK(thread_checker_.CalledOnValidThread()); 298 DCHECK(thread_checker_.CalledOnValidThread());
272 DCHECK(media_codec); 299 DCHECK(media_codec);
273 300
274 // 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
275 if (surface_id == SurfaceManager::kNoSurfaceID) { 302 // the reference to |surface_bundle|, though, so that the SurfaceTexture
276 TaskRunnerFor(task_type)->PostTask( 303 // lasts at least as long as the codec.
304 if (surface_bundle->surface_id == SurfaceManager::kNoSurfaceID) {
305 TaskRunnerFor(task_type)->PostTaskAndReply(
277 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal, 306 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal,
278 base::Passed(std::move(media_codec)), nullptr)); 307 base::Passed(std::move(media_codec)), nullptr),
308 base::Bind(&DropReferenceToSurfaceBundle, surface_bundle));
279 return; 309 return;
280 } 310 }
281 311
312 DCHECK(!surface_bundle->surface_texture);
282 pending_codec_releases_.emplace( 313 pending_codec_releases_.emplace(
283 std::piecewise_construct, std::forward_as_tuple(surface_id), 314 std::piecewise_construct,
315 std::forward_as_tuple(surface_bundle->surface_id),
284 std::forward_as_tuple(base::WaitableEvent::ResetPolicy::MANUAL, 316 std::forward_as_tuple(base::WaitableEvent::ResetPolicy::MANUAL,
285 base::WaitableEvent::InitialState::NOT_SIGNALED)); 317 base::WaitableEvent::InitialState::NOT_SIGNALED));
286 base::WaitableEvent* released = 318 base::WaitableEvent* released =
287 &pending_codec_releases_.find(surface_id)->second; 319 &pending_codec_releases_.find(surface_bundle->surface_id)->second;
288 320
321 // Note that we forward |surface_bundle|, too, so that the surface outlasts
322 // the codec. This doesn't matter so much for CVV surfaces, since they don't
323 // auto-release when they're dropped. However, for surface owners, this will
324 // become important, so we still handle it. Plus, it makes sense.
289 TaskRunnerFor(task_type)->PostTaskAndReply( 325 TaskRunnerFor(task_type)->PostTaskAndReply(
290 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal, 326 FROM_HERE, base::Bind(&DeleteMediaCodecAndSignal,
291 base::Passed(std::move(media_codec)), released), 327 base::Passed(std::move(media_codec)), released),
292 base::Bind(&AVDACodecAllocator::OnMediaCodecAndSurfaceReleased, 328 base::Bind(&AVDACodecAllocator::OnMediaCodecAndSurfaceReleased,
293 base::Unretained(this), surface_id)); 329 base::Unretained(this), surface_bundle));
294 } 330 }
295 331
296 void AVDACodecAllocator::OnMediaCodecAndSurfaceReleased(int surface_id) { 332 void AVDACodecAllocator::OnMediaCodecAndSurfaceReleased(
333 scoped_refptr<AVDASurfaceBundle> surface_bundle) {
297 DCHECK(thread_checker_.CalledOnValidThread()); 334 DCHECK(thread_checker_.CalledOnValidThread());
298 335
299 pending_codec_releases_.erase(surface_id); 336 pending_codec_releases_.erase(surface_bundle->surface_id);
300 if (!surface_owners_.count(surface_id)) 337 if (!surface_owners_.count(surface_bundle->surface_id))
301 return; 338 return;
302 339
303 OwnerRecord& record = surface_owners_[surface_id]; 340 OwnerRecord& record = surface_owners_[surface_bundle->surface_id];
304 if (!record.owner && record.waiter) { 341 if (!record.owner && record.waiter) {
305 record.owner = record.waiter; 342 record.owner = record.waiter;
306 record.waiter = nullptr; 343 record.waiter = nullptr;
307 record.owner->OnSurfaceAvailable(true); 344 record.owner->OnSurfaceAvailable(true);
308 } 345 }
346
347 // Also note that |surface_bundle| lasted at least as long as the codec.
309 } 348 }
310 349
311 // Returns a hint about whether the construction thread has hung for 350 // Returns a hint about whether the construction thread has hung for
312 // |task_type|. Note that if a thread isn't started, then we'll just return 351 // |task_type|. Note that if a thread isn't started, then we'll just return
313 // "not hung", since it'll run on the current thread anyway. The hang 352 // "not hung", since it'll run on the current thread anyway. The hang
314 // detector will see no pending jobs in that case, so it's automatic. 353 // detector will see no pending jobs in that case, so it's automatic.
315 bool AVDACodecAllocator::IsThreadLikelyHung(TaskType task_type) { 354 bool AVDACodecAllocator::IsThreadLikelyHung(TaskType task_type) {
316 DCHECK(thread_checker_.CalledOnValidThread()); 355 DCHECK(thread_checker_.CalledOnValidThread());
317 return threads_[task_type]->hang_detector.IsThreadLikelyHung(); 356 return threads_[task_type]->hang_detector.IsThreadLikelyHung();
318 } 357 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 void AVDACodecAllocator::StopThreadTask(size_t index) { 397 void AVDACodecAllocator::StopThreadTask(size_t index) {
359 threads_[index]->thread.Stop(); 398 threads_[index]->thread.Stop();
360 // Signal the stop event after both threads are stopped. 399 // Signal the stop event after both threads are stopped.
361 if (stop_event_for_testing_ && !threads_[AUTO_CODEC]->thread.IsRunning() && 400 if (stop_event_for_testing_ && !threads_[AUTO_CODEC]->thread.IsRunning() &&
362 !threads_[SW_CODEC]->thread.IsRunning()) { 401 !threads_[SW_CODEC]->thread.IsRunning()) {
363 stop_event_for_testing_->Signal(); 402 stop_event_for_testing_->Signal();
364 } 403 }
365 } 404 }
366 405
367 } // namespace media 406 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698