Index: content/common/gpu/media/v4l2_video_decode_accelerator.cc |
diff --git a/content/common/gpu/media/v4l2_video_decode_accelerator.cc b/content/common/gpu/media/v4l2_video_decode_accelerator.cc |
index 587da6bbc04ed5449ccadf7bf00f693f9273d3e4..b5d94d404f2db73d1e363b30d5d923492694f581 100644 |
--- a/content/common/gpu/media/v4l2_video_decode_accelerator.cc |
+++ b/content/common/gpu/media/v4l2_video_decode_accelerator.cc |
@@ -5,7 +5,6 @@ |
#include <dlfcn.h> |
#include <errno.h> |
#include <fcntl.h> |
-#include <libdrm/drm_fourcc.h> |
#include <linux/videodev2.h> |
#include <poll.h> |
#include <sys/eventfd.h> |
@@ -267,7 +266,7 @@ bool V4L2VideoDecodeAccelerator::Initialize(media::VideoCodecProfile profile, |
struct v4l2_format format; |
memset(&format, 0, sizeof(format)); |
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
- format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; |
+ format.fmt.pix_mp.pixelformat = device_->GetCapturePixelFormat(); |
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); |
// Subscribe to the resolution change event. |
@@ -330,15 +329,6 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
} |
gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); |
- EGLint attrs[] = { |
- EGL_WIDTH, 0, EGL_HEIGHT, 0, |
- EGL_LINUX_DRM_FOURCC_EXT, 0, EGL_DMA_BUF_PLANE0_FD_EXT, 0, |
- EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0, |
- EGL_DMA_BUF_PLANE1_FD_EXT, 0, EGL_DMA_BUF_PLANE1_OFFSET_EXT, 0, |
- EGL_DMA_BUF_PLANE1_PITCH_EXT, 0, EGL_NONE, }; |
- attrs[1] = frame_buffer_size_.width(); |
- attrs[3] = frame_buffer_size_.height(); |
- attrs[5] = DRM_FORMAT_NV12; |
// It's safe to manipulate all the buffer state here, because the decoder |
// thread is waiting on pictures_assigned_. |
@@ -354,15 +344,11 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
DCHECK_EQ(output_record.picture_id, -1); |
DCHECK_EQ(output_record.cleared, false); |
- attrs[7] = output_record.fds[0]; |
- attrs[9] = 0; |
- attrs[11] = frame_buffer_size_.width(); |
- attrs[13] = output_record.fds[1]; |
- attrs[15] = 0; |
- attrs[17] = frame_buffer_size_.width(); |
- |
- EGLImageKHR egl_image = eglCreateImageKHR( |
- egl_display_, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs); |
+ EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_, |
+ buffers[i].texture_id(), |
+ frame_buffer_size_, |
+ i, |
+ output_buffer_map_.size()); |
if (egl_image == EGL_NO_IMAGE_KHR) { |
DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; |
// Ownership of EGLImages allocated in previous iterations of this loop |
@@ -372,9 +358,6 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers( |
return; |
} |
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id()); |
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); |
- |
output_record.egl_image = egl_image; |
output_record.picture_id = buffers[i].id(); |
free_output_buffers_.push(i); |
@@ -1005,7 +988,9 @@ void V4L2VideoDecodeAccelerator::DequeueEvents() { |
if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { |
DVLOG(3) << "DequeueEvents(): got resolution change event."; |
DCHECK(!resolution_change_pending_); |
- resolution_change_pending_ = true; |
+ if (IsResolutionChangeNecessary()) { |
Pawel Osciak
2014/03/27 05:18:06
resolution_change_pending_ = IsResolutionChangeNec
shivdasp
2014/03/27 05:40:37
Done.
|
+ resolution_change_pending_ = true; |
+ } |
} else { |
DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type |
<< ") we haven't subscribed to."; |
@@ -1536,7 +1521,6 @@ void V4L2VideoDecodeAccelerator::FinishResolutionChange() { |
NOTIFY_ERROR(PLATFORM_FAILURE); |
return; |
} |
- |
if (!CreateBuffersForFormat(format)) { |
DVLOG(3) << "Couldn't reallocate buffers after resolution change"; |
NOTIFY_ERROR(PLATFORM_FAILURE); |
@@ -1632,11 +1616,11 @@ bool V4L2VideoDecodeAccelerator::GetFormatInfo(struct v4l2_format* format, |
bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( |
const struct v4l2_format& format) { |
DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); |
- CHECK_EQ(format.fmt.pix_mp.num_planes, 2); |
+ CHECK_EQ(format.fmt.pix_mp.num_planes, device_->GetNumberOfPlanes()); |
frame_buffer_size_.SetSize( |
format.fmt.pix_mp.width, format.fmt.pix_mp.height); |
output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; |
- DCHECK_EQ(output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M); |
+ DCHECK_EQ(output_buffer_pixelformat_, device_->GetCapturePixelFormat()); |
DVLOG(3) << "CreateBuffersForFormat(): new resolution: " |
<< frame_buffer_size_.ToString(); |
@@ -1733,22 +1717,7 @@ bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { |
reqbufs.memory = V4L2_MEMORY_MMAP; |
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); |
- // Create DMABUFs from output buffers. |
output_buffer_map_.resize(reqbufs.count); |
- for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
- OutputRecord& output_record = output_buffer_map_[i]; |
- for (size_t j = 0; j < arraysize(output_record.fds); ++j) { |
- // Export the DMABUF fd so we can export it as a texture. |
- struct v4l2_exportbuffer expbuf; |
- memset(&expbuf, 0, sizeof(expbuf)); |
- expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
- expbuf.index = i; |
- expbuf.plane = j; |
- expbuf.flags = O_CLOEXEC; |
- IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_EXPBUF, &expbuf); |
- output_record.fds[j] = expbuf.fd; |
- } |
- } |
DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " |
<< "buffer_count=" << output_buffer_map_.size() |
@@ -1759,7 +1728,7 @@ bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() { |
client_, |
output_buffer_map_.size(), |
frame_buffer_size_, |
- GL_TEXTURE_EXTERNAL_OES)); |
+ device_->GetTextureTarget())); |
// Wait for the client to call AssignPictureBuffers() on the Child thread. |
// We do this, because if we continue decoding without finishing buffer |
@@ -1812,14 +1781,9 @@ bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { |
for (size_t i = 0; i < output_buffer_map_.size(); ++i) { |
OutputRecord& output_record = output_buffer_map_[i]; |
- for (size_t j = 0; j < arraysize(output_record.fds); ++j) { |
- if (output_record.fds[j] != -1) { |
- if (close(output_record.fds[j])) { |
- DVPLOG(1) << __func__ << " close() on a dmabuf fd failed."; |
- success = false; |
- } |
- } |
- } |
+ |
+ device_->DestroyEGLImage(i); |
+ |
if (output_record.egl_image != EGL_NO_IMAGE_KHR) { |
if (eglDestroyImageKHR(egl_display_, output_record.egl_image) != |
EGL_TRUE) { |
@@ -1926,4 +1890,34 @@ void V4L2VideoDecodeAccelerator::PictureCleared() { |
SendPictureReady(); |
} |
+bool V4L2VideoDecodeAccelerator::IsResolutionChangeNecessary() { |
+ if (frame_buffer_size_.IsEmpty()) |
+ return true; |
+ |
+ struct v4l2_control ctrl; |
+ memset(&ctrl, 0, sizeof(ctrl)); |
+ ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE; |
+ IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl); |
+ if (ctrl.value != output_dpb_size_) { |
+ DVLOG(3) |
+ << "IsResolutionChangeNecessary(): Returning true since DPB mismatch "; |
+ return true; |
+ } |
+ struct v4l2_format format; |
+ bool again = false; |
+ bool ret = GetFormatInfo(&format, &again); |
+ if (!ret || again) { |
+ DVLOG(3) << "IsResolutionChangeNecessary(): GetFormatInfo() failed"; |
+ return false; |
+ } |
+ if ((static_cast<int>(format.fmt.pix_mp.width) != |
Pawel Osciak
2014/03/27 05:18:06
gfx::Size new_size(base::checked_cast<int>(format.
shivdasp
2014/03/27 05:40:37
Will do.
|
+ frame_buffer_size_.width()) || |
+ (static_cast<int>(format.fmt.pix_mp.height) != |
+ frame_buffer_size_.height())) { |
+ DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected"; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
} // namespace content |