Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 | |
| OLD | NEW |