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 "NvVideoConverter.h"
00030 #include "NvLogging.h"
00031
00032 #include <cstring>
00033 #include <errno.h>
00034
00035 #define CONVERTER_DEV "/dev/nvhost-vic"
00036 #define CAT_NAME "NVVIDCONV"
00037
00038 #define CHECK_V4L2_RETURN(ret, str) \
00039 if (ret < 0) { \
00040 COMP_SYS_ERROR_MSG(str << ": failed"); \
00041 return -1; \
00042 } else { \
00043 COMP_DEBUG_MSG(str << ": success"); \
00044 return 0; \
00045 }
00046
00047 #define RETURN_ERROR_IF_FORMATS_SET() \
00048 if (output_plane_pixfmt != 0 || capture_plane_pixfmt != 0) { \
00049 COMP_ERROR_MSG("Should be called before setting plane formats") \
00050 return -1; \
00051 }
00052
00053 #define RETURN_ERROR_IF_BUFFERS_REQUESTED() \
00054 if (output_plane.getNumBuffers() != 0 && capture_plane.getNumBuffers() != 0) { \
00055 COMP_ERROR_MSG("Should be called before requesting buffers on either plane") \
00056 return -1; \
00057 }
00058
00059 #define RETURN_ERROR_IF_FORMATS_NOT_SET() \
00060 if (output_plane_pixfmt == 0 || capture_plane_pixfmt == 0) { \
00061 COMP_ERROR_MSG("Should be called after setting plane formats") \
00062 return -1; \
00063 }
00064
00065 using namespace std;
00066
00067 NvVideoConverter::NvVideoConverter(const char *name, int flags)
00068 :NvV4l2Element(name, CONVERTER_DEV, flags, valid_fields)
00069 {
00070 }
00071
00072 NvVideoConverter *
00073 NvVideoConverter::createVideoConverter(const char *name, int flags)
00074 {
00075 NvVideoConverter *conv = new NvVideoConverter(name, flags);
00076 if (conv->isInError())
00077 {
00078 delete conv;
00079 return NULL;
00080 }
00081 return conv;
00082 }
00083
00084 NvVideoConverter::~NvVideoConverter()
00085 {
00086 }
00087
00088 int
00089 NvVideoConverter::setCapturePlaneFormat(uint32_t pixfmt, uint32_t width,
00090 uint32_t height, enum v4l2_nv_buffer_layout type)
00091 {
00092 struct v4l2_format format;
00093 uint32_t num_bufferplanes;
00094 NvBuffer::NvBufferPlaneFormat planefmts[MAX_PLANES];
00095
00096 if (setCapturePlaneBufferLayout(type) < 0)
00097 {
00098 return -1;
00099 }
00100
00101 capture_plane_pixfmt = pixfmt;
00102 NvBuffer::fill_buffer_plane_format(&num_bufferplanes, planefmts, width,
00103 height, pixfmt);
00104 capture_plane.setBufferPlaneFormat(num_bufferplanes, planefmts);
00105
00106 memset(&format, 0, sizeof(struct v4l2_format));
00107 format.type = capture_plane.getBufType();
00108 format.fmt.pix_mp.width = width;
00109 format.fmt.pix_mp.height = height;
00110 format.fmt.pix_mp.pixelformat = pixfmt;
00111 format.fmt.pix_mp.num_planes = num_bufferplanes;
00112
00113 CHECK_V4L2_RETURN(capture_plane.setFormat(format),
00114 "Setting capture plane format");
00115 }
00116
00117 int
00118 NvVideoConverter::setOutputPlaneFormat(uint32_t pixfmt, uint32_t width,
00119 uint32_t height, enum v4l2_nv_buffer_layout type)
00120 {
00121 struct v4l2_format format;
00122 uint32_t num_bufferplanes;
00123 NvBuffer::NvBufferPlaneFormat planefmts[MAX_PLANES];
00124
00125 if (setOutputPlaneBufferLayout(type) < 0)
00126 {
00127 return -1;
00128 }
00129
00130 output_plane_pixfmt = pixfmt;
00131 NvBuffer::fill_buffer_plane_format(&num_bufferplanes, planefmts, width,
00132 height, pixfmt);
00133 output_plane.setBufferPlaneFormat(num_bufferplanes, planefmts);
00134
00135 memset(&format, 0, sizeof(struct v4l2_format));
00136 format.type = output_plane.getBufType();
00137 format.fmt.pix_mp.width = width;
00138 format.fmt.pix_mp.height = height;
00139 format.fmt.pix_mp.pixelformat = pixfmt;
00140 format.fmt.pix_mp.num_planes = num_bufferplanes;
00141
00142 CHECK_V4L2_RETURN(output_plane.setFormat(format),
00143 "Setting output plane format");
00144 }
00145
00146 int
00147 NvVideoConverter::waitForIdle(uint32_t max_wait_ms)
00148 {
00149 struct timespec timeToWait;
00150 struct timeval now;
00151 int return_val = 0;
00152 int ret;
00153
00154 gettimeofday(&now, NULL);
00155
00156 timeToWait.tv_nsec = (now.tv_usec + (max_wait_ms % 1000) * 1000L) * 1000L;
00157 timeToWait.tv_sec = now.tv_sec + max_wait_ms / 1000 +
00158 timeToWait.tv_nsec / 1000000000L;
00159 timeToWait.tv_nsec = timeToWait.tv_nsec % 1000000000L;
00160
00161 pthread_mutex_lock(&capture_plane.plane_lock);
00162 while (output_plane.getTotalQueuedBuffers() >
00163 capture_plane.getTotalDequeuedBuffers())
00164 {
00165 if (!capture_plane.getStreamStatus())
00166 {
00167 return_val = -2;
00168 break;
00169 }
00170 ret = pthread_cond_timedwait(&capture_plane.plane_cond,
00171 &capture_plane.plane_lock, &timeToWait);
00172 if (ret == ETIMEDOUT)
00173 {
00174 return_val = -1;
00175 break;
00176 }
00177 }
00178 pthread_mutex_unlock(&capture_plane.plane_lock);
00179
00180 return return_val;
00181 }
00182
00183 int
00184 NvVideoConverter::setOutputPlaneBufferLayout(enum v4l2_nv_buffer_layout type)
00185 {
00186 struct v4l2_ext_control ctl;
00187 struct v4l2_ext_controls controls;
00188
00189 RETURN_ERROR_IF_BUFFERS_REQUESTED();
00190
00191 memset(&ctl, 0, sizeof(ctl));
00192 memset(&controls, 0, sizeof(controls));
00193
00194 ctl.id = V4L2_CID_VIDEO_CONVERT_OUTPUT_PLANE_LAYOUT;
00195 ctl.value = (uint32_t) type;
00196 controls.controls = &ctl;
00197 controls.count = 1;
00198
00199 CHECK_V4L2_RETURN(setExtControls(controls),
00200 "Setting output plane buffer layout to " << type);
00201 }
00202
00203 int
00204 NvVideoConverter::setCapturePlaneBufferLayout(enum v4l2_nv_buffer_layout type)
00205 {
00206 struct v4l2_ext_control ctl;
00207 struct v4l2_ext_controls controls;
00208
00209 RETURN_ERROR_IF_BUFFERS_REQUESTED();
00210
00211 memset(&ctl, 0, sizeof(ctl));
00212 memset(&controls, 0, sizeof(controls));
00213
00214 ctl.id = V4L2_CID_VIDEO_CONVERT_CAPTURE_PLANE_LAYOUT;
00215 ctl.value = (uint32_t) type;
00216 controls.controls = &ctl;
00217 controls.count = 1;
00218
00219 CHECK_V4L2_RETURN(setExtControls(controls),
00220 "Setting capture plane buffer layout to " << type);
00221 }
00222
00223 int
00224 NvVideoConverter::setInterpolationMethod(enum v4l2_interpolation_method method)
00225 {
00226 struct v4l2_ext_control ctl;
00227 struct v4l2_ext_controls controls;
00228
00229 RETURN_ERROR_IF_BUFFERS_REQUESTED();
00230
00231 memset(&ctl, 0, sizeof(ctl));
00232 memset(&controls, 0, sizeof(controls));
00233
00234 ctl.id = V4L2_CID_VIDEO_CONVERT_INTERPOLATION_METHOD;
00235 ctl.value = (uint32_t) method;
00236 controls.controls = &ctl;
00237 controls.count = 1;
00238
00239 CHECK_V4L2_RETURN(setExtControls(controls),
00240 "Setting interpolation method to " << method);
00241 }
00242
00243 int
00244 NvVideoConverter::setFlipMethod(enum v4l2_flip_method method)
00245 {
00246 struct v4l2_ext_control ctl;
00247 struct v4l2_ext_controls controls;
00248
00249 RETURN_ERROR_IF_BUFFERS_REQUESTED();
00250
00251 memset(&ctl, 0, sizeof(ctl));
00252 memset(&controls, 0, sizeof(controls));
00253
00254 ctl.id = V4L2_CID_VIDEO_CONVERT_FLIP_METHOD;
00255 ctl.value = (uint32_t) method;
00256 controls.controls = &ctl;
00257 controls.count = 1;
00258
00259 CHECK_V4L2_RETURN(setExtControls(controls),
00260 "Setting flip method to " << method);
00261 }
00262
00263 int
00264 NvVideoConverter::setTnrAlgorithm(enum v4l2_tnr_algorithm algorithm)
00265 {
00266 struct v4l2_ext_control ctl;
00267 struct v4l2_ext_controls controls;
00268
00269 RETURN_ERROR_IF_BUFFERS_REQUESTED();
00270
00271 memset(&ctl, 0, sizeof(ctl));
00272 memset(&controls, 0, sizeof(controls));
00273
00274 ctl.id = V4L2_CID_VIDEO_CONVERT_TNR_ALGORITHM;
00275 ctl.value = (uint32_t) algorithm;
00276 controls.controls = &ctl;
00277 controls.count = 1;
00278
00279 CHECK_V4L2_RETURN(setExtControls(controls),
00280 "Setting TNR algorithm to " << algorithm);
00281 }
00282
00283 int
00284 NvVideoConverter::setCropRect(uint32_t left, uint32_t top, uint32_t width,
00285 uint32_t height)
00286 {
00287 struct v4l2_rect rect;
00288
00289 rect.left = left;
00290 rect.top = top;
00291 rect.width = width;
00292 rect.height = height;
00293
00294 CHECK_V4L2_RETURN(capture_plane.setSelection(V4L2_SEL_TGT_CROP, 0, rect),
00295 "Setting crop rectangle to left=" << left << ", top=" << top <<
00296 ", width=" << width << ", height=" << height);
00297 }