| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/vpx_video_decoder.h" | 5 #include "media/filters/vpx_video_decoder.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 decode_threads = std::min(decode_threads, | 137 decode_threads = std::min(decode_threads, |
| 138 base::SysInfo::NumberOfProcessors()); | 138 base::SysInfo::NumberOfProcessors()); |
| 139 return decode_threads; | 139 return decode_threads; |
| 140 } | 140 } |
| 141 | 141 |
| 142 decode_threads = std::max(decode_threads, 0); | 142 decode_threads = std::max(decode_threads, 0); |
| 143 decode_threads = std::min(decode_threads, kMaxDecodeThreads); | 143 decode_threads = std::min(decode_threads, kMaxDecodeThreads); |
| 144 return decode_threads; | 144 return decode_threads; |
| 145 } | 145 } |
| 146 | 146 |
| 147 static int GetVPXFlags() { |
| 148 int flags = 0; |
| 149 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 150 |
| 151 if (cmd_line->HasSwitch(switches::kEnableVpxFrameThreading)) { |
| 152 LOG(ERROR) << "Frame threading enabled for libVPX."; |
| 153 flags |= VPX_CODEC_USE_FRAME_THREADING; |
| 154 } |
| 155 |
| 156 return flags; |
| 157 } |
| 158 |
| 147 static vpx_codec_ctx* InitializeVpxContext(vpx_codec_ctx* context, | 159 static vpx_codec_ctx* InitializeVpxContext(vpx_codec_ctx* context, |
| 148 const VideoDecoderConfig& config) { | 160 const VideoDecoderConfig& config) { |
| 149 context = new vpx_codec_ctx(); | 161 context = new vpx_codec_ctx(); |
| 150 vpx_codec_dec_cfg_t vpx_config = {0}; | 162 vpx_codec_dec_cfg_t vpx_config = {0}; |
| 151 vpx_config.w = config.coded_size().width(); | 163 vpx_config.w = config.coded_size().width(); |
| 152 vpx_config.h = config.coded_size().height(); | 164 vpx_config.h = config.coded_size().height(); |
| 153 vpx_config.threads = GetThreadCount(config); | 165 vpx_config.threads = GetThreadCount(config); |
| 154 | 166 |
| 167 LOG(ERROR) << "Configured VPX decoder with thread count:" |
| 168 << vpx_config.threads; |
| 169 |
| 155 vpx_codec_err_t status = vpx_codec_dec_init( | 170 vpx_codec_err_t status = vpx_codec_dec_init( |
| 156 context, | 171 context, |
| 157 config.codec() == kCodecVP9 ? vpx_codec_vp9_dx() : vpx_codec_vp8_dx(), | 172 config.codec() == kCodecVP9 ? vpx_codec_vp9_dx() : vpx_codec_vp8_dx(), |
| 158 &vpx_config, 0 /* flags */); | 173 &vpx_config, GetVPXFlags()); |
| 159 if (status == VPX_CODEC_OK) | 174 if (status == VPX_CODEC_OK) |
| 160 return context; | 175 return context; |
| 161 | 176 |
| 162 DLOG(ERROR) << "vpx_codec_dec_init() failed: " << vpx_codec_error(context); | 177 DLOG(ERROR) << "vpx_codec_dec_init() failed: " << vpx_codec_error(context); |
| 163 delete context; | 178 delete context; |
| 164 return nullptr; | 179 return nullptr; |
| 165 } | 180 } |
| 166 | 181 |
| 167 // MemoryPool is a pool of simple CPU memory, allocated by hand and used by both | 182 // MemoryPool is a pool of simple CPU memory, allocated by hand and used by both |
| 168 // VP9 and any data consumers. This class needs to be ref-counted to hold on to | 183 // VP9 and any data consumers. This class needs to be ref-counted to hold on to |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 DCHECK(thread_checker_.CalledOnValidThread()); | 471 DCHECK(thread_checker_.CalledOnValidThread()); |
| 457 if (offload_task_runner_) | 472 if (offload_task_runner_) |
| 458 g_vpx_offload_thread.Pointer()->WaitForOutstandingTasks(); | 473 g_vpx_offload_thread.Pointer()->WaitForOutstandingTasks(); |
| 459 | 474 |
| 460 state_ = kNormal; | 475 state_ = kNormal; |
| 461 // PostTask() to avoid calling |closure| inmediately. | 476 // PostTask() to avoid calling |closure| inmediately. |
| 462 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); | 477 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); |
| 463 } | 478 } |
| 464 | 479 |
| 465 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) { | 480 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) { |
| 466 if (config.codec() != kCodecVP8 && config.codec() != kCodecVP9) | 481 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 482 bool use_ffvp9(cmd_line->HasSwitch(switches::kUseFFVP9)); |
| 483 bool skip_loop_filter(cmd_line->HasSwitch(switches::kSkipVpxLoopFilter)); |
| 484 |
| 485 if (config.codec() != kCodecVP8 && (config.codec() != kCodecVP9 || use_ffvp9)) |
| 467 return false; | 486 return false; |
| 468 | 487 |
| 469 // These are the combinations of codec-pixel format supported in principle. | 488 // These are the combinations of codec-pixel format supported in principle. |
| 470 // Note that VP9 does not support Alpha in the current implementation. | 489 // Note that VP9 does not support Alpha in the current implementation. |
| 471 DCHECK( | 490 DCHECK( |
| 472 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12) || | 491 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12) || |
| 473 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12A) || | 492 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12A) || |
| 474 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV12) || | 493 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV12) || |
| 475 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV24)); | 494 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV24)); |
| 476 | 495 |
| 477 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) | 496 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) |
| 478 // When FFmpegVideoDecoder is available it handles VP8 that doesn't have | 497 // When FFmpegVideoDecoder is available it handles VP8 that doesn't have |
| 479 // alpha, and VpxVideoDecoder will handle VP8 with alpha. | 498 // alpha, and VpxVideoDecoder will handle VP8 with alpha. |
| 480 if (config.codec() == kCodecVP8 && config.format() != PIXEL_FORMAT_YV12A) | 499 if (config.codec() == kCodecVP8 && config.format() != PIXEL_FORMAT_YV12A) |
| 481 return false; | 500 return false; |
| 482 #endif | 501 #endif |
| 483 | 502 |
| 484 CloseDecoder(); | 503 CloseDecoder(); |
| 485 | 504 |
| 486 vpx_codec_ = InitializeVpxContext(vpx_codec_, config); | 505 vpx_codec_ = InitializeVpxContext(vpx_codec_, config); |
| 487 if (!vpx_codec_) | 506 if (!vpx_codec_) |
| 488 return false; | 507 return false; |
| 489 | 508 |
| 509 if (skip_loop_filter) { |
| 510 LOG(ERROR) << "Skipping loop filter (in loop de-blocking) for libVPX."; |
| 511 vpx_codec_control_(vpx_codec_, VP9_SET_SKIP_LOOP_FILTER, skip_loop_filter); |
| 512 } |
| 513 |
| 490 // Configure VP9 to decode on our buffers to skip a data copy on decoding. | 514 // Configure VP9 to decode on our buffers to skip a data copy on decoding. |
| 491 if (config.codec() == kCodecVP9) { | 515 if (config.codec() == kCodecVP9) { |
| 492 DCHECK_NE(PIXEL_FORMAT_YV12A, config.format()); | 516 DCHECK_NE(PIXEL_FORMAT_YV12A, config.format()); |
| 493 DCHECK(vpx_codec_get_caps(vpx_codec_->iface) & | 517 DCHECK(vpx_codec_get_caps(vpx_codec_->iface) & |
| 494 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER); | 518 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER); |
| 495 | 519 |
| 496 // Move high resolution vp9 decodes off of the main media thread (otherwise | 520 // Move high resolution vp9 decodes off of the main media thread (otherwise |
| 497 // decode may block audio decoding, demuxing, and other control activities). | 521 // decode may block audio decoding, demuxing, and other control activities). |
| 498 if (config.coded_size().width() >= 1024) { | 522 if (config.coded_size().width() >= 1024) { |
| 499 offload_task_runner_ = | 523 offload_task_runner_ = |
| 500 g_vpx_offload_thread.Pointer()->RequestOffloadThread(); | 524 g_vpx_offload_thread.Pointer()->RequestOffloadThread(); |
| 501 } | 525 } |
| 502 | 526 |
| 503 memory_pool_ = new MemoryPool(); | 527 memory_pool_ = new MemoryPool(); |
| 504 if (vpx_codec_set_frame_buffer_functions(vpx_codec_, | 528 if (vpx_codec_set_frame_buffer_functions(vpx_codec_, |
| 505 &MemoryPool::GetVP9FrameBuffer, | 529 &MemoryPool::GetVP9FrameBuffer, |
| 506 &MemoryPool::ReleaseVP9FrameBuffer, | 530 &MemoryPool::ReleaseVP9FrameBuffer, |
| 507 memory_pool_.get())) { | 531 memory_pool_.get())) { |
| 508 DLOG(ERROR) << "Failed to configure external buffers. " | 532 DLOG(ERROR) << "Failed to configure external buffers. " |
| 509 << vpx_codec_error(vpx_codec_); | 533 << vpx_codec_error(vpx_codec_); |
| 510 return false; | 534 return false; |
| 511 } | 535 } |
| 512 } | 536 } |
| 513 | 537 |
| 514 if (config.format() != PIXEL_FORMAT_YV12A) | 538 if (config.format() != PIXEL_FORMAT_YV12A) |
| 515 return true; | 539 return true; |
| 516 | 540 |
| 541 LOG(ERROR) << "Using libvpx!!!!!!!!!!!!!!!!!!!!!!"; |
| 517 vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_, config); | 542 vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_, config); |
| 518 return !!vpx_codec_alpha_; | 543 return !!vpx_codec_alpha_; |
| 519 } | 544 } |
| 520 | 545 |
| 521 void VpxVideoDecoder::CloseDecoder() { | 546 void VpxVideoDecoder::CloseDecoder() { |
| 522 if (offload_task_runner_) { | 547 if (offload_task_runner_) { |
| 523 g_vpx_offload_thread.Pointer() | 548 g_vpx_offload_thread.Pointer() |
| 524 ->WaitForOutstandingTasksAndReleaseOffloadThread(); | 549 ->WaitForOutstandingTasksAndReleaseOffloadThread(); |
| 525 offload_task_runner_ = nullptr; | 550 offload_task_runner_ = nullptr; |
| 526 } | 551 } |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 (*video_frame)->visible_data(VideoFrame::kUPlane), | 750 (*video_frame)->visible_data(VideoFrame::kUPlane), |
| 726 (*video_frame)->stride(VideoFrame::kUPlane), | 751 (*video_frame)->stride(VideoFrame::kUPlane), |
| 727 (*video_frame)->visible_data(VideoFrame::kVPlane), | 752 (*video_frame)->visible_data(VideoFrame::kVPlane), |
| 728 (*video_frame)->stride(VideoFrame::kVPlane), coded_size.width(), | 753 (*video_frame)->stride(VideoFrame::kVPlane), coded_size.width(), |
| 729 coded_size.height()); | 754 coded_size.height()); |
| 730 | 755 |
| 731 return true; | 756 return true; |
| 732 } | 757 } |
| 733 | 758 |
| 734 } // namespace media | 759 } // namespace media |
| OLD | NEW |