Chromium Code Reviews| Index: chrome/gpu/arc_gpu_video_decode_accelerator.cc |
| diff --git a/chrome/gpu/arc_gpu_video_decode_accelerator.cc b/chrome/gpu/arc_gpu_video_decode_accelerator.cc |
| index b4b46b0da454249a619c6f9a6357041eeead1c85..c7770c3e7c8010044f1f1a2ede347e0244ae46ae 100644 |
| --- a/chrome/gpu/arc_gpu_video_decode_accelerator.cc |
| +++ b/chrome/gpu/arc_gpu_video_decode_accelerator.cc |
| @@ -21,21 +21,25 @@ ArcGpuVideoDecodeAccelerator::InputRecord::InputRecord( |
| buffer_index(buffer_index), |
| timestamp(timestamp) {} |
| -ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo() |
| - : offset(0), length(0) {} |
| +ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo() = default; |
| ArcGpuVideoDecodeAccelerator::InputBufferInfo::InputBufferInfo( |
| - InputBufferInfo&& other) |
| - : handle(std::move(other.handle)), |
| - offset(other.offset), |
| - length(other.length) {} |
| + InputBufferInfo&& other) = default; |
| -ArcGpuVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() {} |
| +ArcGpuVideoDecodeAccelerator::InputBufferInfo::~InputBufferInfo() = default; |
| + |
| +ArcGpuVideoDecodeAccelerator::OutputBufferInfo::OutputBufferInfo() = default; |
| + |
| +ArcGpuVideoDecodeAccelerator::OutputBufferInfo::OutputBufferInfo( |
| + OutputBufferInfo&& other) = default; |
| + |
| +ArcGpuVideoDecodeAccelerator::OutputBufferInfo::~OutputBufferInfo() = default; |
| ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator() |
| : pending_eos_output_buffer_(false), |
| arc_client_(nullptr), |
| next_bitstream_buffer_id_(0), |
| + output_pixel_format_(media::PIXEL_FORMAT_UNKNOWN), |
| output_buffer_size_(0) {} |
| ArcGpuVideoDecodeAccelerator::~ArcGpuVideoDecodeAccelerator() {} |
| @@ -154,9 +158,46 @@ void ArcGpuVideoDecodeAccelerator::BindSharedMemory(PortType port, |
| input_info->length = length; |
| } |
| +bool ArcGpuVideoDecodeAccelerator::VerifyStride(const base::ScopedFD& dmabuf_fd, |
| + int32_t stride) { |
| + off_t size = lseek(dmabuf_fd.get(), 0, SEEK_END); |
| + lseek(dmabuf_fd.get(), 0, SEEK_SET); |
| + |
| + if (size < 0) { |
| + DLOG(ERROR) << "fail to find the size of dmabuf" << errno; |
| + return false; |
| + } |
| + |
| + int height = coded_size_.height(); |
| + switch (output_pixel_format_) { |
| + case media::PIXEL_FORMAT_I420: |
| + case media::PIXEL_FORMAT_YV12: |
| + case media::PIXEL_FORMAT_NV12: |
| + case media::PIXEL_FORMAT_NV21: |
| + // Adjusts the height for UV plane. |
| + height = height * 3 / 2; |
|
dcheng
2016/05/17 01:12:28
What happens if height isn't even divisible by two
Owen Lin
2016/05/17 08:52:16
The coded height should be always even for YUV fra
|
| + break; |
| + case media::PIXEL_FORMAT_ARGB: |
| + // No need to adjust height. |
| + break; |
| + default: |
| + DLOG(ERROR) << "Format not supported: " << output_pixel_format_; |
| + return false; |
| + } |
| + |
| + if (stride < 0 || height * stride > size) { |
|
dcheng
2016/05/17 01:12:27
height * stride should use CheckedNumeric: https:/
Owen Lin
2016/05/17 08:52:16
Thanks.
|
| + DLOG(ERROR) << "invalid stride: " << stride << ", height: " << height |
| + << ", size of dmabuf: " << size; |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| void ArcGpuVideoDecodeAccelerator::BindDmabuf(PortType port, |
| uint32_t index, |
| - base::ScopedFD dmabuf_fd) { |
| + base::ScopedFD dmabuf_fd, |
| + int32_t stride) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (!vda_) { |
| @@ -173,7 +214,14 @@ void ArcGpuVideoDecodeAccelerator::BindDmabuf(PortType port, |
| arc_client_->OnError(INVALID_ARGUMENT); |
| return; |
| } |
| - buffers_pending_import_[index] = std::move(dmabuf_fd); |
| + if (!VerifyStride(dmabuf_fd, stride)) { |
| + arc_client_->OnError(INVALID_ARGUMENT); |
| + return; |
| + } |
| + |
| + OutputBufferInfo& info = buffers_pending_import_[index]; |
| + info.handle = std::move(dmabuf_fd); |
| + info.stride = stride; |
| } |
| void ArcGpuVideoDecodeAccelerator::UseBuffer(PortType port, |
| @@ -241,10 +289,10 @@ void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers( |
| << ", dimensions=" << dimensions.ToString() << ")"; |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| coded_size_ = dimensions; |
| + output_pixel_format_ = vda_->GetOutputFormat(); |
| VideoFormat video_format; |
| - media::VideoPixelFormat output_format = vda_->GetOutputFormat(); |
| - switch (output_format) { |
| + switch (output_pixel_format_) { |
| case media::PIXEL_FORMAT_I420: |
| case media::PIXEL_FORMAT_YV12: |
| case media::PIXEL_FORMAT_NV12: |
| @@ -255,12 +303,12 @@ void ArcGpuVideoDecodeAccelerator::ProvidePictureBuffers( |
| video_format.pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888; |
| break; |
| default: |
| - DLOG(ERROR) << "Format not supported: " << output_format; |
| + DLOG(ERROR) << "Format not supported: " << output_pixel_format_; |
| arc_client_->OnError(PLATFORM_FAILURE); |
| return; |
| } |
| video_format.buffer_size = |
| - media::VideoFrame::AllocationSize(output_format, coded_size_); |
| + media::VideoFrame::AllocationSize(output_pixel_format_, coded_size_); |
| output_buffer_size_ = video_format.buffer_size; |
| video_format.min_num_buffers = requested_num_of_buffers; |
| video_format.coded_width = dimensions.width(); |
| @@ -361,14 +409,15 @@ void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture( |
| arc_client_->OnBufferDone(PORT_OUTPUT, index, metadata); |
| pending_eos_output_buffer_ = false; |
| } else { |
| - if (buffers_pending_import_[index].is_valid()) { |
| - std::vector<gfx::GpuMemoryBufferHandle> buffers; |
| - buffers.push_back(gfx::GpuMemoryBufferHandle()); |
| + OutputBufferInfo& info = buffers_pending_import_[index]; |
| + if (info.handle.is_valid()) { |
| + gfx::GpuMemoryBufferHandle handle; |
| #if defined(USE_OZONE) |
| - buffers.back().native_pixmap_handle.fd = |
| - base::FileDescriptor(buffers_pending_import_[index].release(), true); |
| + handle.native_pixmap_handle.fd = |
| + base::FileDescriptor(info.handle.release(), true); |
| + handle.native_pixmap_handle.stride = info.stride; |
| #endif |
| - vda_->ImportBufferForPicture(index, buffers); |
| + vda_->ImportBufferForPicture(index, {handle}); |
| } else { |
| vda_->ReusePictureBuffer(index); |
| } |