Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Side by Side Diff: content/common/gpu/media/v4l2_video_decode_accelerator.cc

Issue 137023008: Add support for Tegra V4L2 VDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <dlfcn.h> 5 #include <dlfcn.h>
6 #include <errno.h> 6 #include <errno.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <libdrm/drm_fourcc.h>
9 #include <linux/videodev2.h> 8 #include <linux/videodev2.h>
10 #include <poll.h> 9 #include <poll.h>
11 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
12 #include <sys/ioctl.h> 11 #include <sys/ioctl.h>
13 #include <sys/mman.h> 12 #include <sys/mman.h>
14 13
15 #include "base/bind.h" 14 #include "base/bind.h"
16 #include "base/debug/trace_event.h" 15 #include "base/debug/trace_event.h"
17 #include "base/memory/shared_memory.h" 16 #include "base/memory/shared_memory.h"
18 #include "base/message_loop/message_loop.h" 17 #include "base/message_loop/message_loop.h"
19 #include "base/message_loop/message_loop_proxy.h" 18 #include "base/message_loop/message_loop_proxy.h"
19 #include "base/numerics/safe_conversions.h"
20 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h" 21 #include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
22 #include "media/filters/h264_parser.h" 22 #include "media/filters/h264_parser.h"
23 #include "ui/gl/scoped_binders.h" 23 #include "ui/gl/scoped_binders.h"
24 24
25 namespace content { 25 namespace content {
26 26
27 #define NOTIFY_ERROR(x) \ 27 #define NOTIFY_ERROR(x) \
28 do { \ 28 do { \
29 SetDecoderState(kError); \ 29 SetDecoderState(kError); \
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 V4L2VideoDecodeAccelerator::InputRecord::~InputRecord() { 132 V4L2VideoDecodeAccelerator::InputRecord::~InputRecord() {
133 } 133 }
134 134
135 V4L2VideoDecodeAccelerator::OutputRecord::OutputRecord() 135 V4L2VideoDecodeAccelerator::OutputRecord::OutputRecord()
136 : at_device(false), 136 : at_device(false),
137 at_client(false), 137 at_client(false),
138 egl_image(EGL_NO_IMAGE_KHR), 138 egl_image(EGL_NO_IMAGE_KHR),
139 egl_sync(EGL_NO_SYNC_KHR), 139 egl_sync(EGL_NO_SYNC_KHR),
140 picture_id(-1), 140 picture_id(-1),
141 cleared(false) { 141 cleared(false) {
142 for (size_t i = 0; i < arraysize(fds); ++i)
143 fds[i] = -1;
144 } 142 }
145 143
146 V4L2VideoDecodeAccelerator::OutputRecord::~OutputRecord() {} 144 V4L2VideoDecodeAccelerator::OutputRecord::~OutputRecord() {}
147 145
148 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord( 146 V4L2VideoDecodeAccelerator::PictureRecord::PictureRecord(
149 bool cleared, 147 bool cleared,
150 const media::Picture& picture) 148 const media::Picture& picture)
151 : cleared(cleared), picture(picture) {} 149 : cleared(cleared), picture(picture) {}
152 150
153 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {} 151 V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
(...skipping 18 matching lines...) Expand all
172 decoder_flushing_(false), 170 decoder_flushing_(false),
173 resolution_change_pending_(false), 171 resolution_change_pending_(false),
174 resolution_change_reset_pending_(false), 172 resolution_change_reset_pending_(false),
175 decoder_partial_frame_pending_(false), 173 decoder_partial_frame_pending_(false),
176 input_streamon_(false), 174 input_streamon_(false),
177 input_buffer_queued_count_(0), 175 input_buffer_queued_count_(0),
178 output_streamon_(false), 176 output_streamon_(false),
179 output_buffer_queued_count_(0), 177 output_buffer_queued_count_(0),
180 output_buffer_pixelformat_(0), 178 output_buffer_pixelformat_(0),
181 output_dpb_size_(0), 179 output_dpb_size_(0),
180 output_planes_count_(0),
182 picture_clearing_count_(0), 181 picture_clearing_count_(0),
183 pictures_assigned_(false, false), 182 pictures_assigned_(false, false),
184 device_poll_thread_("V4L2DevicePollThread"), 183 device_poll_thread_("V4L2DevicePollThread"),
185 make_context_current_(make_context_current), 184 make_context_current_(make_context_current),
186 egl_display_(egl_display), 185 egl_display_(egl_display),
187 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {} 186 video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN) {}
188 187
189 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() { 188 V4L2VideoDecodeAccelerator::~V4L2VideoDecodeAccelerator() {
190 DCHECK(!decoder_thread_.IsRunning()); 189 DCHECK(!decoder_thread_.IsRunning());
191 DCHECK(!device_poll_thread_.IsRunning()); 190 DCHECK(!device_poll_thread_.IsRunning());
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 return false; 259 return false;
261 } 260 }
262 261
263 if (!CreateInputBuffers()) 262 if (!CreateInputBuffers())
264 return false; 263 return false;
265 264
266 // Output format has to be setup before streaming starts. 265 // Output format has to be setup before streaming starts.
267 struct v4l2_format format; 266 struct v4l2_format format;
268 memset(&format, 0, sizeof(format)); 267 memset(&format, 0, sizeof(format));
269 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 268 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
270 format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M; 269 format.fmt.pix_mp.pixelformat = device_->PreferredOutputFormat();
271 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format); 270 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_FMT, &format);
272 271
273 // Subscribe to the resolution change event. 272 // Subscribe to the resolution change event.
274 struct v4l2_event_subscription sub; 273 struct v4l2_event_subscription sub;
275 memset(&sub, 0, sizeof(sub)); 274 memset(&sub, 0, sizeof(sub));
276 sub.type = V4L2_EVENT_RESOLUTION_CHANGE; 275 sub.type = V4L2_EVENT_RESOLUTION_CHANGE;
277 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub); 276 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_SUBSCRIBE_EVENT, &sub);
278 277
279 // Initialize format-specific bits. 278 // Initialize format-specific bits.
280 if (video_profile_ >= media::H264PROFILE_MIN && 279 if (video_profile_ >= media::H264PROFILE_MIN &&
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 return; 322 return;
324 } 323 }
325 324
326 if (!make_context_current_.Run()) { 325 if (!make_context_current_.Run()) {
327 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current"; 326 DLOG(ERROR) << "AssignPictureBuffers(): could not make context current";
328 NOTIFY_ERROR(PLATFORM_FAILURE); 327 NOTIFY_ERROR(PLATFORM_FAILURE);
329 return; 328 return;
330 } 329 }
331 330
332 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0); 331 gfx::ScopedTextureBinder bind_restore(GL_TEXTURE_EXTERNAL_OES, 0);
333 EGLint attrs[] = {
334 EGL_WIDTH, 0, EGL_HEIGHT, 0,
335 EGL_LINUX_DRM_FOURCC_EXT, 0, EGL_DMA_BUF_PLANE0_FD_EXT, 0,
336 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
337 EGL_DMA_BUF_PLANE1_FD_EXT, 0, EGL_DMA_BUF_PLANE1_OFFSET_EXT, 0,
338 EGL_DMA_BUF_PLANE1_PITCH_EXT, 0, EGL_NONE, };
339 attrs[1] = frame_buffer_size_.width();
340 attrs[3] = frame_buffer_size_.height();
341 attrs[5] = DRM_FORMAT_NV12;
342 332
343 // It's safe to manipulate all the buffer state here, because the decoder 333 // It's safe to manipulate all the buffer state here, because the decoder
344 // thread is waiting on pictures_assigned_. 334 // thread is waiting on pictures_assigned_.
345 DCHECK(free_output_buffers_.empty()); 335 DCHECK(free_output_buffers_.empty());
346 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 336 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
347 DCHECK(buffers[i].size() == frame_buffer_size_); 337 DCHECK(buffers[i].size() == frame_buffer_size_);
348 338
349 OutputRecord& output_record = output_buffer_map_[i]; 339 OutputRecord& output_record = output_buffer_map_[i];
350 DCHECK(!output_record.at_device); 340 DCHECK(!output_record.at_device);
351 DCHECK(!output_record.at_client); 341 DCHECK(!output_record.at_client);
352 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR); 342 DCHECK_EQ(output_record.egl_image, EGL_NO_IMAGE_KHR);
353 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR); 343 DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
354 DCHECK_EQ(output_record.picture_id, -1); 344 DCHECK_EQ(output_record.picture_id, -1);
355 DCHECK_EQ(output_record.cleared, false); 345 DCHECK_EQ(output_record.cleared, false);
356 346
357 attrs[7] = output_record.fds[0]; 347 EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
358 attrs[9] = 0; 348 buffers[i].texture_id(),
359 attrs[11] = frame_buffer_size_.width(); 349 frame_buffer_size_,
360 attrs[13] = output_record.fds[1]; 350 i,
361 attrs[15] = 0; 351 output_planes_count_);
362 attrs[17] = frame_buffer_size_.width();
363
364 EGLImageKHR egl_image = eglCreateImageKHR(
365 egl_display_, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs);
366 if (egl_image == EGL_NO_IMAGE_KHR) { 352 if (egl_image == EGL_NO_IMAGE_KHR) {
367 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR"; 353 DLOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
368 // Ownership of EGLImages allocated in previous iterations of this loop 354 // Ownership of EGLImages allocated in previous iterations of this loop
369 // has been transferred to output_buffer_map_. After we error-out here 355 // has been transferred to output_buffer_map_. After we error-out here
370 // the destructor will handle their cleanup. 356 // the destructor will handle their cleanup.
371 NOTIFY_ERROR(PLATFORM_FAILURE); 357 NOTIFY_ERROR(PLATFORM_FAILURE);
372 return; 358 return;
373 } 359 }
374 360
375 glBindTexture(GL_TEXTURE_EXTERNAL_OES, buffers[i].texture_id());
376 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
377
378 output_record.egl_image = egl_image; 361 output_record.egl_image = egl_image;
379 output_record.picture_id = buffers[i].id(); 362 output_record.picture_id = buffers[i].id();
380 free_output_buffers_.push(i); 363 free_output_buffers_.push(i);
381 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i 364 DVLOG(3) << "AssignPictureBuffers(): buffer[" << i
382 << "]: picture_id=" << output_record.picture_id; 365 << "]: picture_id=" << output_record.picture_id;
383 } 366 }
384 367
385 pictures_assigned_.Signal(); 368 pictures_assigned_.Signal();
386 } 369 }
387 370
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 DCHECK_NE(decoder_state_, kUninitialized); 981 DCHECK_NE(decoder_state_, kUninitialized);
999 DVLOG(3) << "DequeueEvents()"; 982 DVLOG(3) << "DequeueEvents()";
1000 983
1001 struct v4l2_event ev; 984 struct v4l2_event ev;
1002 memset(&ev, 0, sizeof(ev)); 985 memset(&ev, 0, sizeof(ev));
1003 986
1004 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) { 987 while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) {
1005 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) { 988 if (ev.type == V4L2_EVENT_RESOLUTION_CHANGE) {
1006 DVLOG(3) << "DequeueEvents(): got resolution change event."; 989 DVLOG(3) << "DequeueEvents(): got resolution change event.";
1007 DCHECK(!resolution_change_pending_); 990 DCHECK(!resolution_change_pending_);
1008 resolution_change_pending_ = true; 991 resolution_change_pending_ = IsResolutionChangeNecessary();
1009 } else { 992 } else {
1010 DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type 993 DLOG(FATAL) << "DequeueEvents(): got an event (" << ev.type
1011 << ") we haven't subscribed to."; 994 << ") we haven't subscribed to.";
1012 } 995 }
1013 } 996 }
1014 } 997 }
1015 998
1016 void V4L2VideoDecodeAccelerator::Dequeue() { 999 void V4L2VideoDecodeAccelerator::Dequeue() {
1017 DVLOG(3) << "Dequeue()"; 1000 DVLOG(3) << "Dequeue()";
1018 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1001 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1019 DCHECK_NE(decoder_state_, kUninitialized); 1002 DCHECK_NE(decoder_state_, kUninitialized);
1020 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue"); 1003 TRACE_EVENT0("Video Decoder", "V4L2VDA::Dequeue");
1021 1004
1022 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free 1005 // Dequeue completed input (VIDEO_OUTPUT) buffers, and recycle to the free
1023 // list. 1006 // list.
1024 struct v4l2_buffer dqbuf;
1025 struct v4l2_plane planes[2];
1026 while (input_buffer_queued_count_ > 0) { 1007 while (input_buffer_queued_count_ > 0) {
1027 DCHECK(input_streamon_); 1008 DCHECK(input_streamon_);
1009 struct v4l2_buffer dqbuf;
1010 struct v4l2_plane planes[1];
1028 memset(&dqbuf, 0, sizeof(dqbuf)); 1011 memset(&dqbuf, 0, sizeof(dqbuf));
1029 memset(planes, 0, sizeof(planes)); 1012 memset(planes, 0, sizeof(planes));
1030 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 1013 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1031 dqbuf.memory = V4L2_MEMORY_MMAP; 1014 dqbuf.memory = V4L2_MEMORY_MMAP;
1032 dqbuf.m.planes = planes; 1015 dqbuf.m.planes = planes;
1033 dqbuf.length = 1; 1016 dqbuf.length = 1;
1034 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 1017 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
1035 if (errno == EAGAIN) { 1018 if (errno == EAGAIN) {
1036 // EAGAIN if we're just out of buffers to dequeue. 1019 // EAGAIN if we're just out of buffers to dequeue.
1037 break; 1020 break;
1038 } 1021 }
1039 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; 1022 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
1040 NOTIFY_ERROR(PLATFORM_FAILURE); 1023 NOTIFY_ERROR(PLATFORM_FAILURE);
1041 return; 1024 return;
1042 } 1025 }
1043 InputRecord& input_record = input_buffer_map_[dqbuf.index]; 1026 InputRecord& input_record = input_buffer_map_[dqbuf.index];
1044 DCHECK(input_record.at_device); 1027 DCHECK(input_record.at_device);
1045 free_input_buffers_.push_back(dqbuf.index); 1028 free_input_buffers_.push_back(dqbuf.index);
1046 input_record.at_device = false; 1029 input_record.at_device = false;
1047 input_record.bytes_used = 0; 1030 input_record.bytes_used = 0;
1048 input_record.input_id = -1; 1031 input_record.input_id = -1;
1049 input_buffer_queued_count_--; 1032 input_buffer_queued_count_--;
1050 } 1033 }
1051 1034
1052 // Dequeue completed output (VIDEO_CAPTURE) buffers, and queue to the 1035 // Dequeue completed output (VIDEO_CAPTURE) buffers, and queue to the
1053 // completed queue. 1036 // completed queue.
1054 while (output_buffer_queued_count_ > 0) { 1037 while (output_buffer_queued_count_ > 0) {
1055 DCHECK(output_streamon_); 1038 DCHECK(output_streamon_);
1039 struct v4l2_buffer dqbuf;
1040 scoped_ptr<struct v4l2_plane[]> planes(
1041 new v4l2_plane[output_planes_count_]);
1056 memset(&dqbuf, 0, sizeof(dqbuf)); 1042 memset(&dqbuf, 0, sizeof(dqbuf));
1057 memset(planes, 0, sizeof(planes)); 1043 memset(planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_);
1058 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1044 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1059 dqbuf.memory = V4L2_MEMORY_MMAP; 1045 dqbuf.memory = V4L2_MEMORY_MMAP;
1060 dqbuf.m.planes = planes; 1046 dqbuf.m.planes = planes.get();
1061 dqbuf.length = 2; 1047 dqbuf.length = output_planes_count_;
1062 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 1048 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
1063 if (errno == EAGAIN) { 1049 if (errno == EAGAIN) {
1064 // EAGAIN if we're just out of buffers to dequeue. 1050 // EAGAIN if we're just out of buffers to dequeue.
1065 break; 1051 break;
1066 } 1052 }
1067 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF"; 1053 DPLOG(ERROR) << "Dequeue(): ioctl() failed: VIDIOC_DQBUF";
1068 NOTIFY_ERROR(PLATFORM_FAILURE); 1054 NOTIFY_ERROR(PLATFORM_FAILURE);
1069 return; 1055 return;
1070 } 1056 }
1071 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; 1057 OutputRecord& output_record = output_buffer_map_[dqbuf.index];
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 DVLOG(1) << __func__ << " eglClientWaitSyncKHR failed!"; 1133 DVLOG(1) << __func__ << " eglClientWaitSyncKHR failed!";
1148 } 1134 }
1149 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { 1135 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) {
1150 DLOG(FATAL) << __func__ << " eglDestroySyncKHR failed!"; 1136 DLOG(FATAL) << __func__ << " eglDestroySyncKHR failed!";
1151 NOTIFY_ERROR(PLATFORM_FAILURE); 1137 NOTIFY_ERROR(PLATFORM_FAILURE);
1152 return false; 1138 return false;
1153 } 1139 }
1154 output_record.egl_sync = EGL_NO_SYNC_KHR; 1140 output_record.egl_sync = EGL_NO_SYNC_KHR;
1155 } 1141 }
1156 struct v4l2_buffer qbuf; 1142 struct v4l2_buffer qbuf;
1157 struct v4l2_plane qbuf_planes[arraysize(output_record.fds)]; 1143 scoped_ptr<struct v4l2_plane[]> qbuf_planes(
1144 new v4l2_plane[output_planes_count_]);
1158 memset(&qbuf, 0, sizeof(qbuf)); 1145 memset(&qbuf, 0, sizeof(qbuf));
1159 memset(qbuf_planes, 0, sizeof(qbuf_planes)); 1146 memset(
1147 qbuf_planes.get(), 0, sizeof(struct v4l2_plane) * output_planes_count_);
1160 qbuf.index = buffer; 1148 qbuf.index = buffer;
1161 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1149 qbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1162 qbuf.memory = V4L2_MEMORY_MMAP; 1150 qbuf.memory = V4L2_MEMORY_MMAP;
1163 qbuf.m.planes = qbuf_planes; 1151 qbuf.m.planes = qbuf_planes.get();
1164 qbuf.length = arraysize(output_record.fds); 1152 qbuf.length = output_planes_count_;
1165 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 1153 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
1166 free_output_buffers_.pop(); 1154 free_output_buffers_.pop();
1167 output_record.at_device = true; 1155 output_record.at_device = true;
1168 output_buffer_queued_count_++; 1156 output_buffer_queued_count_++;
1169 return true; 1157 return true;
1170 } 1158 }
1171 1159
1172 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask( 1160 void V4L2VideoDecodeAccelerator::ReusePictureBufferTask(
1173 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) { 1161 int32 picture_buffer_id, scoped_ptr<EGLSyncKHRRef> egl_sync_ref) {
1174 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id=" 1162 DVLOG(3) << "ReusePictureBufferTask(): picture_buffer_id="
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 return false; 1613 return false;
1626 } 1614 }
1627 } 1615 }
1628 1616
1629 return true; 1617 return true;
1630 } 1618 }
1631 1619
1632 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat( 1620 bool V4L2VideoDecodeAccelerator::CreateBuffersForFormat(
1633 const struct v4l2_format& format) { 1621 const struct v4l2_format& format) {
1634 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1622 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1635 CHECK_EQ(format.fmt.pix_mp.num_planes, 2); 1623 output_planes_count_ = format.fmt.pix_mp.num_planes;
1636 frame_buffer_size_.SetSize( 1624 frame_buffer_size_.SetSize(
1637 format.fmt.pix_mp.width, format.fmt.pix_mp.height); 1625 format.fmt.pix_mp.width, format.fmt.pix_mp.height);
1638 output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat; 1626 output_buffer_pixelformat_ = format.fmt.pix_mp.pixelformat;
1639 DCHECK_EQ(output_buffer_pixelformat_, V4L2_PIX_FMT_NV12M); 1627 DCHECK_EQ(output_buffer_pixelformat_, device_->PreferredOutputFormat());
1640 DVLOG(3) << "CreateBuffersForFormat(): new resolution: " 1628 DVLOG(3) << "CreateBuffersForFormat(): new resolution: "
1641 << frame_buffer_size_.ToString(); 1629 << frame_buffer_size_.ToString();
1642 1630
1643 if (!CreateOutputBuffers()) 1631 if (!CreateOutputBuffers())
1644 return false; 1632 return false;
1645 1633
1646 return true; 1634 return true;
1647 } 1635 }
1648 1636
1649 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() { 1637 bool V4L2VideoDecodeAccelerator::CreateInputBuffers() {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1726 // Output format setup in Initialize(). 1714 // Output format setup in Initialize().
1727 1715
1728 // Allocate the output buffers. 1716 // Allocate the output buffers.
1729 struct v4l2_requestbuffers reqbufs; 1717 struct v4l2_requestbuffers reqbufs;
1730 memset(&reqbufs, 0, sizeof(reqbufs)); 1718 memset(&reqbufs, 0, sizeof(reqbufs));
1731 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount; 1719 reqbufs.count = output_dpb_size_ + kDpbOutputBufferExtraCount;
1732 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 1720 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1733 reqbufs.memory = V4L2_MEMORY_MMAP; 1721 reqbufs.memory = V4L2_MEMORY_MMAP;
1734 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs); 1722 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
1735 1723
1736 // Create DMABUFs from output buffers.
1737 output_buffer_map_.resize(reqbufs.count); 1724 output_buffer_map_.resize(reqbufs.count);
1738 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1739 OutputRecord& output_record = output_buffer_map_[i];
1740 for (size_t j = 0; j < arraysize(output_record.fds); ++j) {
1741 // Export the DMABUF fd so we can export it as a texture.
1742 struct v4l2_exportbuffer expbuf;
1743 memset(&expbuf, 0, sizeof(expbuf));
1744 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1745 expbuf.index = i;
1746 expbuf.plane = j;
1747 expbuf.flags = O_CLOEXEC;
1748 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_EXPBUF, &expbuf);
1749 output_record.fds[j] = expbuf.fd;
1750 }
1751 }
1752 1725
1753 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): " 1726 DVLOG(3) << "CreateOutputBuffers(): ProvidePictureBuffers(): "
1754 << "buffer_count=" << output_buffer_map_.size() 1727 << "buffer_count=" << output_buffer_map_.size()
1755 << ", width=" << frame_buffer_size_.width() 1728 << ", width=" << frame_buffer_size_.width()
1756 << ", height=" << frame_buffer_size_.height(); 1729 << ", height=" << frame_buffer_size_.height();
1757 child_message_loop_proxy_->PostTask(FROM_HERE, 1730 child_message_loop_proxy_->PostTask(FROM_HERE,
1758 base::Bind(&Client::ProvidePictureBuffers, 1731 base::Bind(&Client::ProvidePictureBuffers,
1759 client_, 1732 client_,
1760 output_buffer_map_.size(), 1733 output_buffer_map_.size(),
1761 frame_buffer_size_, 1734 frame_buffer_size_,
1762 GL_TEXTURE_EXTERNAL_OES)); 1735 device_->GetTextureTarget()));
1763 1736
1764 // Wait for the client to call AssignPictureBuffers() on the Child thread. 1737 // Wait for the client to call AssignPictureBuffers() on the Child thread.
1765 // We do this, because if we continue decoding without finishing buffer 1738 // We do this, because if we continue decoding without finishing buffer
1766 // allocation, we may end up Resetting before AssignPictureBuffers arrives, 1739 // allocation, we may end up Resetting before AssignPictureBuffers arrives,
1767 // resulting in unnecessary complications and subtle bugs. 1740 // resulting in unnecessary complications and subtle bugs.
1768 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2) 1741 // For example, if the client calls Decode(Input1), Reset(), Decode(Input2)
1769 // in a sequence, and Decode(Input1) results in us getting here and exiting 1742 // in a sequence, and Decode(Input1) results in us getting here and exiting
1770 // without waiting, we might end up running Reset{,Done}Task() before 1743 // without waiting, we might end up running Reset{,Done}Task() before
1771 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers 1744 // AssignPictureBuffers is scheduled, thus cleaning up and pushing buffers
1772 // to the free_output_buffers_ map twice. If we somehow marked buffers as 1745 // to the free_output_buffers_ map twice. If we somehow marked buffers as
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1805 } 1778 }
1806 1779
1807 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() { 1780 bool V4L2VideoDecodeAccelerator::DestroyOutputBuffers() {
1808 DVLOG(3) << "DestroyOutputBuffers()"; 1781 DVLOG(3) << "DestroyOutputBuffers()";
1809 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); 1782 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread());
1810 DCHECK(!output_streamon_); 1783 DCHECK(!output_streamon_);
1811 bool success = true; 1784 bool success = true;
1812 1785
1813 for (size_t i = 0; i < output_buffer_map_.size(); ++i) { 1786 for (size_t i = 0; i < output_buffer_map_.size(); ++i) {
1814 OutputRecord& output_record = output_buffer_map_[i]; 1787 OutputRecord& output_record = output_buffer_map_[i];
1815 for (size_t j = 0; j < arraysize(output_record.fds); ++j) { 1788
1816 if (output_record.fds[j] != -1) {
1817 if (close(output_record.fds[j])) {
1818 DVPLOG(1) << __func__ << " close() on a dmabuf fd failed.";
1819 success = false;
1820 }
1821 }
1822 }
1823 if (output_record.egl_image != EGL_NO_IMAGE_KHR) { 1789 if (output_record.egl_image != EGL_NO_IMAGE_KHR) {
1824 if (eglDestroyImageKHR(egl_display_, output_record.egl_image) != 1790 if (device_->DestroyEGLImage(egl_display_, output_record.egl_image) !=
1825 EGL_TRUE) { 1791 EGL_TRUE) {
1826 DVLOG(1) << __func__ << " eglDestroyImageKHR failed."; 1792 DVLOG(1) << __func__ << " DestroyEGLImage failed.";
1827 success = false; 1793 success = false;
1828 } 1794 }
1829 } 1795 }
1830 1796
1831 if (output_record.egl_sync != EGL_NO_SYNC_KHR) { 1797 if (output_record.egl_sync != EGL_NO_SYNC_KHR) {
1832 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) { 1798 if (eglDestroySyncKHR(egl_display_, output_record.egl_sync) != EGL_TRUE) {
1833 DVLOG(1) << __func__ << " eglDestroySyncKHR failed."; 1799 DVLOG(1) << __func__ << " eglDestroySyncKHR failed.";
1834 success = false; 1800 success = false;
1835 } 1801 }
1836 } 1802 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1919 } 1885 }
1920 1886
1921 void V4L2VideoDecodeAccelerator::PictureCleared() { 1887 void V4L2VideoDecodeAccelerator::PictureCleared() {
1922 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_; 1888 DVLOG(3) << "PictureCleared(). clearing count=" << picture_clearing_count_;
1923 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current()); 1889 DCHECK_EQ(decoder_thread_.message_loop(), base::MessageLoop::current());
1924 DCHECK_GT(picture_clearing_count_, 0); 1890 DCHECK_GT(picture_clearing_count_, 0);
1925 picture_clearing_count_--; 1891 picture_clearing_count_--;
1926 SendPictureReady(); 1892 SendPictureReady();
1927 } 1893 }
1928 1894
1895 bool V4L2VideoDecodeAccelerator::IsResolutionChangeNecessary() {
1896 DVLOG(3) << "IsResolutionChangeNecessary() ";
1897
1898 struct v4l2_control ctrl;
1899 memset(&ctrl, 0, sizeof(ctrl));
1900 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
1901 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_G_CTRL, &ctrl);
1902 if (ctrl.value != output_dpb_size_) {
1903 DVLOG(3)
1904 << "IsResolutionChangeNecessary(): Returning true since DPB mismatch ";
1905 return true;
1906 }
1907 struct v4l2_format format;
1908 bool again = false;
1909 bool ret = GetFormatInfo(&format, &again);
1910 if (!ret || again) {
1911 DVLOG(3) << "IsResolutionChangeNecessary(): GetFormatInfo() failed";
1912 return false;
Ami GONE FROM CHROMIUM 2014/03/28 19:33:40 Response below makes sense to me for why you retur
shivdasp 2014/03/28 20:39:26 GetFormatInfo() on failure will call NOTIFY_PLATFO
1913 }
1914 gfx::Size new_size(base::checked_cast<int>(format.fmt.pix_mp.width),
1915 base::checked_cast<int>(format.fmt.pix_mp.height));
1916 if (frame_buffer_size_ != new_size) {
1917 DVLOG(3) << "IsResolutionChangeNecessary(): Resolution change detected";
1918 return true;
1919 }
1920 return false;
1921 }
1922
1929 } // namespace content 1923 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698