| 1 | {{{#!html |
| 2 | <div id="wikipage" class="trac-content"><p> |
| 3 | </p><div class="wiki-toc"> |
| 4 | <ol> |
| 5 | <li> |
| 6 | <a href="#LinuxVideo4Linux2APIv4l2">Linux Video4Linux2 API (v4l2)</a> |
| 7 | <ol> |
| 8 | <li> |
| 9 | <a href="#v4l2-ctlutility">v4l2-ctl utility</a> |
| 10 | <ol> |
| 11 | <li> |
| 12 | <a href="#videostandards">video standards</a> |
| 13 | </li> |
| 14 | <li> |
| 15 | <a href="#videoinputs">video inputs</a> |
| 16 | </li> |
| 17 | <li> |
| 18 | <a href="#pixelformatsframesizesandframerates">pixel formats, framesizes, and framerates</a> |
| 19 | </li> |
| 20 | <li> |
| 21 | <a href="#capturingvideoframes">capturing video frames</a> |
| 22 | </li> |
| 23 | </ol> |
| 24 | </li> |
| 25 | <li> |
| 26 | <a href="#v4l2applicationcode">v4l2 application code</a> |
| 27 | </li> |
| 28 | <li> |
| 29 | <a href="#IMX6Ventanamxc_v4l2_capturedriver">IMX6 Ventana mxc_v4l2_capture driver</a> |
| 30 | </li> |
| 31 | </ol> |
| 32 | </li> |
| 33 | </ol> |
| 34 | </div><p> |
| 35 | </p> |
| 36 | <h1 id="LinuxVideo4Linux2APIv4l2">Linux Video4Linux2 API (v4l2)</h1> |
| 37 | <p> |
| 38 | The Linux Video4Linux2 (v4l2) API is the kernel's video input and output interface. |
| 39 | </p> |
| 40 | <p> |
| 41 | <span class="wikianchor" id="v4l2-ctl"></span> |
| 42 | </p> |
| 43 | <h2 id="v4l2-ctlutility">v4l2-ctl utility</h2> |
| 44 | <p> |
| 45 | The <tt>v4l2-ctl</tt> userspace application can be used to query or configure a v4l2 device. For complete information, including output resolutions etc , use the following: |
| 46 | </p> |
| 47 | <div class="code"><pre>root@ventana:~# v4l2-ctl --device /dev/video3 --all <span class="c"># query all details about /dev/video3 |
| 48 | </span></pre></div><p> |
| 49 | See Also: |
| 50 | </p> |
| 51 | <ul><li><a class="wiki" href="/wiki/Yocto/gstreamer">GStreamer</a> |
| 52 | </li></ul><p> |
| 53 | <span class="wikianchor" id="standard"></span> |
| 54 | </p> |
| 55 | <h3 id="videostandards">video standards</h3> |
| 56 | <p> |
| 57 | Analog video v4l2 capture devices will support one or more of the various analog video standards used throughout the world. For example the ADV7180 supports NTSC, PAL, and SECAM standards. |
| 58 | </p> |
| 59 | <p> |
| 60 | You can use the Video4Linux API to determine if an input is detected and what mode by using the <tt>v4l2-ctl --get-standard</tt> command which reports one of the following: |
| 61 | </p> |
| 62 | <ul><li>No supported input detected - Video Standard = 0x00ffffff |
| 63 | </li><li>NTSC - Video Standard = 0x000000ff |
| 64 | </li><li>PAL - Video Standard = 0x000000ff |
| 65 | </li></ul><p> |
| 66 | Example: |
| 67 | </p> |
| 68 | <ul><li>Show Analog Video status on GW51xx/GW52xx/GW53xx (/dev/video0): |
| 69 | <div class="code"><pre>v4l2-ctl --device /dev/video0 --get-standard |
| 70 | </pre></div></li><li>Show Analog Video status on GW54xx (/dev/video1) |
| 71 | <div class="code"><pre>v4l2-ctl --device /devivideo0 --get-standard |
| 72 | </pre></div></li></ul><p> |
| 73 | <span class="wikianchor" id="input"></span> |
| 74 | </p> |
| 75 | <h3 id="videoinputs">video inputs</h3> |
| 76 | <p> |
| 77 | Some capture devices have multiple video inputs. The <tt>v4l2-ctl</tt> application can be used to get or set the current input. |
| 78 | </p> |
| 79 | <p> |
| 80 | Examples: |
| 81 | </p> |
| 82 | <ul><li>show current inputs that <tt>/dev/video3</tt> supports: |
| 83 | <div class="code"><pre>v4l2-ctl --device /dev/video3 --get-input |
| 84 | </pre></div></li><li>select input1: |
| 85 | <div class="code"><pre>v4l2-ctl --device /dev/video3 --set-input<span class="o">=</span>1 |
| 86 | </pre></div></li></ul><p> |
| 87 | <span class="wikianchor" id="format"></span> |
| 88 | </p> |
| 89 | <h3 id="pixelformatsframesizesandframerates">pixel formats, framesizes, and framerates</h3> |
| 90 | <p> |
| 91 | You can use <tt>v4l2-ctl</tt> to show what pixel formats a video device supports and select a desired format. Note that v4l2 devices support one or more pixel formats, and various resolutions and framerates for each format. You must ask what resolutions are supported for a particular format, and what framerates are supported for a particular resolution/format. |
| 92 | </p> |
| 93 | <p> |
| 94 | Examples: |
| 95 | </p> |
| 96 | <ul><li>show formats that <tt>/dev/video3</tt> supports: |
| 97 | <div class="code"><pre>v4l2-ctl --device /dev/video3 --list-formats-ext |
| 98 | </pre></div></li><li>show what resolutions <tt>/dev/video3</tt> supports for the UYVY pixel format: |
| 99 | <div class="code"><pre>v4l2-ctl --device /dev/video3 --list-framesizes<span class="o">=</span>UYVY |
| 100 | </pre></div></li><li>show what framerates <tt>/dev/video3</tt> supports for UYVY at 640x480: |
| 101 | <div class="code"><pre>v4l2-ctl --device /dev/video3 --list-frameintervals<span class="o">=</span><span class="nv">width</span><span class="o">=</span>640,height<span class="o">=</span>480,pixelformat<span class="o">=</span>UYVY |
| 102 | </pre></div></li><li>set format for <tt>/dev/video0</tt> to 1280x720 UYVY: |
| 103 | <div class="code"><pre>v4l2-ctl --device /dev/video0 --set-fmt-video<span class="o">=</span><span class="nv">width</span><span class="o">=</span>1280,height<span class="o">=</span>720,pixelformat<span class="o">=</span>UYVY |
| 104 | </pre></div></li></ul><p> |
| 105 | It is not uncommon for a v4l2 driver to not properly support the enumeration of various formats, resolutions, and framerates. If you find that a device is not returning anything useful for <tt>--list-formats</tt> <tt>--list-formats-ext</tt> <tt>--list-framesizes</tt> <tt>--list-framerates</tt> then you can try <tt>--all</tt> to get the default configuration of the device. |
| 106 | </p> |
| 107 | <p> |
| 108 | Examples: |
| 109 | </p> |
| 110 | <ul><li>the TDA1997x HDMI receiver on a GW54xx |
| 111 | <div class="code"><pre>root@ventana:~# v4l2-ctl --device /dev/video0 --all |
| 112 | Driver Info <span class="o">(</span>not using libv4l2<span class="o">)</span>: |
| 113 | Driver name : mxc_v4l2 |
| 114 | Card <span class="nb">type</span> : |
| 115 | Bus info : |
| 116 | Driver version: 0.1.11 |
| 117 | Capabilities : 0x05000005 |
| 118 | Video Capture |
| 119 | Video Overlay |
| 120 | Read/Write |
| 121 | Streaming |
| 122 | Video input : 0 <span class="o">(</span>CSI IC MEM: ok<span class="o">)</span> |
| 123 | Video output: 0 <span class="o">(</span>DISP3 BG<span class="o">)</span> |
| 124 | Video <span class="nv">Standard</span> <span class="o">=</span> 0x00000000 |
| 125 | Format Video Capture: |
| 126 | Width/Height : 288/352 |
| 127 | Pixel Format : <span class="s1">'UYVY'</span> |
| 128 | Field : Any |
| 129 | Bytes per Line: 432 |
| 130 | Size Image : 152064 |
| 131 | Colorspace : Unknown <span class="o">(</span>00000000<span class="o">)</span> |
| 132 | Format Video Overlay: |
| 133 | Left/Top : 0/0 |
| 134 | Width/Height: 160/160 |
| 135 | Field : Any |
| 136 | Chroma Key : 0x00000000 |
| 137 | Global Alpha: 0x00 |
| 138 | Clip Count : 0 |
| 139 | Clip Bitmap : No |
| 140 | Framebuffer Format: |
| 141 | Capability : Extern Overlay |
| 142 | Flags : Overlay Matches Capture/Output Size |
| 143 | Width : 0 |
| 144 | Height : 0 |
| 145 | Pixel Format : <span class="s1">''</span> |
| 146 | Crop Capability Video Capture: |
| 147 | Bounds : Left 0, Top 0, Width 1920, Height 1080 |
| 148 | Default : Left 0, Top 0, Width 1920, Height 1080 |
| 149 | Pixel Aspect: 0/0 |
| 150 | Crop: Left 0, Top 0, Width 1920, Height 1080 |
| 151 | Streaming Parameters Video Capture: |
| 152 | Frames per second: 60.000 <span class="o">(</span>60/1<span class="o">)</span> |
| 153 | Read buffers : 0 |
| 154 | Streaming Parameters Video Output: |
| 155 | Frames per second: invalid <span class="o">(</span>0/0<span class="o">)</span> |
| 156 | Write buffers : 0 |
| 157 | |
| 158 | </pre></div><ul><li>Note that the width/height does not reflect the resolution of the current video input source. In the above case a 1080p@60Hz input is attached. You can determine the source resolution via the crop parameters. |
| 159 | </li></ul></li><li>the ADV7180 Analog Video Decoder on a GW5400: |
| 160 | <div class="code"><pre>root@ventana:~# v4l2-ctl --device /dev/video1 --all |
| 161 | Driver Info <span class="o">(</span>not using libv4l2<span class="o">)</span>:<span class="o">[</span> 1863.994275<span class="o">]</span> ERROR: unrecognized std! ffffff <span class="o">(</span><span class="nv">PAL</span><span class="o">=</span>ff, <span class="nv">NTSC</span><span class="o">=</span>b000 |
| 162 | |
| 163 | Driver name : mxc_v4l2 |
| 164 | Card <span class="nb">type</span> : |
| 165 | Bus info : |
| 166 | Driver version: 0.1.11 |
| 167 | Capabilities : 0x05000005 |
| 168 | Video Capture |
| 169 | Video Overlay |
| 170 | Read/Write |
| 171 | Streaming |
| 172 | Video input : 0 <span class="o">(</span>CSI IC MEM: ok<span class="o">)</span> |
| 173 | Video output: 0 <span class="o">(</span>DISP3 BG<span class="o">)</span> |
| 174 | Video <span class="nv">Standard</span> <span class="o">=</span> 0x00ffffff |
| 175 | PAL-B/B1/G/H/I/D/D1/K/M/N/Nc/60 |
| 176 | NTSC-M/M-JP/443/M-KR |
| 177 | SECAM-B/D/G/H/K/K1/L/Lc |
| 178 | Format Video Capture: |
| 179 | Width/Height : 288/352 |
| 180 | Pixel Format : <span class="s1">'YU12'</span> |
| 181 | Field : Any |
| 182 | Bytes per Line: 432 |
| 183 | Size Image : 152064 |
| 184 | Colorspace : Unknown <span class="o">(</span>00000000<span class="o">)</span> |
| 185 | Format Video Overlay: |
| 186 | Left/Top : 0/0 |
| 187 | Width/Height: 160/160 |
| 188 | Field : Any |
| 189 | Chroma Key : 0x00000000 |
| 190 | Global Alpha: 0x00 |
| 191 | Clip Count : 0 |
| 192 | Clip Bitmap : No |
| 193 | Framebuffer Format: |
| 194 | Capability : Extern Overlay |
| 195 | Flags : Overlay Matches Capture/Output Size |
| 196 | Width : 0 |
| 197 | Height : 0 |
| 198 | Pixel Format : <span class="s1">''</span> |
| 199 | Crop Capability Video Capture: |
| 200 | Bounds : Left 0, Top 0, Width 720, Height 625 |
| 201 | Default : Left 0, Top 0, Width 720, Height 625 |
| 202 | Pixel Aspect: 0/0 |
| 203 | Crop: Left 0, Top 0, Width 720, Height 576 |
| 204 | Streaming Parameters Video Capture: |
| 205 | Frames per second: 30.000 <span class="o">(</span>30/1<span class="o">)</span> |
| 206 | Read buffers : 0 |
| 207 | Streaming Parameters Video Output: |
| 208 | Frames per second: invalid <span class="o">(</span>0/0<span class="o">)</span> |
| 209 | Write buffers : 0 |
| 210 | </pre></div></li></ul><p> |
| 211 | <span class="wikianchor" id="capture"></span> |
| 212 | </p> |
| 213 | <h3 id="capturingvideoframes">capturing video frames</h3> |
| 214 | <p> |
| 215 | You can use <tt>v4l2-ctl</tt> to capture frames as well. |
| 216 | </p> |
| 217 | <p> |
| 218 | Examples: |
| 219 | </p> |
| 220 | <ul><li>capture a single raw frame using mmap method: |
| 221 | <div class="code"><pre>v4l2-ctl --device /dev/video0 --stream-mmap --stream-to<span class="o">=</span>frame.raw --stream-count<span class="o">=</span>1 |
| 222 | </pre></div></li></ul><p> |
| 223 | Note that the <tt>convert</tt> tool from the <a class="ext-link" href="http://www.imagemagick.org/"><span class="icon"></span>ImageMagick</a> package is useful for image format conversions as long as you know the specific details of the raw image. |
| 224 | </p> |
| 225 | <p> |
| 226 | Examples: |
| 227 | </p> |
| 228 | <ul><li>convert a raw 640x480 16bit UYVY to png: |
| 229 | <div class="code"><pre>convert -size 640x480 -depth 16 uyvy:frame.raw frame.png |
| 230 | </pre></div></li></ul><p> |
| 231 | For an example v4l2 application for capturing frames see <a class="ext-link" href="https://linuxtv.org/downloads/v4l-dvb-apis/capture-example.html"><span class="icon"></span>here</a> |
| 232 | </p> |
| 233 | <p> |
| 234 | For capturing video we recommend using more full-featured applications such as <a class="wiki" href="/wiki/Yocto/gstreamer">GStreamer</a> |
| 235 | </p> |
| 236 | <p> |
| 237 | <span class="wikianchor" id="code"></span> |
| 238 | </p> |
| 239 | <h2 id="v4l2applicationcode">v4l2 application code</h2> |
| 240 | <p> |
| 241 | If you are coding an application that uses the v4l2 API the best examples are the v4l2-util application. You can find its source at <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/"><span class="icon"></span>https://git.linuxtv.org/v4l-utils.git/tree/</a> |
| 242 | </p> |
| 243 | <p> |
| 244 | The API documentation can be found at: |
| 245 | </p> |
| 246 | <ul><li><a class="ext-link" href="http://www.linuxtv.org/downloads/v4l-dvb-apis/"><span class="icon"></span>http://www.linuxtv.org/downloads/v4l-dvb-apis/</a> |
| 247 | <ul><li>Note that there are many references online to what is considered the 'legacy' API used prior to the 3.0 kernel. Be sure to use the documentation above for the current version of the v4l2 API. |
| 248 | </li></ul></li></ul><p> |
| 249 | Examples: |
| 250 | </p> |
| 251 | <ul><li>get/set/list video standard - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-stds.cpp"><span class="icon"></span>v4l2-ctl-stds.cpp</a> |
| 252 | </li><li>get/set/list video input - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-io.cpp"><span class="icon"></span>v4l2-ctl-io.cpp</a> |
| 253 | </li><li>get/set/list video pixel format - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp"><span class="icon"></span>v4l2-ctl-vidcap.cpp</a> |
| 254 | </li><li>get/set/list video framesizes - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp"><span class="icon"></span>v4l2-ctl-vidcap.cpp</a> |
| 255 | </li><li>get/set/list video framerates - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp"><span class="icon"></span>v4l2-ctl-vidcap.cpp</a> |
| 256 | </li><li>video capture - <a class="ext-link" href="https://git.linuxtv.org/v4l-utils.git/tree/utils/v4l2-ctl/v4l2-ctl-streaming.cpp"><span class="icon"></span>v4l2-ctl-streaming.cpp</a> |
| 257 | </li></ul><p> |
| 258 | As a rule of thumb it is best to configure all aspects of a device within your code to eliminate any dependence on the initial state of a video device and/or requiring configuring a device outside of your application with something like <tt>v4l2-ctl</tt>. For completeness set the following: |
| 259 | </p> |
| 260 | <ul><li>input (VIDIOC_S_INPUT) |
| 261 | </li><li>standard (VIDIOC_S_STD) |
| 262 | </li><li>format (VIDIOC_S_FMT) including width, height, pixel format, fields |
| 263 | </li><li>framerate (VIDIOC_S_PARM) |
| 264 | </li></ul><p> |
| 265 | Be aware that the <tt>ioctl</tt> syscall can return a -1 result with errno = EINTR to indicate the syscall was interrupted in which case it should be tried again. Because of this you should consider providing a wrapper for ioctl such as: |
| 266 | </p> |
| 267 | <div class="code"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">xioctl</span><span class="p">(</span><span class="kt">int</span> fh<span class="p">,</span> <span class="kt">int</span> request<span class="p">,</span> <span class="kt">void</span> <span class="o">*</span>arg<span class="p">)</span> |
| 268 | <span class="p">{</span> |
| 269 | <span class="kt">int</span> r<span class="p">;</span> |
| 270 | |
| 271 | <span class="k">do</span> <span class="p">{</span> |
| 272 | r <span class="o">=</span> ioctl<span class="p">(</span>fh<span class="p">,</span> request<span class="p">,</span> arg<span class="p">);</span> |
| 273 | <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> r <span class="o">&&</span> EINTR <span class="o">==</span> errno<span class="p">);</span> |
| 274 | |
| 275 | <span class="k">return</span> r<span class="p">;</span> |
| 276 | <span class="p">}</span> |
| 277 | </pre></div><p> |
| 278 | <span class="wikianchor" id="ventana"></span> |
| 279 | </p> |
| 280 | <h2 id="IMX6Ventanamxc_v4l2_capturedriver">IMX6 Ventana mxc_v4l2_capture driver</h2> |
| 281 | <p> |
| 282 | The Ventana product family based on the Freescale IMX6 System On Chip (SoC) has a Freescale provided capture driver (mxc_v4l2_capture) that is present in the Gateworks downstream vendor kernel used for the Yocto BSP. |
| 283 | </p> |
| 284 | <p> |
| 285 | This capture device driver implements two video inputs which represent different pipelines in the SoC: |
| 286 | </p> |
| 287 | <ul><li>input0 (default) - CSI -> IC -> MEM: useful if you want to perform image manipulation using the IMX6 hardware blocks |
| 288 | </li><li>input1 - CSI -> MEM: raw image capture |
| 289 | </li></ul><p> |
| 290 | If capturing frames be sure to skip the first frame as the CSI has not fully synchronized on its capture input. |
| 291 | </p> |
| 292 | <p> |
| 293 | To demonstrate a capture of a raw frame you can use the <tt>v4l2_ctl</tt> application: |
| 294 | </p> |
| 295 | <div class="code"><pre><span class="c"># configure input 1 for CSI -> MEM (raw image capture) |
| 296 | </span>v4l2-ctl --device /dev/video0 --set-input<span class="o">=</span>1 |
| 297 | <span class="c"># configure format |
| 298 | </span>v4l2-ctl --device /dev/video0 --set-fmt-video<span class="o">=</span><span class="nv">width</span><span class="o">=</span>1920,height<span class="o">=</span>1080,pixelformat<span class="o">=</span>UYVY |
| 299 | <span class="c"># capture 2nd frame |
| 300 | </span>v4l2-ctl --device /dev/video0 --stream-mmap --stream-skip<span class="o">=</span>1 --stream-to<span class="o">=</span>frame.raw --stream-count<span class="o">=</span>1 |
| 301 | <span class="c"># Use ImageMagick to convert it from raw 16-bit UYVY to PNG |
| 302 | </span>convert -size 1920x1080 -depth 16 uyvy:frame.raw frame.png |
| 303 | </pre></div><p> |
| 304 | Notes: |
| 305 | </p> |
| 306 | <ul><li>The mxc_v4l2_capture driver does not support the enumeration ioctls necessary to query device capabilities (VIDIOC_ENUM_FMT, VIDIOC_ENUM_FRAMESIZES, VIDIOC_ENUM_FRAMEINTERVALS). The following format details show what is supported: |
| 307 | <ul><li>HDMI In via tda1997x (GW54xx/GW551x): V4L2_PIX_FMT_UYVY non-interlaced frames (even when using the yuv422bt656 capture mode the bt656 is converted to non-interlaced frames by the IMX IC) with a resolution, framerate and colorspace dictated by the HDMI source. |
| 308 | </li><li>CVBS In via adv7180: V4L2_PIX_FMT_UYVY non-interlaced frames (bt656 output is converted to non-interlaced frames by the IMX IC) with a resolution of either 720x480 (NTSC) or 720x576 (PAL) depending on the input source |
| 309 | </li></ul></li></ul><p> |
| 310 | Code Example: |
| 311 | </p> |
| 312 | <ul><li>This example code will capture raw frames from the onboard video capture devices on the Ventana boards using the IMX6 CSI. It shows how to save the raw frame, process pixels (by counting the number of red pixels in the image), and convert it to a png via imagemagick |
| 313 | <div class="code"><pre><span class="cm">/* |
| 314 | * V4L2 video capture example |
| 315 | * |
| 316 | * This program can be used and distributed without restrictions. |
| 317 | * |
| 318 | * This program is provided with the V4L2 API |
| 319 | * see http://linuxtv.org/docs.php for more information |
| 320 | */</span> |
| 321 | <span class="cp"> |
| 322 | #include <byteswap.h> |
| 323 | #include <stdio.h> |
| 324 | #include <stdlib.h> |
| 325 | #include <stdint.h> |
| 326 | #include <string.h> |
| 327 | #include <assert.h> |
| 328 | #include <fcntl.h> </span><span class="cm">/* low-level i/o */</span><span class="cp"> |
| 329 | #include <unistd.h> |
| 330 | #include <errno.h> |
| 331 | #include <sys/types.h> |
| 332 | #include <sys/mman.h> |
| 333 | #include <sys/ioctl.h> |
| 334 | |
| 335 | #include <linux/videodev2.h> |
| 336 | |
| 337 | #define CLEAR(x) memset(&(x), 0, sizeof(x)) |
| 338 | </span> |
| 339 | <span class="k">struct</span> buffer <span class="p">{</span> |
| 340 | <span class="kt">void</span> <span class="o">*</span>start<span class="p">;</span> |
| 341 | <span class="kt">size_t</span> length<span class="p">;</span> |
| 342 | <span class="p">};</span> |
| 343 | |
| 344 | <span class="k">static</span> <span class="kt">void</span> <span class="nf">errno_exit</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span>s<span class="p">)</span> |
| 345 | <span class="p">{</span> |
| 346 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"%s error %d, %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> s<span class="p">,</span> errno<span class="p">,</span> strerror<span class="p">(</span>errno<span class="p">));</span> |
| 347 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 348 | <span class="p">}</span> |
| 349 | |
| 350 | <span class="k">static</span> <span class="kt">int</span> <span class="nf">xioctl</span><span class="p">(</span><span class="kt">int</span> fh<span class="p">,</span> <span class="kt">int</span> request<span class="p">,</span> <span class="kt">void</span> <span class="o">*</span>arg<span class="p">)</span> |
| 351 | <span class="p">{</span> |
| 352 | <span class="kt">int</span> r<span class="p">;</span> |
| 353 | |
| 354 | <span class="k">do</span> <span class="p">{</span> |
| 355 | r <span class="o">=</span> ioctl<span class="p">(</span>fh<span class="p">,</span> request<span class="p">,</span> arg<span class="p">);</span> |
| 356 | <span class="p">}</span> <span class="k">while</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> r <span class="o">&&</span> EINTR <span class="o">==</span> errno<span class="p">);</span> |
| 357 | |
| 358 | <span class="k">return</span> r<span class="p">;</span> |
| 359 | <span class="p">}</span> |
| 360 | |
| 361 | <span class="cm">/* 16bit/pixel interleaved YUV */</span> |
| 362 | <span class="k">static</span> <span class="kt">void</span> <span class="nf">process_image</span><span class="p">(</span><span class="k">const</span> <span class="kt">void</span> <span class="o">*</span>_p<span class="p">,</span> <span class="k">struct</span> v4l2_pix_format <span class="o">*</span>fmt<span class="p">)</span> |
| 363 | <span class="p">{</span> |
| 364 | <span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span>p <span class="o">=</span> _p<span class="p">;</span> |
| 365 | <span class="kt">int8_t</span> u<span class="p">;</span> |
| 366 | <span class="kt">uint8_t</span> y1<span class="p">;</span> |
| 367 | <span class="kt">int8_t</span> v<span class="p">;</span> |
| 368 | <span class="kt">uint8_t</span> y2<span class="p">;</span> |
| 369 | <span class="kt">int</span> r<span class="p">,</span> g<span class="p">,</span> b<span class="p">,</span> c<span class="p">,</span> d <span class="p">,</span>e<span class="p">;</span> |
| 370 | <span class="kt">int</span> red<span class="p">,</span> i<span class="p">,</span> x<span class="p">,</span> y<span class="p">;</span> |
| 371 | <span class="kt">int</span> size <span class="o">=</span> fmt<span class="o">-></span>sizeimage<span class="p">;</span> |
| 372 | |
| 373 | printf<span class="p">(</span><span class="s">"Processing Frame: %dx%d %c%c%c%c</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 374 | fmt<span class="o">-></span>width<span class="p">,</span> fmt<span class="o">-></span>height<span class="p">,</span> |
| 375 | <span class="p">(</span>fmt<span class="o">-></span>pixelformat <span class="o">>></span> <span class="mi">0</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 376 | <span class="p">(</span>fmt<span class="o">-></span>pixelformat <span class="o">>></span> <span class="mi">8</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 377 | <span class="p">(</span>fmt<span class="o">-></span>pixelformat <span class="o">>></span> <span class="mi">16</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 378 | <span class="p">(</span>fmt<span class="o">-></span>pixelformat <span class="o">>></span> <span class="mi">24</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">);</span> |
| 379 | |
| 380 | red <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> |
| 381 | <span class="k">for</span> <span class="p">(</span>i <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> i <span class="o"><</span> size<span class="p">;</span> i <span class="o">+=</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span> |
| 382 | u <span class="o">=</span> p<span class="p">[</span>i<span class="o">+</span><span class="mi">0</span><span class="p">];</span> |
| 383 | y1 <span class="o">=</span> p<span class="p">[</span>i<span class="o">+</span><span class="mi">1</span><span class="p">];</span> |
| 384 | v <span class="o">=</span> p<span class="p">[</span>i<span class="o">+</span><span class="mi">2</span><span class="p">];</span> |
| 385 | y2 <span class="o">=</span> p<span class="p">[</span>i<span class="o">+</span><span class="mi">3</span><span class="p">];</span> |
| 386 | |
| 387 | u <span class="o">-=</span> <span class="mi">128</span><span class="p">;</span> |
| 388 | v <span class="o">-=</span> <span class="mi">128</span><span class="p">;</span> |
| 389 | |
| 390 | r <span class="o">=</span> y1 <span class="o">+</span> v <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">5</span><span class="p">);</span> |
| 391 | g <span class="o">=</span> y1 <span class="o">-</span> <span class="p">((</span>u<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">5</span><span class="p">))</span> |
| 392 | <span class="o">-</span> <span class="p">((</span>v<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">5</span><span class="p">));</span> |
| 393 | b <span class="o">=</span> y1 <span class="o">+</span> u <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">6</span><span class="p">);</span> |
| 394 | <span class="k">if</span> <span class="p">(</span>r <span class="o">></span> <span class="mi">100</span> <span class="o">&&</span> g <span class="o"><</span> <span class="mi">60</span> <span class="o">&&</span> b <span class="o"><</span> <span class="mi">60</span><span class="p">)</span> red<span class="o">++</span><span class="p">;</span> |
| 395 | |
| 396 | r <span class="o">=</span> y2 <span class="o">+</span> v <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">5</span><span class="p">);</span> |
| 397 | g <span class="o">=</span> y2 <span class="o">-</span> <span class="p">((</span>u<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">5</span><span class="p">))</span> |
| 398 | <span class="o">-</span> <span class="p">((</span>v<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">4</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>v<span class="o">>></span><span class="mi">5</span><span class="p">));</span> |
| 399 | b <span class="o">=</span> y2 <span class="o">+</span> u <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span>u<span class="o">>></span><span class="mi">6</span><span class="p">);</span> |
| 400 | <span class="k">if</span> <span class="p">(</span>r <span class="o">></span> <span class="mi">100</span> <span class="o">&&</span> g <span class="o"><</span> <span class="mi">60</span> <span class="o">&&</span> b <span class="o"><</span> <span class="mi">60</span><span class="p">)</span> red<span class="o">++</span><span class="p">;</span> |
| 401 | |
| 402 | <span class="cm">/* describe pixels on first line every 250 pixels |
| 403 | * (colorbars) |
| 404 | */</span> |
| 405 | x <span class="o">=</span> <span class="p">(</span>i<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">%</span> fmt<span class="o">-></span>width<span class="p">;</span> |
| 406 | y <span class="o">=</span> <span class="p">(</span>i<span class="o">>></span><span class="mi">1</span><span class="p">)</span> <span class="o">/</span> fmt<span class="o">-></span>height<span class="p">;</span> |
| 407 | <span class="k">if</span> <span class="p">(</span>y <span class="o">==</span> <span class="mi">0</span> <span class="o">&&</span> <span class="o">!</span><span class="p">(</span>x <span class="o">%</span> <span class="mi">250</span><span class="p">))</span> <span class="p">{</span> |
| 408 | printf<span class="p">(</span><span class="s">"[%4d,%4d] YUYV:0x%02x%02x%02x%02x "</span><span class="p">,</span> |
| 409 | x<span class="p">,</span>y<span class="p">,</span>y1<span class="p">,(</span><span class="kt">uint8_t</span><span class="p">)</span>u<span class="p">,</span>y2<span class="p">,(</span><span class="kt">uint8_t</span><span class="p">)</span>v<span class="p">);</span> |
| 410 | printf<span class="p">(</span><span class="s">"RGB:0x%02x%02x%02x</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> r<span class="p">,</span>g<span class="p">,</span>b<span class="p">);</span> |
| 411 | <span class="p">}</span> |
| 412 | <span class="p">}</span> |
| 413 | printf<span class="p">(</span><span class="s">"red pixel count=%d</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> red<span class="p">);</span> |
| 414 | <span class="p">}</span> |
| 415 | |
| 416 | <span class="k">static</span> <span class="kt">void</span> <span class="nf">save_frame</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span>path<span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span>p<span class="p">,</span> <span class="kt">int</span> size<span class="p">)</span> |
| 417 | <span class="p">{</span> |
| 418 | <span class="kt">int</span> fd<span class="p">,</span> rz<span class="p">;</span> |
| 419 | |
| 420 | fd <span class="o">=</span> open<span class="p">(</span>path<span class="p">,</span> O_WRONLY <span class="o">|</span> O_CREAT <span class="o">|</span> O_TRUNC<span class="p">,</span> <span class="mo">0755</span><span class="p">);</span> |
| 421 | <span class="k">if</span> <span class="p">(</span>fd <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> |
| 422 | perror<span class="p">(</span><span class="s">"open"</span><span class="p">);</span> |
| 423 | <span class="k">else</span> <span class="p">{</span> |
| 424 | rz <span class="o">=</span> write<span class="p">(</span>fd<span class="p">,</span> p<span class="p">,</span> size<span class="p">);</span> |
| 425 | printf<span class="p">(</span><span class="s">"Wrote %d of %d bytes to %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> rz<span class="p">,</span> size<span class="p">,</span> path<span class="p">);</span> |
| 426 | close<span class="p">(</span>fd<span class="p">);</span> |
| 427 | <span class="p">}</span> |
| 428 | <span class="p">}</span> |
| 429 | |
| 430 | <span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> argc<span class="p">,</span> <span class="kt">char</span> <span class="o">**</span>argv<span class="p">)</span> |
| 431 | <span class="p">{</span> |
| 432 | <span class="k">static</span> <span class="kt">char</span> <span class="o">*</span>dev_name<span class="p">;</span> |
| 433 | <span class="kt">int</span> width<span class="p">,</span> height<span class="p">;</span> |
| 434 | <span class="k">static</span> <span class="kt">int</span> fd <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span> |
| 435 | <span class="k">struct</span> stat st<span class="p">;</span> |
| 436 | <span class="k">struct</span> buffer <span class="o">*</span>buffers<span class="p">;</span> |
| 437 | <span class="k">static</span> <span class="kt">unsigned</span> <span class="kt">int</span> n_buffers<span class="p">;</span> |
| 438 | <span class="k">enum</span> v4l2_buf_type type<span class="p">;</span> |
| 439 | <span class="k">struct</span> v4l2_capability cap<span class="p">;</span> |
| 440 | <span class="k">struct</span> v4l2_format fmt<span class="p">;</span> |
| 441 | <span class="k">struct</span> v4l2_requestbuffers req<span class="p">;</span> |
| 442 | <span class="k">struct</span> v4l2_streamparm parm<span class="p">;</span> |
| 443 | <span class="k">struct</span> v4l2_input input<span class="p">;</span> |
| 444 | v4l2_std_id std_id<span class="p">;</span> |
| 445 | <span class="k">struct</span> v4l2_buffer buf<span class="p">;</span> |
| 446 | <span class="kt">unsigned</span> <span class="kt">int</span> count<span class="p">;</span> |
| 447 | <span class="kt">unsigned</span> <span class="kt">int</span> i<span class="p">;</span> |
| 448 | <span class="kt">char</span> filename<span class="p">[</span><span class="mi">32</span><span class="p">];</span> |
| 449 | |
| 450 | <span class="cm">/* parse args */</span> |
| 451 | <span class="k">if</span> <span class="p">(</span>argc <span class="o"><</span> <span class="mi">5</span><span class="p">)</span> <span class="p">{</span> |
| 452 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"usage: %s <device> <width> <height> <count></span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 453 | argv<span class="p">[</span><span class="mi">0</span><span class="p">]);</span> |
| 454 | exit<span class="p">(</span><span class="mi">1</span><span class="p">);</span> |
| 455 | <span class="p">}</span> |
| 456 | dev_name <span class="o">=</span> argv<span class="p">[</span><span class="mi">1</span><span class="p">];</span> |
| 457 | width <span class="o">=</span> atoi<span class="p">(</span>argv<span class="p">[</span><span class="mi">2</span><span class="p">]);</span> |
| 458 | height <span class="o">=</span> atoi<span class="p">(</span>argv<span class="p">[</span><span class="mi">3</span><span class="p">]);</span> |
| 459 | count <span class="o">=</span> atoi<span class="p">(</span>argv<span class="p">[</span><span class="mi">4</span><span class="p">]);</span> |
| 460 | |
| 461 | <span class="cm">/* open device */</span> |
| 462 | fd <span class="o">=</span> open<span class="p">(</span>dev_name<span class="p">,</span> O_RDWR <span class="o">|</span> O_NONBLOCK<span class="p">,</span> <span class="mi">0</span><span class="p">);</span> |
| 463 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> fd<span class="p">)</span> <span class="p">{</span> |
| 464 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"Cannot open '%s': %d, %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 465 | dev_name<span class="p">,</span> errno<span class="p">,</span> strerror<span class="p">(</span>errno<span class="p">));</span> |
| 466 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 467 | <span class="p">}</span> |
| 468 | |
| 469 | <span class="cm">/* get standard (wait for it to be locked onto a signal) */</span> |
| 470 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_G_STD<span class="p">,</span> <span class="o">&</span>std_id<span class="p">))</span> |
| 471 | perror<span class="p">(</span><span class="s">"VIDIOC_G_STD"</span><span class="p">);</span> |
| 472 | <span class="k">for</span> <span class="p">(</span>i <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> std_id <span class="o">==</span> V4L2_STD_ALL <span class="o">&&</span> i <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> i<span class="o">++</span><span class="p">)</span> <span class="p">{</span> |
| 473 | usleep<span class="p">(</span><span class="mi">100000</span><span class="p">);</span> |
| 474 | xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_G_STD<span class="p">,</span> <span class="o">&</span>std_id<span class="p">);</span> |
| 475 | <span class="p">}</span> |
| 476 | <span class="cm">/* set the standard to the detected standard (this is critical for autodetect) */</span> |
| 477 | <span class="k">if</span> <span class="p">(</span>std_id <span class="o">!=</span> V4L2_STD_UNKNOWN<span class="p">)</span> <span class="p">{</span> |
| 478 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_S_STD<span class="p">,</span> <span class="o">&</span>std_id<span class="p">))</span> |
| 479 | perror<span class="p">(</span><span class="s">"VIDIOC_S_STD"</span><span class="p">);</span> |
| 480 | <span class="k">if</span> <span class="p">(</span>std_id <span class="o">&</span> V4L2_STD_NTSC<span class="p">)</span> |
| 481 | printf<span class="p">(</span><span class="s">"found NTSC TV decoder</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 482 | <span class="k">if</span> <span class="p">(</span>std_id <span class="o">&</span> V4L2_STD_SECAM<span class="p">)</span> |
| 483 | printf<span class="p">(</span><span class="s">"found SECAM TV decoder</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 484 | <span class="k">if</span> <span class="p">(</span>std_id <span class="o">&</span> V4L2_STD_PAL<span class="p">)</span> |
| 485 | printf<span class="p">(</span><span class="s">"found PAL TV decoder</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 486 | <span class="p">}</span> |
| 487 | |
| 488 | <span class="cm">/* ensure device has video capture capability */</span> |
| 489 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_QUERYCAP<span class="p">,</span> <span class="o">&</span>cap<span class="p">))</span> <span class="p">{</span> |
| 490 | <span class="k">if</span> <span class="p">(</span>EINVAL <span class="o">==</span> errno<span class="p">)</span> <span class="p">{</span> |
| 491 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"%s is no V4L2 device</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 492 | dev_name<span class="p">);</span> |
| 493 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 494 | <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> |
| 495 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_QUERYCAP"</span><span class="p">);</span> |
| 496 | <span class="p">}</span> |
| 497 | <span class="p">}</span> |
| 498 | <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span>cap<span class="p">.</span>capabilities <span class="o">&</span> V4L2_CAP_VIDEO_CAPTURE<span class="p">))</span> <span class="p">{</span> |
| 499 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"%s is no video capture device</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 500 | dev_name<span class="p">);</span> |
| 501 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 502 | <span class="p">}</span> |
| 503 | <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span>cap<span class="p">.</span>capabilities <span class="o">&</span> V4L2_CAP_STREAMING<span class="p">))</span> <span class="p">{</span> |
| 504 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"%s does not support streaming i/o</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 505 | dev_name<span class="p">);</span> |
| 506 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 507 | <span class="p">}</span> |
| 508 | |
| 509 | <span class="cm">/* set video input */</span> |
| 510 | CLEAR<span class="p">(</span>input<span class="p">);</span> |
| 511 | input<span class="p">.</span>index <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="cm">/* IMX6 v4l2 driver: input1 is CSI<->MEM */</span> |
| 512 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_S_INPUT<span class="p">,</span> <span class="o">&</span>input<span class="p">))</span> |
| 513 | perror<span class="p">(</span><span class="s">"VIDIOC_S_INPUT"</span><span class="p">);</span> |
| 514 | |
| 515 | <span class="cm">/* set framerate */</span> |
| 516 | CLEAR<span class="p">(</span>parm<span class="p">);</span> |
| 517 | parm<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 518 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_S_PARM<span class="p">,</span> <span class="o">&</span>parm<span class="p">))</span> |
| 519 | perror<span class="p">(</span><span class="s">"VIDIOC_S_PARM"</span><span class="p">);</span> |
| 520 | |
| 521 | <span class="cm">/* get framerate */</span> |
| 522 | CLEAR<span class="p">(</span>parm<span class="p">);</span> |
| 523 | parm<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 524 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_G_PARM<span class="p">,</span> <span class="o">&</span>parm<span class="p">))</span> |
| 525 | perror<span class="p">(</span><span class="s">"VIDIOC_G_PARM"</span><span class="p">);</span> |
| 526 | |
| 527 | <span class="cm">/* set format */</span> |
| 528 | CLEAR<span class="p">(</span>fmt<span class="p">);</span> |
| 529 | fmt<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 530 | fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>width <span class="o">=</span> width<span class="p">;</span> |
| 531 | fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>height <span class="o">=</span> height<span class="p">;</span> |
| 532 | fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>pixelformat <span class="o">=</span> V4L2_PIX_FMT_UYVY<span class="p">;</span> |
| 533 | fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>field <span class="o">=</span> V4L2_FIELD_ANY<span class="p">;</span> |
| 534 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_S_FMT<span class="p">,</span> <span class="o">&</span>fmt<span class="p">))</span> |
| 535 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_S_FMT"</span><span class="p">);</span> |
| 536 | |
| 537 | <span class="cm">/* get and display format */</span> |
| 538 | CLEAR<span class="p">(</span>fmt<span class="p">);</span> |
| 539 | fmt<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 540 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_G_FMT<span class="p">,</span> <span class="o">&</span>fmt<span class="p">))</span> |
| 541 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_G_FMT"</span><span class="p">);</span> |
| 542 | printf<span class="p">(</span><span class="s">"%s: %dx%d %c%c%c%c %2.2ffps</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> dev_name<span class="p">,</span> |
| 543 | fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>width<span class="p">,</span> fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>height<span class="p">,</span> |
| 544 | <span class="p">(</span>fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>pixelformat <span class="o">>></span> <span class="mi">0</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 545 | <span class="p">(</span>fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>pixelformat <span class="o">>></span> <span class="mi">8</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 546 | <span class="p">(</span>fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>pixelformat <span class="o">>></span> <span class="mi">16</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 547 | <span class="p">(</span>fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">.</span>pixelformat <span class="o">>></span> <span class="mi">24</span><span class="p">)</span> <span class="o">&</span> <span class="mh">0xff</span><span class="p">,</span> |
| 548 | <span class="p">(</span><span class="kt">float</span><span class="p">)</span>parm<span class="p">.</span>parm<span class="p">.</span>capture<span class="p">.</span>timeperframe<span class="p">.</span>denominator <span class="o">/</span> |
| 549 | <span class="p">(</span><span class="kt">float</span><span class="p">)</span>parm<span class="p">.</span>parm<span class="p">.</span>capture<span class="p">.</span>timeperframe<span class="p">.</span>numerator |
| 550 | <span class="p">);</span> |
| 551 | |
| 552 | <span class="cm">/* request buffers */</span> |
| 553 | CLEAR<span class="p">(</span>req<span class="p">);</span> |
| 554 | req<span class="p">.</span>count <span class="o">=</span> <span class="mi">4</span><span class="p">;</span> |
| 555 | req<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 556 | req<span class="p">.</span>memory <span class="o">=</span> V4L2_MEMORY_MMAP<span class="p">;</span> |
| 557 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_REQBUFS<span class="p">,</span> <span class="o">&</span>req<span class="p">))</span> <span class="p">{</span> |
| 558 | <span class="k">if</span> <span class="p">(</span>EINVAL <span class="o">==</span> errno<span class="p">)</span> <span class="p">{</span> |
| 559 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"%s does not support "</span> |
| 560 | <span class="s">"memory mapping</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> dev_name<span class="p">);</span> |
| 561 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 562 | <span class="p">}</span> <span class="k">else</span> <span class="p">{</span> |
| 563 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_REQBUFS"</span><span class="p">);</span> |
| 564 | <span class="p">}</span> |
| 565 | <span class="p">}</span> |
| 566 | <span class="k">if</span> <span class="p">(</span>req<span class="p">.</span>count <span class="o"><</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> |
| 567 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"Insufficient buffer memory on %s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> |
| 568 | dev_name<span class="p">);</span> |
| 569 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 570 | <span class="p">}</span> |
| 571 | |
| 572 | <span class="cm">/* allocate buffers */</span> |
| 573 | buffers <span class="o">=</span> calloc<span class="p">(</span>req<span class="p">.</span>count<span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="o">*</span>buffers<span class="p">));</span> |
| 574 | <span class="k">if</span> <span class="p">(</span><span class="o">!</span>buffers<span class="p">)</span> <span class="p">{</span> |
| 575 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"Out of memory</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 576 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 577 | <span class="p">}</span> |
| 578 | |
| 579 | <span class="cm">/* mmap buffers */</span> |
| 580 | <span class="k">for</span> <span class="p">(</span>n_buffers <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> n_buffers <span class="o"><</span> req<span class="p">.</span>count<span class="p">;</span> <span class="o">++</span>n_buffers<span class="p">)</span> <span class="p">{</span> |
| 581 | <span class="k">struct</span> v4l2_buffer buf<span class="p">;</span> |
| 582 | |
| 583 | CLEAR<span class="p">(</span>buf<span class="p">);</span> |
| 584 | |
| 585 | buf<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 586 | buf<span class="p">.</span>memory <span class="o">=</span> V4L2_MEMORY_MMAP<span class="p">;</span> |
| 587 | buf<span class="p">.</span>index <span class="o">=</span> n_buffers<span class="p">;</span> |
| 588 | |
| 589 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_QUERYBUF<span class="p">,</span> <span class="o">&</span>buf<span class="p">))</span> |
| 590 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_QUERYBUF"</span><span class="p">);</span> |
| 591 | |
| 592 | buffers<span class="p">[</span>n_buffers<span class="p">].</span>length <span class="o">=</span> buf<span class="p">.</span>length<span class="p">;</span> |
| 593 | buffers<span class="p">[</span>n_buffers<span class="p">].</span>start <span class="o">=</span> |
| 594 | mmap<span class="p">(</span><span class="nb">NULL</span> <span class="cm">/* start anywhere */</span><span class="p">,</span> |
| 595 | buf<span class="p">.</span>length<span class="p">,</span> |
| 596 | PROT_READ <span class="o">|</span> PROT_WRITE <span class="cm">/* required */</span><span class="p">,</span> |
| 597 | MAP_SHARED <span class="cm">/* recommended */</span><span class="p">,</span> |
| 598 | fd<span class="p">,</span> buf<span class="p">.</span>m<span class="p">.</span>offset<span class="p">);</span> |
| 599 | |
| 600 | <span class="k">if</span> <span class="p">(</span>MAP_FAILED <span class="o">==</span> buffers<span class="p">[</span>n_buffers<span class="p">].</span>start<span class="p">)</span> |
| 601 | errno_exit<span class="p">(</span><span class="s">"mmap"</span><span class="p">);</span> |
| 602 | <span class="p">}</span> |
| 603 | |
| 604 | <span class="cm">/* queue buffers */</span> |
| 605 | <span class="k">for</span> <span class="p">(</span>i <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> i <span class="o"><</span> n_buffers<span class="p">;</span> <span class="o">++</span>i<span class="p">)</span> <span class="p">{</span> |
| 606 | <span class="k">struct</span> v4l2_buffer buf<span class="p">;</span> |
| 607 | |
| 608 | CLEAR<span class="p">(</span>buf<span class="p">);</span> |
| 609 | buf<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 610 | buf<span class="p">.</span>memory <span class="o">=</span> V4L2_MEMORY_MMAP<span class="p">;</span> |
| 611 | buf<span class="p">.</span>index <span class="o">=</span> i<span class="p">;</span> |
| 612 | |
| 613 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_QBUF<span class="p">,</span> <span class="o">&</span>buf<span class="p">))</span> |
| 614 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_QBUF"</span><span class="p">);</span> |
| 615 | <span class="p">}</span> |
| 616 | |
| 617 | <span class="cm">/* start capture */</span> |
| 618 | type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 619 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_STREAMON<span class="p">,</span> <span class="o">&</span>type<span class="p">))</span> |
| 620 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_STREAMON"</span><span class="p">);</span> |
| 621 | |
| 622 | <span class="cm">/* capture frame(s) (we throw away first incomplete frame ) */</span> |
| 623 | <span class="k">for</span> <span class="p">(</span>i <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> i <span class="o"><</span> count <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> i<span class="o">++</span><span class="p">)</span> <span class="p">{</span> |
| 624 | <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span> |
| 625 | fd_set fds<span class="p">;</span> |
| 626 | <span class="k">struct</span> timeval tv<span class="p">;</span> |
| 627 | <span class="kt">int</span> r<span class="p">;</span> |
| 628 | |
| 629 | FD_ZERO<span class="p">(</span><span class="o">&</span>fds<span class="p">);</span> |
| 630 | FD_SET<span class="p">(</span>fd<span class="p">,</span> <span class="o">&</span>fds<span class="p">);</span> |
| 631 | |
| 632 | <span class="cm">/* Timeout. */</span> |
| 633 | tv<span class="p">.</span>tv_sec <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> |
| 634 | tv<span class="p">.</span>tv_usec <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> |
| 635 | |
| 636 | r <span class="o">=</span> select<span class="p">(</span>fd <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="o">&</span>fds<span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="o">&</span>tv<span class="p">);</span> |
| 637 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> r<span class="p">)</span> <span class="p">{</span> |
| 638 | <span class="k">if</span> <span class="p">(</span>EINTR <span class="o">==</span> errno<span class="p">)</span> |
| 639 | <span class="k">continue</span><span class="p">;</span> |
| 640 | errno_exit<span class="p">(</span><span class="s">"select"</span><span class="p">);</span> |
| 641 | <span class="p">}</span> |
| 642 | <span class="k">if</span> <span class="p">(</span><span class="mi">0</span> <span class="o">==</span> r<span class="p">)</span> <span class="p">{</span> |
| 643 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"select timeout</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 644 | exit<span class="p">(</span>EXIT_FAILURE<span class="p">);</span> |
| 645 | <span class="p">}</span> |
| 646 | |
| 647 | <span class="cm">/* dequeue captured buffer */</span> |
| 648 | CLEAR<span class="p">(</span>buf<span class="p">);</span> |
| 649 | buf<span class="p">.</span>type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 650 | buf<span class="p">.</span>memory <span class="o">=</span> V4L2_MEMORY_MMAP<span class="p">;</span> |
| 651 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_DQBUF<span class="p">,</span> <span class="o">&</span>buf<span class="p">))</span> <span class="p">{</span> |
| 652 | <span class="k">if</span> <span class="p">(</span>errno <span class="o">==</span> EAGAIN<span class="p">)</span> |
| 653 | <span class="k">continue</span><span class="p">;</span> |
| 654 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_DQBUF"</span><span class="p">);</span> |
| 655 | <span class="p">}</span> |
| 656 | assert<span class="p">(</span>buf<span class="p">.</span>index <span class="o"><</span> n_buffers<span class="p">);</span> |
| 657 | |
| 658 | <span class="cm">/* skip first image as it may not be sync'd */</span> |
| 659 | <span class="k">if</span> <span class="p">(</span>i <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> |
| 660 | process_image<span class="p">(</span>buffers<span class="p">[</span>buf<span class="p">.</span>index<span class="p">].</span>start<span class="p">,</span> |
| 661 | <span class="o">&</span>fmt<span class="p">.</span>fmt<span class="p">.</span>pix<span class="p">);</span> |
| 662 | sprintf<span class="p">(</span>filename<span class="p">,</span> <span class="s">"frame%d.raw"</span><span class="p">,</span> i<span class="p">);</span> |
| 663 | save_frame<span class="p">(</span>filename<span class="p">,</span> |
| 664 | buffers<span class="p">[</span>buf<span class="p">.</span>index<span class="p">].</span>start<span class="p">,</span> |
| 665 | buf<span class="p">.</span>bytesused<span class="p">);</span> |
| 666 | <span class="p">}</span> |
| 667 | |
| 668 | <span class="cm">/* queue buffer */</span> |
| 669 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_QBUF<span class="p">,</span> <span class="o">&</span>buf<span class="p">))</span> |
| 670 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_QBUF"</span><span class="p">);</span> |
| 671 | |
| 672 | <span class="k">break</span><span class="p">;</span> |
| 673 | <span class="p">}</span> |
| 674 | <span class="p">}</span> |
| 675 | |
| 676 | <span class="cm">/* stop capture */</span> |
| 677 | type <span class="o">=</span> V4L2_BUF_TYPE_VIDEO_CAPTURE<span class="p">;</span> |
| 678 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> xioctl<span class="p">(</span>fd<span class="p">,</span> VIDIOC_STREAMOFF<span class="p">,</span> <span class="o">&</span>type<span class="p">))</span> |
| 679 | errno_exit<span class="p">(</span><span class="s">"VIDIOC_STREAMOFF"</span><span class="p">);</span> |
| 680 | |
| 681 | <span class="cm">/* unmap and free buffers */</span> |
| 682 | <span class="k">for</span> <span class="p">(</span>i <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> i <span class="o"><</span> n_buffers<span class="p">;</span> <span class="o">++</span>i<span class="p">)</span> |
| 683 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> munmap<span class="p">(</span>buffers<span class="p">[</span>i<span class="p">].</span>start<span class="p">,</span> buffers<span class="p">[</span>i<span class="p">].</span>length<span class="p">))</span> |
| 684 | errno_exit<span class="p">(</span><span class="s">"munmap"</span><span class="p">);</span> |
| 685 | free<span class="p">(</span>buffers<span class="p">);</span> |
| 686 | |
| 687 | <span class="cm">/* close device */</span> |
| 688 | <span class="k">if</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">==</span> close<span class="p">(</span>fd<span class="p">))</span> |
| 689 | errno_exit<span class="p">(</span><span class="s">"close"</span><span class="p">);</span> |
| 690 | |
| 691 | fprintf<span class="p">(</span>stderr<span class="p">,</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span> |
| 692 | <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> |
| 693 | <span class="p">}</span> |
| 694 | </pre></div></li></ul><p> |
| 695 | Example usage: |
| 696 | </p> |
| 697 | <ul><li>Capture HDMI input on GW5400 from a 1080P HDMI source: |
| 698 | <div class="code"><pre><span class="nv">$ </span>./capture /dev/video0 1920 1080 1 |
| 699 | /dev/video0: 1920x1080 UYVY 60.00fps |
| 700 | Processing Frame: 1920x1080 UYVY |
| 701 | <span class="o">[</span> 0, 0<span class="o">]</span> YUYV:0xeb00eb00 RGB:0xebebeb |
| 702 | <span class="o">[</span> 250, 0<span class="o">]</span> YUYV:0x9dad9d0d RGB:0xaeb409 |
| 703 | <span class="o">[</span> 500, 0<span class="o">]</span> YUYV:0x801b80ae RGB:0x0bb6ae |
| 704 | <span class="o">[</span> 750, 0<span class="o">]</span> YUYV:0x6dc96dbb RGB:0x0ab50b |
| 705 | <span class="o">[</span>1000, 0<span class="o">]</span> YUYV:0x52365244 RGB:0xb111b0 |
| 706 | red pixel <span class="nv">count</span><span class="o">=</span>259200 |
| 707 | Wrote 4147200 of 4147200 bytes to frame.raw |
| 708 | |
| 709 | ./convert -size 1920x1080 -depth 16 uyvy:frame.raw frame.png <span class="c"># convert to png via imagemagick |
| 710 | </span></pre></div></li><li>Capture CVBS input on GW5400 from NTSC camera (720x480): |
| 711 | <div class="code"><pre><span class="nv">$ </span>./capture /dev/video1 720 480 1 |
| 712 | /dev/video1: 720x520 UYVY 30.00fps |
| 713 | Processing Frame: 720x520 UYVY |
| 714 | <span class="o">[</span> 0, 0<span class="o">]</span> YUYV:0x1eff1c00 RGB:0x1c1f18 |
| 715 | <span class="o">[</span> 250, 0<span class="o">]</span> YUYV:0x1dfd1d01 RGB:0x1e2016 |
| 716 | <span class="o">[</span> 500, 0<span class="o">]</span> YUYV:0x28fa2aff RGB:0x26321e |
| 717 | red pixel <span class="nv">count</span><span class="o">=</span>27 |
| 718 | Wrote 748800 of 748800 bytes to frame.raw |
| 719 | |
| 720 | ./convert -size 720x480 -depth 16 uyvy:frame.raw frame.png <span class="c"># convert to png via imagemagick |
| 721 | </span></pre></div></li></ul |
| 722 | }}} |