| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "content/common/gpu/media/vaapi_jpeg_decode_accelerator.h" | 5 #include "content/common/gpu/media/vaapi_jpeg_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "content/common/gpu/gpu_channel.h" | 16 #include "content/common/gpu/gpu_channel.h" |
| 17 #include "content/common/gpu/media/shared_memory_region.h" |
| 17 #include "content/common/gpu/media/vaapi_picture.h" | 18 #include "content/common/gpu/media/vaapi_picture.h" |
| 18 #include "media/base/video_frame.h" | 19 #include "media/base/video_frame.h" |
| 19 #include "media/filters/jpeg_parser.h" | 20 #include "media/filters/jpeg_parser.h" |
| 20 #include "third_party/libyuv/include/libyuv.h" | 21 #include "third_party/libyuv/include/libyuv.h" |
| 21 | 22 |
| 22 namespace content { | 23 namespace content { |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 // UMA errors that the VaapiJpegDecodeAccelerator class reports. | 26 // UMA errors that the VaapiJpegDecodeAccelerator class reports. |
| 26 enum VAJDADecoderFailure { | 27 enum VAJDADecoderFailure { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 DVLOG(1) << "Unsupported sampling factor: num_components=" | 70 DVLOG(1) << "Unsupported sampling factor: num_components=" |
| 70 << frame_header.num_components << ", h=" << std::hex << h | 71 << frame_header.num_components << ", h=" << std::hex << h |
| 71 << ", v=" << v; | 72 << ", v=" << v; |
| 72 | 73 |
| 73 return 0; | 74 return 0; |
| 74 } | 75 } |
| 75 | 76 |
| 76 } // namespace | 77 } // namespace |
| 77 | 78 |
| 78 VaapiJpegDecodeAccelerator::DecodeRequest::DecodeRequest( | 79 VaapiJpegDecodeAccelerator::DecodeRequest::DecodeRequest( |
| 79 const media::BitstreamBuffer& bitstream_buffer, | 80 int32_t bitstream_buffer_id, |
| 80 scoped_ptr<base::SharedMemory> shm, | 81 scoped_ptr<SharedMemoryRegion> shm, |
| 81 const scoped_refptr<media::VideoFrame>& video_frame) | 82 const scoped_refptr<media::VideoFrame>& video_frame) |
| 82 : bitstream_buffer(bitstream_buffer), | 83 : bitstream_buffer_id(bitstream_buffer_id), |
| 83 shm(std::move(shm)), | 84 shm(std::move(shm)), |
| 84 video_frame(video_frame) {} | 85 video_frame(video_frame) {} |
| 85 | 86 |
| 86 VaapiJpegDecodeAccelerator::DecodeRequest::~DecodeRequest() { | 87 VaapiJpegDecodeAccelerator::DecodeRequest::~DecodeRequest() { |
| 87 } | 88 } |
| 88 | 89 |
| 89 void VaapiJpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id, | 90 void VaapiJpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id, |
| 90 Error error) { | 91 Error error) { |
| 91 DCHECK(task_runner_->BelongsToCurrentThread()); | 92 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 92 DLOG(ERROR) << "Notifying of error " << error; | 93 DLOG(ERROR) << "Notifying of error " << error; |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 220 |
| 220 void VaapiJpegDecodeAccelerator::DecodeTask( | 221 void VaapiJpegDecodeAccelerator::DecodeTask( |
| 221 const scoped_ptr<DecodeRequest>& request) { | 222 const scoped_ptr<DecodeRequest>& request) { |
| 222 DVLOG(3) << __func__; | 223 DVLOG(3) << __func__; |
| 223 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); | 224 DCHECK(decoder_task_runner_->BelongsToCurrentThread()); |
| 224 TRACE_EVENT0("jpeg", "DecodeTask"); | 225 TRACE_EVENT0("jpeg", "DecodeTask"); |
| 225 | 226 |
| 226 media::JpegParseResult parse_result; | 227 media::JpegParseResult parse_result; |
| 227 if (!media::ParseJpegPicture( | 228 if (!media::ParseJpegPicture( |
| 228 reinterpret_cast<const uint8_t*>(request->shm->memory()), | 229 reinterpret_cast<const uint8_t*>(request->shm->memory()), |
| 229 request->bitstream_buffer.size(), &parse_result)) { | 230 request->shm->size(), &parse_result)) { |
| 230 DLOG(ERROR) << "ParseJpegPicture failed"; | 231 DLOG(ERROR) << "ParseJpegPicture failed"; |
| 231 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(), | 232 NotifyErrorFromDecoderThread(request->bitstream_buffer_id, |
| 232 PARSE_JPEG_FAILED); | 233 PARSE_JPEG_FAILED); |
| 233 return; | 234 return; |
| 234 } | 235 } |
| 235 | 236 |
| 236 unsigned int new_va_rt_format = | 237 unsigned int new_va_rt_format = |
| 237 VaSurfaceFormatForJpeg(parse_result.frame_header); | 238 VaSurfaceFormatForJpeg(parse_result.frame_header); |
| 238 if (!new_va_rt_format) { | 239 if (!new_va_rt_format) { |
| 239 DLOG(ERROR) << "Unsupported subsampling"; | 240 DLOG(ERROR) << "Unsupported subsampling"; |
| 240 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(), | 241 NotifyErrorFromDecoderThread(request->bitstream_buffer_id, |
| 241 UNSUPPORTED_JPEG); | 242 UNSUPPORTED_JPEG); |
| 242 return; | 243 return; |
| 243 } | 244 } |
| 244 | 245 |
| 245 // Reuse VASurface if size doesn't change. | 246 // Reuse VASurface if size doesn't change. |
| 246 gfx::Size new_coded_size(parse_result.frame_header.coded_width, | 247 gfx::Size new_coded_size(parse_result.frame_header.coded_width, |
| 247 parse_result.frame_header.coded_height); | 248 parse_result.frame_header.coded_height); |
| 248 if (new_coded_size != coded_size_ || va_surface_id_ == VA_INVALID_SURFACE || | 249 if (new_coded_size != coded_size_ || va_surface_id_ == VA_INVALID_SURFACE || |
| 249 new_va_rt_format != va_rt_format_) { | 250 new_va_rt_format != va_rt_format_) { |
| 250 vaapi_wrapper_->DestroySurfaces(); | 251 vaapi_wrapper_->DestroySurfaces(); |
| 251 va_surface_id_ = VA_INVALID_SURFACE; | 252 va_surface_id_ = VA_INVALID_SURFACE; |
| 252 va_rt_format_ = new_va_rt_format; | 253 va_rt_format_ = new_va_rt_format; |
| 253 | 254 |
| 254 std::vector<VASurfaceID> va_surfaces; | 255 std::vector<VASurfaceID> va_surfaces; |
| 255 if (!vaapi_wrapper_->CreateSurfaces(va_rt_format_, new_coded_size, 1, | 256 if (!vaapi_wrapper_->CreateSurfaces(va_rt_format_, new_coded_size, 1, |
| 256 &va_surfaces)) { | 257 &va_surfaces)) { |
| 257 LOG(ERROR) << "Create VA surface failed"; | 258 LOG(ERROR) << "Create VA surface failed"; |
| 258 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(), | 259 NotifyErrorFromDecoderThread(request->bitstream_buffer_id, |
| 259 PLATFORM_FAILURE); | 260 PLATFORM_FAILURE); |
| 260 return; | 261 return; |
| 261 } | 262 } |
| 262 va_surface_id_ = va_surfaces[0]; | 263 va_surface_id_ = va_surfaces[0]; |
| 263 coded_size_ = new_coded_size; | 264 coded_size_ = new_coded_size; |
| 264 } | 265 } |
| 265 | 266 |
| 266 if (!VaapiJpegDecoder::Decode(vaapi_wrapper_.get(), parse_result, | 267 if (!VaapiJpegDecoder::Decode(vaapi_wrapper_.get(), parse_result, |
| 267 va_surface_id_)) { | 268 va_surface_id_)) { |
| 268 LOG(ERROR) << "Decode JPEG failed"; | 269 LOG(ERROR) << "Decode JPEG failed"; |
| 269 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(), | 270 NotifyErrorFromDecoderThread(request->bitstream_buffer_id, |
| 270 PLATFORM_FAILURE); | 271 PLATFORM_FAILURE); |
| 271 return; | 272 return; |
| 272 } | 273 } |
| 273 | 274 |
| 274 if (!OutputPicture(va_surface_id_, request->bitstream_buffer.id(), | 275 if (!OutputPicture(va_surface_id_, request->bitstream_buffer_id, |
| 275 request->video_frame)) { | 276 request->video_frame)) { |
| 276 LOG(ERROR) << "Output picture failed"; | 277 LOG(ERROR) << "Output picture failed"; |
| 277 NotifyErrorFromDecoderThread(request->bitstream_buffer.id(), | 278 NotifyErrorFromDecoderThread(request->bitstream_buffer_id, |
| 278 PLATFORM_FAILURE); | 279 PLATFORM_FAILURE); |
| 279 return; | 280 return; |
| 280 } | 281 } |
| 281 } | 282 } |
| 282 | 283 |
| 283 void VaapiJpegDecodeAccelerator::Decode( | 284 void VaapiJpegDecodeAccelerator::Decode( |
| 284 const media::BitstreamBuffer& bitstream_buffer, | 285 const media::BitstreamBuffer& bitstream_buffer, |
| 285 const scoped_refptr<media::VideoFrame>& video_frame) { | 286 const scoped_refptr<media::VideoFrame>& video_frame) { |
| 286 DVLOG(3) << __func__; | 287 DVLOG(3) << __func__; |
| 287 DCHECK(io_task_runner_->BelongsToCurrentThread()); | 288 DCHECK(io_task_runner_->BelongsToCurrentThread()); |
| 288 TRACE_EVENT1("jpeg", "Decode", "input_id", bitstream_buffer.id()); | 289 TRACE_EVENT1("jpeg", "Decode", "input_id", bitstream_buffer.id()); |
| 289 | 290 |
| 290 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() | 291 DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id() |
| 291 << " size: " << bitstream_buffer.size(); | 292 << " size: " << bitstream_buffer.size(); |
| 292 | 293 |
| 294 // SharedMemoryRegion will take over the |bitstream_buffer.handle()|. |
| 295 scoped_ptr<SharedMemoryRegion> shm( |
| 296 new SharedMemoryRegion(bitstream_buffer, true)); |
| 297 |
| 293 if (bitstream_buffer.id() < 0) { | 298 if (bitstream_buffer.id() < 0) { |
| 294 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); | 299 LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id(); |
| 295 if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle())) | |
| 296 base::SharedMemory::CloseHandle(bitstream_buffer.handle()); | |
| 297 NotifyErrorFromDecoderThread(bitstream_buffer.id(), INVALID_ARGUMENT); | 300 NotifyErrorFromDecoderThread(bitstream_buffer.id(), INVALID_ARGUMENT); |
| 298 return; | 301 return; |
| 299 } | 302 } |
| 300 | 303 |
| 301 scoped_ptr<base::SharedMemory> shm( | 304 if (!shm->Map()) { |
| 302 new base::SharedMemory(bitstream_buffer.handle(), true)); | |
| 303 | |
| 304 if (!shm->Map(bitstream_buffer.size())) { | |
| 305 LOG(ERROR) << "Failed to map input buffer"; | 305 LOG(ERROR) << "Failed to map input buffer"; |
| 306 NotifyErrorFromDecoderThread(bitstream_buffer.id(), UNREADABLE_INPUT); | 306 NotifyErrorFromDecoderThread(bitstream_buffer.id(), UNREADABLE_INPUT); |
| 307 return; | 307 return; |
| 308 } | 308 } |
| 309 | 309 |
| 310 scoped_ptr<DecodeRequest> request( | 310 scoped_ptr<DecodeRequest> request( |
| 311 new DecodeRequest(bitstream_buffer, std::move(shm), video_frame)); | 311 new DecodeRequest(bitstream_buffer.id(), std::move(shm), video_frame)); |
| 312 | 312 |
| 313 decoder_task_runner_->PostTask( | 313 decoder_task_runner_->PostTask( |
| 314 FROM_HERE, base::Bind(&VaapiJpegDecodeAccelerator::DecodeTask, | 314 FROM_HERE, base::Bind(&VaapiJpegDecodeAccelerator::DecodeTask, |
| 315 base::Unretained(this), base::Passed(&request))); | 315 base::Unretained(this), base::Passed(&request))); |
| 316 } | 316 } |
| 317 | 317 |
| 318 bool VaapiJpegDecodeAccelerator::IsSupported() { | 318 bool VaapiJpegDecodeAccelerator::IsSupported() { |
| 319 return VaapiWrapper::IsJpegDecodeSupported(); | 319 return VaapiWrapper::IsJpegDecodeSupported(); |
| 320 } | 320 } |
| 321 | 321 |
| 322 } // namespace content | 322 } // namespace content |
| OLD | NEW |