Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/v4l2_video_decode_accelerator.h" | 5 #include "media/gpu/v4l2_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <linux/videodev2.h> | 10 #include <linux/videodev2.h> |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 // descriptors, mmap() segments, etc. | 196 // descriptors, mmap() segments, etc. |
| 197 DCHECK(input_buffer_map_.empty()); | 197 DCHECK(input_buffer_map_.empty()); |
| 198 DCHECK(output_buffer_map_.empty()); | 198 DCHECK(output_buffer_map_.empty()); |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, | 201 bool V4L2VideoDecodeAccelerator::Initialize(const Config& config, |
| 202 Client* client) { | 202 Client* client) { |
| 203 DVLOGF(3) << "profile: " << config.profile | 203 DVLOGF(3) << "profile: " << config.profile |
| 204 << ", output_mode=" << static_cast<int>(config.output_mode); | 204 << ", output_mode=" << static_cast<int>(config.output_mode); |
| 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 205 DCHECK(child_task_runner_->BelongsToCurrentThread()); |
| 206 DCHECK_EQ(decoder_state_, kUninitialized); | 206 DCHECK_EQ(decoder_state_, kUninitialized); |
|
kcwu
2016/11/28 06:31:14
Two questions,
1. should we add kInitializing stat
wuchengli
2016/11/28 07:04:49
I don't think it's very useful to add a state to j
wuchengli
2016/11/28 09:03:19
As discussed, moved decoder_state_ = kInitialized;
| |
| 207 | 207 |
| 208 if (config.is_encrypted) { | 208 if (config.is_encrypted) { |
| 209 NOTREACHED() << "Encrypted streams are not supported for this VDA"; | 209 NOTREACHED() << "Encrypted streams are not supported for this VDA"; |
| 210 return false; | 210 return false; |
| 211 } | 211 } |
| 212 | 212 |
| 213 if (config.output_mode != Config::OutputMode::ALLOCATE && | 213 if (config.output_mode != Config::OutputMode::ALLOCATE && |
| 214 config.output_mode != Config::OutputMode::IMPORT) { | 214 config.output_mode != Config::OutputMode::IMPORT) { |
| 215 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; | 215 NOTREACHED() << "Only ALLOCATE and IMPORT OutputModes are supported"; |
| 216 return false; | 216 return false; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); | 267 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); |
| 268 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { | 268 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { |
| 269 LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP" | 269 LOGF(ERROR) << "ioctl() failed: VIDIOC_QUERYCAP" |
| 270 << ", caps check failed: 0x" << std::hex << caps.capabilities; | 270 << ", caps check failed: 0x" << std::hex << caps.capabilities; |
| 271 return false; | 271 return false; |
| 272 } | 272 } |
| 273 | 273 |
| 274 if (!SetupFormats()) | 274 if (!SetupFormats()) |
| 275 return false; | 275 return false; |
| 276 | 276 |
| 277 // Subscribe to the resolution change event. | |
| 278 struct v4l2_event_subscription sub; | |
| 279 memset(&sub, 0, sizeof(sub)); | |
| 280 sub.type = V4L2_EVENT_SOURCE_CHANGE; | |
| 281 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); | |
| 282 | |
| 283 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) { | 277 if (video_profile_ >= H264PROFILE_MIN && video_profile_ <= H264PROFILE_MAX) { |
| 284 decoder_h264_parser_.reset(new H264Parser()); | 278 decoder_h264_parser_.reset(new H264Parser()); |
| 285 } | 279 } |
| 286 | 280 |
| 287 if (!CreateInputBuffers()) | |
| 288 return false; | |
| 289 | |
| 290 decoder_cmd_supported_ = IsDecoderCmdSupported(); | |
| 291 | |
| 292 if (!decoder_thread_.Start()) { | 281 if (!decoder_thread_.Start()) { |
| 293 LOGF(ERROR) << "decoder thread failed to start"; | 282 LOGF(ERROR) << "decoder thread failed to start"; |
| 294 return false; | 283 return false; |
| 295 } | 284 } |
| 296 | 285 |
| 297 decoder_state_ = kInitialized; | |
| 298 output_mode_ = config.output_mode; | 286 output_mode_ = config.output_mode; |
| 299 | 287 |
| 300 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. | 288 // InitializeTask will NOTIFY_ERROR on failure. |
| 301 decoder_thread_.task_runner()->PostTask( | 289 decoder_thread_.task_runner()->PostTask( |
| 302 FROM_HERE, base::Bind(base::IgnoreResult( | 290 FROM_HERE, base::Bind(&V4L2VideoDecodeAccelerator::InitializeTask, |
| 303 &V4L2VideoDecodeAccelerator::StartDevicePoll), | |
| 304 base::Unretained(this))); | 291 base::Unretained(this))); |
| 305 | 292 |
| 306 return true; | 293 return true; |
| 307 } | 294 } |
| 308 | 295 |
| 296 void V4L2VideoDecodeAccelerator::InitializeTask() { | |
| 297 DVLOGF(3); | |
| 298 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | |
|
kcwu
2016/11/28 06:31:14
DCHECK_EQ(decoder_state_, kUninitialized);
wuchengli
2016/11/28 09:03:19
Done.
| |
| 299 | |
| 300 // Subscribe to the resolution change event. | |
| 301 struct v4l2_event_subscription sub; | |
| 302 memset(&sub, 0, sizeof(sub)); | |
| 303 sub.type = V4L2_EVENT_SOURCE_CHANGE; | |
| 304 IOCTL_OR_ERROR_RETURN(VIDIOC_SUBSCRIBE_EVENT, &sub); | |
| 305 | |
| 306 if (!CreateInputBuffers()) { | |
| 307 NOTIFY_ERROR(PLATFORM_FAILURE); | |
| 308 return; | |
| 309 } | |
| 310 | |
| 311 decoder_cmd_supported_ = IsDecoderCmdSupported(); | |
| 312 | |
| 313 if (!StartDevicePoll()) | |
| 314 return; | |
| 315 | |
| 316 decoder_state_ = kInitialized; | |
| 317 } | |
| 318 | |
| 309 void V4L2VideoDecodeAccelerator::Decode( | 319 void V4L2VideoDecodeAccelerator::Decode( |
| 310 const BitstreamBuffer& bitstream_buffer) { | 320 const BitstreamBuffer& bitstream_buffer) { |
| 311 DVLOGF(1) << "input_id=" << bitstream_buffer.id() | 321 DVLOGF(1) << "input_id=" << bitstream_buffer.id() |
| 312 << ", size=" << bitstream_buffer.size(); | 322 << ", size=" << bitstream_buffer.size(); |
| 313 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 323 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
| 314 | 324 |
| 315 if (bitstream_buffer.id() < 0) { | 325 if (bitstream_buffer.id() < 0) { |
| 316 LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 326 LOGF(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
| 317 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | 327 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) |
| 318 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | 328 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); |
| (...skipping 1803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2122 DLOGF(ERROR) << "Unexpected visible rectangle " << rect.ToString() | 2132 DLOGF(ERROR) << "Unexpected visible rectangle " << rect.ToString() |
| 2123 << ", top-left is not origin"; | 2133 << ", top-left is not origin"; |
| 2124 return coded_size; | 2134 return coded_size; |
| 2125 } | 2135 } |
| 2126 | 2136 |
| 2127 return rect.size(); | 2137 return rect.size(); |
| 2128 } | 2138 } |
| 2129 | 2139 |
| 2130 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { | 2140 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { |
| 2131 DVLOGF(3); | 2141 DVLOGF(3); |
| 2142 DCHECK(decoder_thread_.task_runner()->BelongsToCurrentThread()); | |
| 2132 // We always run this as we prepare to initialize. | 2143 // We always run this as we prepare to initialize. |
| 2133 DCHECK_EQ(decoder_state_, kUninitialized); | 2144 DCHECK_EQ(decoder_state_, kUninitialized); |
| 2134 DCHECK(!input_streamon_); | 2145 DCHECK(!input_streamon_); |
| 2135 DCHECK(input_buffer_map_.empty()); | 2146 DCHECK(input_buffer_map_.empty()); |
| 2136 | 2147 |
| 2137 struct v4l2_requestbuffers reqbufs; | 2148 struct v4l2_requestbuffers reqbufs; |
| 2138 memset(&reqbufs, 0, sizeof(reqbufs)); | 2149 memset(&reqbufs, 0, sizeof(reqbufs)); |
| 2139 reqbufs.count = kInputBufferCount; | 2150 reqbufs.count = kInputBufferCount; |
| 2140 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; | 2151 reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 2141 reqbufs.memory = V4L2_MEMORY_MMAP; | 2152 reqbufs.memory = V4L2_MEMORY_MMAP; |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2624 StartResolutionChange(); | 2635 StartResolutionChange(); |
| 2625 } | 2636 } |
| 2626 } | 2637 } |
| 2627 | 2638 |
| 2628 void V4L2VideoDecodeAccelerator::ImageProcessorError() { | 2639 void V4L2VideoDecodeAccelerator::ImageProcessorError() { |
| 2629 LOGF(ERROR) << "Image processor error"; | 2640 LOGF(ERROR) << "Image processor error"; |
| 2630 NOTIFY_ERROR(PLATFORM_FAILURE); | 2641 NOTIFY_ERROR(PLATFORM_FAILURE); |
| 2631 } | 2642 } |
| 2632 | 2643 |
| 2633 } // namespace media | 2644 } // namespace media |
| OLD | NEW |