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

Side by Side Diff: content/common/gpu/media/tegra_v4l2_video_device.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, 10 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
(Empty)
1 #include <dlfcn.h>
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 missing copyright header
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <libdrm/drm_fourcc.h>
Pawel Osciak 2014/02/10 06:36:17 Not needed?
5 #include <linux/videodev2.h>
6 #include <poll.h>
Pawel Osciak 2014/02/10 06:36:17 Not needed.
7 #include <sys/eventfd.h>
Pawel Osciak 2014/02/10 06:36:17 Not needed.
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
Pawel Osciak 2014/02/10 06:36:17 Not needed? Please clean up the headers in this f
10
11 #include "base/bind.h"
12 #include "base/debug/trace_event.h"
13 #include "base/memory/shared_memory.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/posix/eintr_wrapper.h"
17 #include "content/common/gpu/media/tegra_v4l2_video_device.h"
18 #include "ui/gl/gl_bindings.h"
19
20 namespace content {
21
22 namespace {
23 const char kDevice[] = "/dev/video0";
Pawel Osciak 2014/02/10 06:36:17 Is this is the codec device exposed by Tegra kerne
shivdasp 2014/02/10 13:31:17 This is a v4l2 decoder device name which we use to
Pawel Osciak 2014/02/12 09:15:13 Which device is actually being used? Does the libr
shivdasp 2014/02/12 10:11:55 This library internally talks to MM layer which ta
Pawel Osciak 2014/02/13 10:42:54 This means you will have to add it to sandbox rule
shivdasp 2014/02/14 03:06:45 Yes /dev/tegra_avpchannel will be added in the san
Pawel Osciak 2014/02/14 07:36:10 Why it may not be required? How else would it be a
shivdasp 2014/02/14 09:18:58 Whitelisted will not be required because of pre-ac
24 }
25
26 TegraV4L2Device::TegraV4L2Device(EGLContext egl_context)
27 : device_fd_(-1), egl_context_(egl_context) {}
28
29 TegraV4L2Device::~TegraV4L2Device() {
30 if (device_fd_ != -1) {
31 TegraV4L2Close(device_fd_);
32 device_fd_ = -1;
33 }
34 }
35
36 int TegraV4L2Device::Ioctl(int flags, void* arg) {
37 return TegraV4L2Ioctl(device_fd_, flags, arg);
38 }
39
40 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) {
41 if (TegraV4L2Poll(device_fd_, poll_device, event_pending) == -1) {
42 DLOG(ERROR) << "TegraV4L2Poll returned -1 ";
43 return false;
44 }
45 return true;
46 }
47
48 void* TegraV4L2Device::Mmap(void* addr,
49 unsigned int len,
50 int prot,
51 int flags,
52 unsigned int offset) {
53 // No real mmap for tegrav4l2 device, the offset is itself the address.
54 return (void*)offset;
Pawel Osciak 2014/02/10 06:36:17 QUERYBUFS from V4L2VDA is used to acquire offsets
shivdasp 2014/02/10 13:31:17 When REQBUFS is called for OUTPUT_PLANE, the libra
Pawel Osciak 2014/02/12 09:15:13 The library must be using some kind of an mmap cal
shivdasp 2014/02/12 10:11:55 Okay I will add Mmap and Munmap calls to the libra
Pawel Osciak 2014/02/13 10:42:54 Great. Thank you!
55 }
56
57 void TegraV4L2Device::Munmap(void* addr, unsigned int len) {
58 // No real munmap for tegrav4l2 device.
Pawel Osciak 2014/02/10 06:36:17 If so, how is unmapping handled then? What if we w
shivdasp 2014/02/10 13:31:17 Buffers are unmapped in REQBUFS(0) call and destro
Pawel Osciak 2014/02/12 09:15:13 We should not rely on V4L2VDA to be the only place
shivdasp 2014/02/12 10:11:55 If not in REQBUFS(0) then what will be the appropr
Pawel Osciak 2014/02/13 10:42:54 Sorry, perhaps I wasn't clear, the term "buffers"
shivdasp 2014/02/14 03:06:45 Understood. I believe the dmabuf export mechanism
Pawel Osciak 2014/02/14 07:36:10 Yes, although it's not "synchronized", but the own
shivdasp 2014/02/14 09:18:58 I checked with the graphics team here. This is han
59 return;
60 }
61
62 bool TegraV4L2Device::SetDevicePollInterrupt(void) {
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 drop "void"
63 if (HANDLE_EINTR(TegraV4L2SetDevicePollInterrupt(device_fd_) == -1)) {
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 bug: HANDLE_EINTR should not be accepting the ==-1
64 DLOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt";
65 return false;
66 }
67 return true;
68 }
69
70 bool TegraV4L2Device::ClearDevicePollInterrupt(void) {
71 if (HANDLE_EINTR(TegraV4L2ClearDevicePollInterrupt(device_fd_) == -1)) {
72 DLOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt";
73 return false;
74 }
75 return true;
76 }
77
78 bool TegraV4L2Device::Initialize(void) {
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 drop "void"
79 TegraV4L2Open = reinterpret_cast<TegraV4L2OpenFunc>(
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 Please avoid the sort of code duplication below (s
shivdasp 2014/02/10 13:31:17 Yes I will do this. That looks very clean. On 2014
80 dlsym(RTLD_DEFAULT, "tegra_v4l2_open"));
81 if (TegraV4L2Open == NULL) {
82 DLOG(ERROR) << "Unable to get Tegra_v4l2_open handle ";
83 return false;
84 }
85
86 TegraV4L2Ioctl = reinterpret_cast<TegraV4L2IoctlFunc>(
87 dlsym(RTLD_DEFAULT, "tegra_v4l2_ioctl"));
88 if (TegraV4L2Ioctl == NULL) {
89 DLOG(ERROR) << "Unable to get tegra_v4l2_ioctl handle ";
90 return false;
91 }
92
93 TegraV4L2Close = reinterpret_cast<TegraV4L2CloseFunc>(
94 dlsym(RTLD_DEFAULT, "tegra_v4l2_close"));
95 if (TegraV4L2Close == NULL) {
96 DLOG(ERROR) << "Unable to get tegra_v4l2_close handle ";
97 return false;
98 }
99
100 TegraV4L2Poll = reinterpret_cast<TegraV4L2PollFunc>(
101 dlsym(RTLD_DEFAULT, "tegra_v4l2_poll"));
102 if (TegraV4L2Poll == NULL) {
103 DLOG(ERROR) << "Unable to get tegra_v4l2_poll handle ";
104 return false;
105 }
106
107 TegraV4L2SetDevicePollInterrupt =
108 reinterpret_cast<TegraV4L2SetDevicePollInterruptFunc>(
109 dlsym(RTLD_DEFAULT, "tegra_v4l2_set_device_poll_interrupt"));
110 if (TegraV4L2SetDevicePollInterrupt == NULL) {
111 DLOG(ERROR) << "Unable to get tegra_v4l2_set_device_poll_interrupt handle";
112 return false;
113 }
114
115 TegraV4L2ClearDevicePollInterrupt =
116 reinterpret_cast<TegraV4L2ClearDevicePollInterruptFunc>(
117 dlsym(RTLD_DEFAULT, "tegra_v4l2_clear_device_poll_interrupt"));
118 if (TegraV4L2ClearDevicePollInterrupt == NULL) {
119 DLOG(ERROR)
120 << "Unable to get tegra_v4l2_clear_device_poll_interrupt handle ";
121 return false;
122 }
123
124 device_fd_ =
125 HANDLE_EINTR(TegraV4L2Open(kDevice, O_RDWR | O_NONBLOCK | O_CLOEXEC));
126 if (device_fd_ == -1) {
127 DLOG(ERROR) << "Unable to open tegra_v4l2_open ";
128 return false;
129 }
130 return true;
131 }
132
133 EGLImageKHR TegraV4L2Device::CreateEGLImage(EGLDisplay egl_display,
134 EGLint attrib[],
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 EGLint[] /* attrib */
135 unsigned int texture_id,
136 unsigned int buffer_index) {
Pawel Osciak 2014/02/10 06:36:17 This method should take a v4l2_buffer instead. De
shivdasp 2014/02/10 13:31:17 Since ExynosV4L2Device does not need the v4l2_buff
137 // Ignore the attributes sent to us since Tegra does not need those.
138 EGLint attr = EGL_NONE;
139 EGLImageKHR egl_image = eglCreateImageKHR(egl_display,
140 egl_context_,
141 EGL_GL_TEXTURE_2D_KHR,
142 (EGLClientBuffer)(texture_id),
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 static_cast
143 &attr);
144 if (egl_image == EGL_NO_IMAGE_KHR) {
145 DLOG(ERROR) << "CreateEGLImage(): could not create EGLImageKHR";
146 return egl_image;
147 }
148
149 struct v4l2_plane planes[2];
150 struct v4l2_buffer capture_buffer;
151
152 memset(&capture_buffer, 0, sizeof(capture_buffer));
153 memset(planes, 0, sizeof(planes));
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 swap w/ previous line to match declaration order
154 capture_buffer.index = buffer_index;
155 capture_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
156 capture_buffer.memory = V4L2_MEMORY_MMAP;
157 capture_buffer.m.planes = planes;
158 capture_buffer.length = 2;
Pawel Osciak 2014/02/10 06:36:17 arraysize(planes)
159 // We send the EGLImage handle in mem_offset for the library to perform
160 // conversion internally
161
162 planes[0].m.mem_offset = reinterpret_cast<unsigned int>(egl_image);
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 how wide is mem_offset? I'm worried about this ca
Pawel Osciak 2014/02/10 06:36:17 mem_offset is u32 always, an unsigned int shouldn'
shivdasp 2014/02/10 13:31:17 We are really passing in the EglImage handle here
Pawel Osciak 2014/02/12 09:15:13 EGLImageKHR is typedef void*, which can be 64 bit.
shivdasp 2014/02/12 10:11:55 The output is YUV420 planar. I think rather than u
Pawel Osciak 2014/02/13 10:42:54 Are all planes non-interleaved and contiguous in m
shivdasp 2014/02/14 03:06:45 Okay I will change the pixel format. However there
Pawel Osciak 2014/02/14 07:36:10 As I said, those checks and should be fixed to use
shivdasp 2014/02/14 09:18:58 Okay will use the V4L2 API.
163 if (HANDLE_EINTR(Ioctl(VIDIOC_QUERYBUF, &capture_buffer)) != 0) {
164 DLOG(ERROR) << "Some error in querybuf";
165 return EGL_NO_IMAGE_KHR;
Ami GONE FROM CHROMIUM 2014/02/07 09:09:30 leak? (no eglDestroyImageKHR needed?)
shivdasp 2014/02/10 13:31:17 Yes will fix this. On 2014/02/07 09:09:30, Ami Fis
166 }
167 return egl_image;
168 }
Pawel Osciak 2014/02/10 06:36:17 After reading through it, this method feels unnece
shivdasp 2014/02/10 13:31:17 Since we started with implementing this as a V4L2-
Pawel Osciak 2014/02/12 09:15:13 Please understand that: 1. We are asking for a V4L
shivdasp 2014/02/12 10:11:55 There is no extension to create EglImages from dma
Pawel Osciak 2014/02/13 10:42:54 Could you explain why is it not affected? VEA call
shivdasp 2014/02/14 03:06:45 The fd returned by TegraV4L2Open() knows whether i
169
170 unsigned int TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; }
171
172 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698