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..5ac5d1401f27bf3e4c9e8a8cc38acf4af04394b2 100644 |
--- a/chrome/gpu/arc_gpu_video_decode_accelerator.cc |
+++ b/chrome/gpu/arc_gpu_video_decode_accelerator.cc |
@@ -6,6 +6,7 @@ |
#include "base/callback_helpers.h" |
#include "base/logging.h" |
+#include "base/numerics/safe_math.h" |
#include "base/run_loop.h" |
#include "content/public/gpu/gpu_video_decode_accelerator_factory.h" |
#include "media/base/video_frame.h" |
@@ -21,21 +22,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 +159,49 @@ 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. |
+ DCHECK(height % 2 == 0); // The coded height should be even for YUV. |
dcheng
2016/05/17 18:56:15
Not DCHECK(), this should just return false.
|
+ height = height * 3 / 2; |
+ break; |
+ case media::PIXEL_FORMAT_ARGB: |
+ // No need to adjust height. |
+ break; |
+ default: |
+ DLOG(ERROR) << "Format not supported: " << output_pixel_format_; |
+ return false; |
+ } |
+ base::CheckedNumeric<off_t> used_bytes(height); |
+ used_bytes *= stride; |
+ |
+ if (stride < 0 || !used_bytes.IsValid() || used_bytes.ValueOrDie() > size) { |
+ 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 +218,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 +293,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 +307,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 +413,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); |
} |