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

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

Issue 2461073002: Use MediaCodec.setOutputSurface() for fullscreen transitions on M. (Closed)
Patch Set: Simplify APIs. Created 4 years, 1 month 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/android_video_decode_accelerator.h" 5 #include "media/gpu/android_video_decode_accelerator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 if (timer_avda_instances_.empty()) 162 if (timer_avda_instances_.empty())
163 io_timer_.Stop(); 163 io_timer_.Stop();
164 } 164 }
165 165
166 // |avda| would like to use |surface_id|. If it is not busy, then mark it 166 // |avda| would like to use |surface_id|. If it is not busy, then mark it
167 // as busy and return true. If it is busy, then replace any existing waiter, 167 // as busy and return true. If it is busy, then replace any existing waiter,
168 // make |avda| the current waiter, and return false. Any existing waiter 168 // make |avda| the current waiter, and return false. Any existing waiter
169 // is assumed to be on the way out, so we fail its allocation request. 169 // is assumed to be on the way out, so we fail its allocation request.
170 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { 170 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
171 // Nobody has to wait for no surface. 171 // Nobody has to wait for no surface.
172 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) 172 if (surface_id == SurfaceManager::kNoSurfaceID)
173 return true; 173 return true;
174 174
175 auto iter = surface_waiter_map_.find(surface_id); 175 auto iter = surface_waiter_map_.find(surface_id);
176 if (iter == surface_waiter_map_.end()) { 176 if (iter == surface_waiter_map_.end()) {
177 // SurfaceView isn't allocated. Succeed. 177 // SurfaceView isn't allocated. Succeed.
178 surface_waiter_map_[surface_id].owner = avda; 178 surface_waiter_map_[surface_id].owner = avda;
179 return true; 179 return true;
180 } 180 }
181 181
182 // SurfaceView is already allocated. 182 // SurfaceView is already allocated.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 // Promote |waiter| to be the owner. 218 // Promote |waiter| to be the owner.
219 iter->second.owner = waiter; 219 iter->second.owner = waiter;
220 iter->second.waiter = nullptr; 220 iter->second.waiter = nullptr;
221 waiter->OnSurfaceAvailable(true); 221 waiter->OnSurfaceAvailable(true);
222 } 222 }
223 223
224 // On low end devices (< KitKat is always low-end due to buggy MediaCodec), 224 // On low end devices (< KitKat is always low-end due to buggy MediaCodec),
225 // defer the surface creation until the codec is actually used if we know no 225 // defer the surface creation until the codec is actually used if we know no
226 // software fallback exists. 226 // software fallback exists.
227 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) { 227 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) {
228 return surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID && 228 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 &&
229 codec == kCodecH264 &&
230 g_avda_codec_allocator.Get().IsAnyRegisteredAVDA() && 229 g_avda_codec_allocator.Get().IsAnyRegisteredAVDA() &&
231 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 || 230 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 ||
232 base::SysInfo::IsLowEndDevice()); 231 base::SysInfo::IsLowEndDevice());
233 } 232 }
234 233
235 private: 234 private:
236 friend struct base::DefaultLazyInstanceTraits<AVDAManager>; 235 friend struct base::DefaultLazyInstanceTraits<AVDAManager>;
237 236
238 AVDAManager() {} 237 AVDAManager() {}
239 ~AVDAManager() { NOTREACHED(); } 238 ~AVDAManager() { NOTREACHED(); }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 AndroidVideoDecodeAccelerator::BitstreamRecord::~BitstreamRecord() {} 301 AndroidVideoDecodeAccelerator::BitstreamRecord::~BitstreamRecord() {}
303 302
304 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator( 303 AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator(
305 const MakeGLContextCurrentCallback& make_context_current_cb, 304 const MakeGLContextCurrentCallback& make_context_current_cb,
306 const GetGLES2DecoderCallback& get_gles2_decoder_cb) 305 const GetGLES2DecoderCallback& get_gles2_decoder_cb)
307 : client_(NULL), 306 : client_(NULL),
308 make_context_current_cb_(make_context_current_cb), 307 make_context_current_cb_(make_context_current_cb),
309 get_gles2_decoder_cb_(get_gles2_decoder_cb), 308 get_gles2_decoder_cb_(get_gles2_decoder_cb),
310 state_(NO_ERROR), 309 state_(NO_ERROR),
311 picturebuffers_requested_(false), 310 picturebuffers_requested_(false),
311 picture_buffer_manager_(this),
312 drain_type_(DRAIN_TYPE_NONE), 312 drain_type_(DRAIN_TYPE_NONE),
313 media_drm_bridge_cdm_context_(nullptr), 313 media_drm_bridge_cdm_context_(nullptr),
314 cdm_registration_id_(0), 314 cdm_registration_id_(0),
315 pending_input_buf_index_(-1), 315 pending_input_buf_index_(-1),
316 error_sequence_token_(0), 316 error_sequence_token_(0),
317 defer_errors_(false), 317 defer_errors_(false),
318 deferred_initialization_pending_(false), 318 deferred_initialization_pending_(false),
319 codec_needs_reset_(false), 319 codec_needs_reset_(false),
320 defer_surface_creation_(false), 320 defer_surface_creation_(false),
321 surface_id_(SurfaceManager::kNoSurfaceID),
321 weak_this_factory_(this) {} 322 weak_this_factory_(this) {}
322 323
323 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
324 DCHECK(thread_checker_.CalledOnValidThread()); 325 DCHECK(thread_checker_.CalledOnValidThread());
325 g_avda_manager.Get().StopTimer(this); 326 g_avda_manager.Get().StopTimer(this);
326 g_avda_codec_allocator.Get().StopThread(this); 327 g_avda_codec_allocator.Get().StopThread(this);
327 328
328 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 329 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
329 if (!media_drm_bridge_cdm_context_) 330 if (!media_drm_bridge_cdm_context_)
330 return; 331 return;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 << " is not hardware accelerated"; 390 << " is not hardware accelerated";
390 return false; 391 return false;
391 } 392 }
392 393
393 auto gles_decoder = get_gles2_decoder_cb_.Run(); 394 auto gles_decoder = get_gles2_decoder_cb_.Run();
394 if (!gles_decoder) { 395 if (!gles_decoder) {
395 DLOG(ERROR) << "Failed to get gles2 decoder instance."; 396 DLOG(ERROR) << "Failed to get gles2 decoder instance.";
396 return false; 397 return false;
397 } 398 }
398 399
400 // If SetSurface() was called before initialize, pick up the surface.
401 if (pending_surface_id_) {
402 surface_id_ = pending_surface_id_.value();
403 pending_surface_id_.reset();
404 }
405
399 // If we're low on resources, we may decide to defer creation of the surface 406 // If we're low on resources, we may decide to defer creation of the surface
400 // until the codec is actually used. 407 // until the codec is actually used.
401 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(config_.surface_id, 408 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(surface_id_,
402 codec_config_->codec_)) { 409 codec_config_->codec_)) {
403 DCHECK(!deferred_initialization_pending_); 410 DCHECK(!deferred_initialization_pending_);
404 411
405 // We should never be here if a SurfaceView is required. 412 // We should never be here if a SurfaceView is required.
406 DCHECK_EQ(config_.surface_id, Config::kNoSurfaceID); 413 DCHECK_EQ(surface_id_, SurfaceManager::kNoSurfaceID);
407 DCHECK(g_avda_manager.Get().AllocateSurface(config_.surface_id, this)); 414 DCHECK(g_avda_manager.Get().AllocateSurface(surface_id_, this));
408 415
409 defer_surface_creation_ = true; 416 defer_surface_creation_ = true;
410 NotifyInitializationComplete(true); 417 NotifyInitializationComplete(true);
411 return true; 418 return true;
412 } 419 }
413 420
414 // We signaled that we support deferred initialization, so see if the client 421 // We signaled that we support deferred initialization, so see if the client
415 // does also. 422 // does also.
416 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; 423 deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
417 if (config_.is_encrypted && !deferred_initialization_pending_) { 424 if (config_.is_encrypted && !deferred_initialization_pending_) {
418 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; 425 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams";
419 return false; 426 return false;
420 } 427 }
421 428
422 if (g_avda_manager.Get().AllocateSurface(config_.surface_id, this)) { 429 if (g_avda_manager.Get().AllocateSurface(surface_id_, this)) {
423 // We have successfully owned the surface, so finish initialization now. 430 // We have successfully owned the surface, so finish initialization now.
424 return InitializePictureBufferManager(); 431 return InitializePictureBufferManager();
425 } 432 }
426 433
427 // We have to wait for some other AVDA instance to free up the surface. 434 // We have to wait for some other AVDA instance to free up the surface.
428 // OnSurfaceAvailable will be called when it's available. 435 // OnSurfaceAvailable will be called when it's available.
429 return true; 436 return true;
430 } 437 }
431 438
432 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) { 439 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) {
433 DCHECK(deferred_initialization_pending_); 440 DCHECK(deferred_initialization_pending_);
434 DCHECK(!defer_surface_creation_); 441 DCHECK(!defer_surface_creation_);
435 442
436 if (!success || !InitializePictureBufferManager()) { 443 if (!success || !InitializePictureBufferManager()) {
437 NotifyInitializationComplete(false); 444 NotifyInitializationComplete(false);
438 deferred_initialization_pending_ = false; 445 deferred_initialization_pending_ = false;
439 } 446 }
440 } 447 }
441 448
442 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { 449 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
443 if (!make_context_current_cb_.Run()) { 450 if (!make_context_current_cb_.Run()) {
444 LOG(ERROR) << "Failed to make this decoder's GL context current."; 451 LOG(ERROR) << "Failed to make this decoder's GL context current.";
445 return false; 452 return false;
446 } 453 }
447 454
448 codec_config_->surface_ = 455 codec_config_->surface_ = picture_buffer_manager_.Initialize(surface_id_);
449 picture_buffer_manager_.Initialize(this, config_.surface_id);
450 if (codec_config_->surface_.IsEmpty()) 456 if (codec_config_->surface_.IsEmpty())
451 return false; 457 return false;
452 458
453 on_destroying_surface_cb_ = 459 on_destroying_surface_cb_ =
454 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface, 460 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
455 weak_this_factory_.GetWeakPtr()); 461 weak_this_factory_.GetWeakPtr());
456 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback( 462 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
457 on_destroying_surface_cb_); 463 on_destroying_surface_cb_);
458 464
459 if (!g_avda_codec_allocator.Get().StartThread(this)) 465 if (!g_avda_codec_allocator.Get().StartThread(this))
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 if (picturebuffers_requested_ && output_picture_buffers_.empty() && 652 if (picturebuffers_requested_ && output_picture_buffers_.empty() &&
647 !IsDrainingForResetOrDestroy()) { 653 !IsDrainingForResetOrDestroy()) {
648 return false; 654 return false;
649 } 655 }
650 if (!output_picture_buffers_.empty() && free_picture_ids_.empty() && 656 if (!output_picture_buffers_.empty() && free_picture_ids_.empty() &&
651 !IsDrainingForResetOrDestroy()) { 657 !IsDrainingForResetOrDestroy()) {
652 // Don't have any picture buffer to send. Need to wait. 658 // Don't have any picture buffer to send. Need to wait.
653 return false; 659 return false;
654 } 660 }
655 661
662 // If we're waiting to switch surfaces pause output release until we have all
663 // picture buffers returned. This is so we can ensure the right flags are set
664 // on the picture buffers returned to the client.
665 if (pending_surface_id_) {
666 DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), 23);
667 if (picture_buffer_manager_.ArePicturesOutstanding())
668 return false;
669 surface_id_ = pending_surface_id_.value();
670 codec_config_->surface_ =
671 picture_buffer_manager_.Initialize(pending_surface_id_.value());
672 media_codec_->SetSurface(codec_config_->surface_.j_surface().obj());
673 pending_surface_id_.reset();
674 }
675
656 bool eos = false; 676 bool eos = false;
657 base::TimeDelta presentation_timestamp; 677 base::TimeDelta presentation_timestamp;
658 int32_t buf_index = 0; 678 int32_t buf_index = 0;
659 do { 679 do {
660 size_t offset = 0; 680 size_t offset = 0;
661 size_t size = 0; 681 size_t size = 0;
662 682
663 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); 683 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput");
664 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( 684 MediaCodecStatus status = media_codec_->DequeueOutputBuffer(
665 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp, 685 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp,
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 // Postpone ResetCodecState() after the drain. 1253 // Postpone ResetCodecState() after the drain.
1234 StartCodecDrain(DRAIN_FOR_RESET); 1254 StartCodecDrain(DRAIN_FOR_RESET);
1235 } else { 1255 } else {
1236 ResetCodecState(); 1256 ResetCodecState();
1237 base::ThreadTaskRunnerHandle::Get()->PostTask( 1257 base::ThreadTaskRunnerHandle::Get()->PostTask(
1238 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, 1258 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
1239 weak_this_factory_.GetWeakPtr())); 1259 weak_this_factory_.GetWeakPtr()));
1240 } 1260 }
1241 } 1261 }
1242 1262
1263 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) {
1264 if (surface_id == surface_id_)
1265 return;
1266
1267 // Surface changes never take affect immediately, they will be handled during
1268 // DequeOutput() once we get to a good switch point or immediately during an
1269 // OnDestroyingSurface() call.
1270 pending_surface_id_ = surface_id;
1271 }
1272
1243 void AndroidVideoDecodeAccelerator::Destroy() { 1273 void AndroidVideoDecodeAccelerator::Destroy() {
1244 DVLOG(1) << __FUNCTION__; 1274 DVLOG(1) << __FUNCTION__;
1245 DCHECK(thread_checker_.CalledOnValidThread()); 1275 DCHECK(thread_checker_.CalledOnValidThread());
1246 1276
1247 picture_buffer_manager_.Destroy(output_picture_buffers_); 1277 picture_buffer_manager_.Destroy(output_picture_buffers_);
1248 1278
1249 client_ = nullptr; 1279 client_ = nullptr;
1250 1280
1251 // Some VP8 files require a complete MediaCodec drain before we can call 1281 // Some VP8 files require a complete MediaCodec drain before we can call
1252 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In 1282 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In
(...skipping 13 matching lines...) Expand all
1266 DVLOG(1) << __FUNCTION__; 1296 DVLOG(1) << __FUNCTION__;
1267 DCHECK(thread_checker_.CalledOnValidThread()); 1297 DCHECK(thread_checker_.CalledOnValidThread());
1268 1298
1269 if (!on_destroying_surface_cb_.is_null()) { 1299 if (!on_destroying_surface_cb_.is_null()) {
1270 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( 1300 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1271 on_destroying_surface_cb_); 1301 on_destroying_surface_cb_);
1272 } 1302 }
1273 1303
1274 // We no longer care about |surface_id|, in case we did before. It's okay 1304 // We no longer care about |surface_id|, in case we did before. It's okay
1275 // if we have no surface and/or weren't the owner or a waiter. 1305 // if we have no surface and/or weren't the owner or a waiter.
1276 g_avda_manager.Get().DeallocateSurface(config_.surface_id, this); 1306 g_avda_manager.Get().DeallocateSurface(surface_id_, this);
1277 1307
1278 // Note that async codec construction might still be in progress. In that 1308 // Note that async codec construction might still be in progress. In that
1279 // case, the codec will be deleted when it completes once we invalidate all 1309 // case, the codec will be deleted when it completes once we invalidate all
1280 // our weak refs. 1310 // our weak refs.
1281 weak_this_factory_.InvalidateWeakPtrs(); 1311 weak_this_factory_.InvalidateWeakPtrs();
1282 if (media_codec_) { 1312 if (media_codec_) {
1283 g_avda_manager.Get().StopTimer(this); 1313 g_avda_manager.Get().StopTimer(this);
1284 ReleaseMediaCodec(); 1314 ReleaseMediaCodec();
1285 } 1315 }
1286 1316
(...skipping 13 matching lines...) Expand all
1300 base::WeakPtr<gpu::gles2::GLES2Decoder> 1330 base::WeakPtr<gpu::gles2::GLES2Decoder>
1301 AndroidVideoDecodeAccelerator::GetGlDecoder() const { 1331 AndroidVideoDecodeAccelerator::GetGlDecoder() const {
1302 return get_gles2_decoder_cb_.Run(); 1332 return get_gles2_decoder_cb_.Run();
1303 } 1333 }
1304 1334
1305 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) { 1335 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
1306 DCHECK(thread_checker_.CalledOnValidThread()); 1336 DCHECK(thread_checker_.CalledOnValidThread());
1307 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface"); 1337 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
1308 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id; 1338 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id;
1309 1339
1310 if (surface_id != config_.surface_id) 1340 if (surface_id != surface_id_)
1311 return; 1341 return;
1312 1342
1343 // If the API is available avoid having to restart the decoder in order to
1344 // leave full screen. If we don't clear the surface immediately during this
1345 // callback, the MediaCodec will throw an error as the surface is destroyed.
1346 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) {
1347 // Since we can't wait for a transition, we must invalidate all outstanding
1348 // picture buffers to avoid putting the GL system in a broken state.
liberato (no reviews please) 2016/11/03 20:51:04 we can almost un-overlay these things in the overl
1349 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1350
1351 // Switch away from the surface being destroyed to a surface texture.
1352 DCHECK_NE(surface_id_, SurfaceManager::kNoSurfaceID);
1353
1354 // The leaving full screen notification may come in before this point, so
1355 // clear it if necessary.
1356 if (pending_surface_id_) {
liberato (no reviews please) 2016/11/03 20:51:04 if it comes in later, then we might already be usi
DaleCurtis 2016/11/04 01:07:22 This case is already handled in SetSurface and her
1357 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID);
1358 pending_surface_id_.reset();
1359 }
1360
1361 surface_id_ = SurfaceManager::kNoSurfaceID;
1362 codec_config_->surface_ =
1363 picture_buffer_manager_.Initialize(SurfaceManager::kNoSurfaceID);
1364 if (media_codec_)
1365 media_codec_->SetSurface(codec_config_->surface_.j_surface().obj());
1366 return;
1367 }
1368
1313 // If we're currently asynchronously configuring a codec, it will be destroyed 1369 // If we're currently asynchronously configuring a codec, it will be destroyed
1314 // when configuration completes and it notices that |state_| has changed to 1370 // when configuration completes and it notices that |state_| has changed to
1315 // SURFACE_DESTROYED. 1371 // SURFACE_DESTROYED.
1316 state_ = SURFACE_DESTROYED; 1372 state_ = SURFACE_DESTROYED;
1317 if (media_codec_) { 1373 if (media_codec_) {
1318 ReleaseMediaCodec(); 1374 ReleaseMediaCodec();
1319 picture_buffer_manager_.CodecChanged(media_codec_.get()); 1375 picture_buffer_manager_.CodecChanged(media_codec_.get());
1320 } 1376 }
1321 // If we're draining, signal completion now because the drain can no longer 1377 // If we're draining, signal completion now because the drain can no longer
1322 // proceed. 1378 // proceed.
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
1577 1633
1578 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() 1634 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden()
1579 const { 1635 const {
1580 // Prevent MediaCodec from using its internal software decoders when we have 1636 // Prevent MediaCodec from using its internal software decoders when we have
1581 // more secure and up to date versions in the renderer process. 1637 // more secure and up to date versions in the renderer process.
1582 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || 1638 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 ||
1583 codec_config_->codec_ == kCodecVP9); 1639 codec_config_->codec_ == kCodecVP9);
1584 } 1640 }
1585 1641
1586 } // namespace media 1642 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698