00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "NvV4l2Element.h"
00030 #include "NvLogging.h"
00031
00032 #include <fcntl.h>
00033 #include <cstring>
00034 #include <errno.h>
00035 #include <libv4l2.h>
00036
00037 #define CAT_NAME "V4l2Element"
00038
00039 using namespace std;
00040
00041 NvV4l2Element::NvV4l2Element(const char *comp_name, const char *dev_node, int flags, NvElementProfiler::ProfilerField fields)
00042 :NvElement(comp_name, fields),
00043 output_plane(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, comp_name,
00044 fd, !(flags & O_NONBLOCK), profiler),
00045 capture_plane(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, comp_name,
00046 fd, !(flags & O_NONBLOCK), profiler)
00047 {
00048 struct v4l2_capability caps;
00049 int ret;
00050
00051 app_data = NULL;
00052 output_plane_pixfmt = 0;
00053 capture_plane_pixfmt = 0;
00054
00055 fd = v4l2_open(dev_node, flags | O_RDWR);
00056 if (fd == -1)
00057 {
00058 COMP_SYS_ERROR_MSG("Could not open device '" << dev_node << "'");
00059 is_in_error = 1;
00060 return;
00061 }
00062 COMP_DEBUG_MSG("Opened, fd = " << fd);
00063
00064 ret = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &caps);
00065 if (ret != 0)
00066 {
00067 COMP_SYS_ERROR_MSG("Error in VIDIOC_QUERYCAP");
00068 is_in_error = 1;
00069 return;
00070 }
00071 if (!(caps.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE))
00072 {
00073 COMP_ERROR_MSG("Device does not support V4L2_CAP_VIDEO_M2M_MPLANE");
00074 is_in_error = 1;
00075 return;
00076 }
00077 }
00078
00079 NvV4l2Element::~NvV4l2Element()
00080 {
00081 output_plane.deinitPlane();
00082 capture_plane.deinitPlane();
00083
00084 if (fd != -1)
00085 {
00086 v4l2_close(fd);
00087 CAT_DEBUG_MSG("Device closed, fd = " << fd);
00088 }
00089 }
00090
00091 int
00092 NvV4l2Element::dqEvent(struct v4l2_event &ev, uint32_t max_wait_ms)
00093 {
00094 int ret;
00095
00096 do
00097 {
00098 ret = v4l2_ioctl(fd, VIDIOC_DQEVENT, &ev);
00099
00100 if (ret == 0)
00101 {
00102 COMP_DEBUG_MSG("DQed event " << hex << ev.type << dec);
00103 }
00104 else if (errno != EAGAIN || max_wait_ms-- == 0)
00105 {
00106 COMP_SYS_ERROR_MSG("Error while DQing event");
00107 break;
00108 }
00109 else
00110 {
00111 usleep(1000);
00112 }
00113 }
00114 while (ret);
00115
00116 return ret;
00117 }
00118
00119 int
00120 NvV4l2Element::setControl(uint32_t id, int32_t value)
00121 {
00122 struct v4l2_control ctl;
00123 int ret;
00124
00125 ctl.id = id;
00126 ctl.value = value;
00127
00128 ret = v4l2_ioctl(fd, VIDIOC_S_CTRL, &ctl);
00129
00130 if (ret < 0)
00131 {
00132 COMP_SYS_ERROR_MSG("Error setting value " << value << " on control " <<
00133 id);
00134 }
00135 else
00136 {
00137 COMP_DEBUG_MSG("Set value " << value << " on control " << id);
00138 }
00139 return ret;
00140 }
00141
00142 int
00143 NvV4l2Element::getControl(uint32_t id, int32_t &value)
00144 {
00145 struct v4l2_control ctl;
00146 int ret;
00147
00148 ctl.id = id;
00149
00150 ret = v4l2_ioctl(fd, VIDIOC_G_CTRL, &ctl);
00151
00152 if (ret < 0)
00153 {
00154 COMP_SYS_ERROR_MSG("Error getting value of control " << id);
00155 }
00156 else
00157 {
00158 COMP_DEBUG_MSG("Got value " << ctl.value << " for control " << id);
00159 value = ctl.value;
00160 }
00161 return ret;
00162 }
00163
00164 int
00165 NvV4l2Element::setExtControls(v4l2_ext_controls &ctl)
00166 {
00167 int ret;
00168
00169 ret = v4l2_ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctl);
00170
00171 if (ret < 0)
00172 {
00173 COMP_SYS_ERROR_MSG("Error setting controls");
00174 }
00175 else
00176 {
00177 COMP_DEBUG_MSG("Set controls");
00178 }
00179 return ret;
00180 }
00181
00182 int
00183 NvV4l2Element::getExtControls(v4l2_ext_controls &ctl)
00184 {
00185 int ret;
00186
00187 ret = v4l2_ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctl);
00188
00189 if (ret < 0)
00190 {
00191 COMP_SYS_ERROR_MSG("Error getting value of controls");
00192 }
00193 else
00194 {
00195 COMP_DEBUG_MSG("Got controls");
00196 }
00197 return ret;
00198 }
00199
00200 int
00201 NvV4l2Element::subscribeEvent(uint32_t type, uint32_t id, uint32_t flags)
00202 {
00203 struct v4l2_event_subscription sub;
00204 int ret;
00205
00206 memset(&sub, 0, sizeof(struct v4l2_event_subscription));
00207
00208 sub.type = type;
00209 sub.id = id;
00210 sub.flags = flags;
00211
00212 ret = v4l2_ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
00213 if (ret == 0)
00214 {
00215 COMP_DEBUG_MSG("Successfully subscribed to event " << type);
00216 }
00217 else
00218 {
00219 COMP_SYS_ERROR_MSG
00220 ("Error while subscribing to event " << type);
00221 }
00222
00223 return ret;
00224 }
00225
00226 int
00227 NvV4l2Element::abort()
00228 {
00229 int ret = 0;
00230
00231 ret |= output_plane.setStreamStatus(false);
00232 ret |= capture_plane.setStreamStatus(false);
00233
00234 return ret;
00235 }
00236
00237 int
00238 NvV4l2Element::waitForIdle(uint32_t max_wait_ms)
00239 {
00240 COMP_ERROR_MSG("wait_for_idle not implemented");
00241 return 0;
00242 }
00243
00244 int
00245 NvV4l2Element::isInError()
00246 {
00247 int error = is_in_error;
00248 error |= capture_plane.isInError();
00249 error |= output_plane.isInError();
00250 return error;
00251 }
00252
00253 void
00254 NvV4l2Element::enableProfiling()
00255 {
00256 if (output_plane_pixfmt || capture_plane_pixfmt)
00257 {
00258 COMP_ERROR_MSG("Profiling must be enabled before setting formats on either plane");
00259 return;
00260 }
00261 profiler.enableProfiling(true);
00262 }