<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <title>ZVBI Library: examples/wss.c</title> <link href="tabs.css" rel="stylesheet" type="text/css"> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.5.9 --> <div class="navigation" id="top"> <div class="tabs"> <ul> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="pages.html"><span>Related Pages</span></a></li> <li><a href="modules.html"><span>Modules</span></a></li> <li><a href="annotated.html"><span>Data Structures</span></a></li> <li><a href="examples.html"><span>Examples</span></a></li> </ul> </div> </div> <div class="contents"> <h1>examples/wss.c</h1>WSS capture example.<p> <div class="fragment"><pre class="fragment"><span class="comment">/*</span> <span class="comment"> * libzvbi WSS capture example</span> <span class="comment"> *</span> <span class="comment"> * Copyright (C) 2005 Michael H. Schimek</span> <span class="comment"> *</span> <span class="comment"> * Redistribution and use in source and binary forms, with or without</span> <span class="comment"> * modification, are permitted provided that the following conditions</span> <span class="comment"> * are met:</span> <span class="comment"> * 1. Redistributions of source code must retain the above copyright</span> <span class="comment"> * notice, this list of conditions and the following disclaimer.</span> <span class="comment"> * 2. Redistributions in binary form must reproduce the above copyright</span> <span class="comment"> * notice, this list of conditions and the following disclaimer in</span> <span class="comment"> * the documentation and/or other materials provided with the</span> <span class="comment"> * distribution.</span> <span class="comment"> * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS</span> <span class="comment"> * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT</span> <span class="comment"> * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR</span> <span class="comment"> * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT</span> <span class="comment"> * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</span> <span class="comment"> * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</span> <span class="comment"> * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,</span> <span class="comment"> * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY</span> <span class="comment"> * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT</span> <span class="comment"> * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span> <span class="comment"> * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span> <span class="comment"> */</span> <span class="comment">/* $Id: wss.c,v 1.11 2008/02/19 00:52:04 mschimek Exp $ */</span> <span class="comment">/* This example shows how to extract Wide Screen Signalling data</span> <span class="comment"> (EN 300 294) from video images. The signal is transmitted on the</span> <span class="comment"> first half of PAL/SECAM scan line 23, which ITU-R BT.601 defines</span> <span class="comment"> as the first line of a 576 line picture.</span> <span class="comment"></span> <span class="comment"> The author is not aware of any drivers which can capture a scan</span> <span class="comment"> line as raw VBI and video data at the same time, and sliced VBI</span> <span class="comment"> capturing is not supported yet by libzvbi. Note some drivers like</span> <span class="comment"> the Linux saa7134 driver cannot capture line 23 at all.</span> <span class="comment"></span> <span class="comment"> gcc -o wss wss.c `pkg-config zvbi-0.2 --cflags --libs` */</span> <span class="preprocessor">#ifdef HAVE_CONFIG_H</span> <span class="preprocessor"></span><span class="preprocessor"># include "config.h"</span> <span class="preprocessor">#endif</span> <span class="preprocessor"></span> <span class="preprocessor">#include <stdio.h></span> <span class="preprocessor">#include <stdlib.h></span> <span class="preprocessor">#include <string.h></span> <span class="preprocessor">#include <assert.h></span> <span class="preprocessor">#ifdef ENABLE_V4L2</span> <span class="preprocessor"></span> <span class="preprocessor">#include <fcntl.h></span> <span class="comment">/* low-level i/o */</span> <span class="preprocessor">#include <unistd.h></span> <span class="preprocessor">#include <errno.h></span> <span class="preprocessor">#include <sys/stat.h></span> <span class="preprocessor">#include <sys/types.h></span> <span class="preprocessor">#include <sys/time.h></span> <span class="preprocessor">#include <sys/mman.h></span> <span class="preprocessor">#include <sys/ioctl.h></span> <span class="preprocessor">#include <libzvbi.h></span> <span class="preprocessor">#include <asm/types.h></span> <span class="comment">/* for videodev2.h */</span> <span class="preprocessor">#include "videodev2k.h"</span> <span class="preprocessor">#define CLEAR(x) memset (&(x), 0, sizeof (x))</span> <span class="preprocessor"></span> <span class="keyword">struct </span>buffer { <span class="keywordtype">void</span> * start; <span class="keywordtype">size_t</span> length; }; <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> * dev_name = <span class="stringliteral">"/dev/video"</span>; <span class="keyword">static</span> <span class="keywordtype">int</span> fd; <span class="keyword">static</span> <span class="keyword">struct </span>buffer * buffers; <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_buffers; <span class="keyword">static</span> <span class="keywordtype">int</span> quit; <span class="keyword">static</span> <a name="_a0"></a><a class="code" href="structvbi__raw__decoder.html" title="Raw vbi decoder context.">vbi_raw_decoder</a> rd; <span class="keyword">static</span> <span class="keywordtype">void</span> errno_exit (<span class="keyword">const</span> <span class="keywordtype">char</span> * s) { fprintf (stderr, <span class="stringliteral">"%s error %d, %s\n"</span>, s, errno, strerror (errno)); exit (EXIT_FAILURE); } <span class="keyword">static</span> <span class="keywordtype">int</span> xioctl (<span class="keywordtype">int</span> fd, <span class="keywordtype">int</span> request, <span class="keywordtype">void</span> * p) { <span class="keywordtype">int</span> r; <span class="keywordflow">do</span> r = ioctl (fd, request, p); <span class="keywordflow">while</span> (-1 == r && EINTR == errno); <span class="keywordflow">return</span> r; } <span class="keyword">static</span> <span class="keywordtype">void</span> decode_wss_625 (uint8_t * buf) { <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *formats [] = { <span class="stringliteral">"Full format 4:3, 576 lines"</span>, <span class="stringliteral">"Letterbox 14:9 centre, 504 lines"</span>, <span class="stringliteral">"Letterbox 14:9 top, 504 lines"</span>, <span class="stringliteral">"Letterbox 16:9 centre, 430 lines"</span>, <span class="stringliteral">"Letterbox 16:9 top, 430 lines"</span>, <span class="stringliteral">"Letterbox > 16:9 centre"</span>, <span class="stringliteral">"Full format 14:9 centre, 576 lines"</span>, <span class="stringliteral">"Anamorphic 16:9, 576 lines"</span> }; <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> *subtitles [] = { <span class="stringliteral">"none"</span>, <span class="stringliteral">"in active image area"</span>, <span class="stringliteral">"out of active image area"</span>, <span class="stringliteral">"<invalid>"</span> }; <span class="keywordtype">int</span> g1; <span class="keywordtype">int</span> parity; g1 = buf[0] & 15; parity = g1; parity ^= parity >> 2; parity ^= parity >> 1; g1 &= 7; printf (<span class="stringliteral">"WSS PAL: "</span>); <span class="keywordflow">if</span> (!(parity & 1)) printf (<span class="stringliteral">"<parity error> "</span>); printf (<span class="stringliteral">"%s; %s mode; %s colour coding; %s helper; "</span> <span class="stringliteral">"reserved b7=%d; %s Teletext subtitles; "</span> <span class="stringliteral">"open subtitles: %s; %s surround sound; "</span> <span class="stringliteral">"copyright %s; copying %s\n"</span>, formats[g1], (buf[0] & 0x10) ? <span class="stringliteral">"film"</span> : <span class="stringliteral">"camera"</span>, (buf[0] & 0x20) ? <span class="stringliteral">"MA/CP"</span> : <span class="stringliteral">"standard"</span>, (buf[0] & 0x40) ? <span class="stringliteral">"modulated"</span> : <span class="stringliteral">"no"</span>, !!(buf[0] & 0x80), (buf[1] & 0x01) ? <span class="stringliteral">"have"</span> : <span class="stringliteral">"no"</span>, subtitles[(buf[1] >> 1) & 3], (buf[1] & 0x08) ? <span class="stringliteral">"have"</span> : <span class="stringliteral">"no"</span>, (buf[1] & 0x10) ? <span class="stringliteral">"asserted"</span> : <span class="stringliteral">"unknown"</span>, (buf[1] & 0x20) ? <span class="stringliteral">"restricted"</span> : <span class="stringliteral">"not restricted"</span>); } <span class="keyword">static</span> <span class="keywordtype">void</span> process_image (<span class="keyword">const</span> <span class="keywordtype">void</span> * p) { <a name="_a1"></a><a class="code" href="structvbi__sliced.html" title="This structure holds one scan line of sliced vbi data.">vbi_sliced</a> sliced[1]; <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_lines; n_lines = <a name="a2"></a><a class="code" href="group__Rawdec.html#g590834a98acc13c74c08b72de4fbfe80">vbi_raw_decode</a> (&rd, (uint8_t *) p, sliced); <span class="keywordflow">if</span> (0 <span class="comment">/* test */</span>) { <span class="comment">/* Error ignored. */</span> write (STDOUT_FILENO, p, rd.<a name="a3"></a><a class="code" href="structvbi__raw__decoder.html#0610feb3dba297670cadb678d8370e80">bytes_per_line</a>); } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n_lines > 0) { assert (VBI_SLICED_WSS_625 == sliced[0].<span class="keywordtype">id</span>); assert (1 == n_lines); decode_wss_625 (sliced[0].data); } <span class="keywordflow">else</span> { fputc (<span class="charliteral">'.'</span>, stdout); fflush (stdout); } } <span class="keyword">static</span> <span class="keywordtype">void</span> init_decoder (<span class="keywordtype">void</span>) { <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> services; <a name="a4"></a><a class="code" href="group__Rawdec.html#g5bbc43c12196c9be0065ecc566906adb">vbi_raw_decoder_init</a> (&rd); rd.<a name="a5"></a><a class="code" href="structvbi__raw__decoder.html#7ff6b942e66eae2ca7a3b6bbfbbc550f">scanning</a> = 625; rd.<a name="a6"></a><a class="code" href="structvbi__raw__decoder.html#042431c6c0abab3eeecce4f9a014bd1d">sampling_format</a> = VBI_PIXFMT_YUYV; <span class="comment">/* Should be calculated from VIDIOC_CROPCAP information.</span> <span class="comment"> Common sampling rates are 14.75 MHz to get 768 PAL/SECAM</span> <span class="comment"> square pixels per line, and 13.5 MHz according to ITU-R Rec.</span> <span class="comment"> BT.601 with 720 pixels/line. Note BT.601 overscans the line:</span> <span class="comment"> 13.5e6 / 720 > 14.75e6 / 768. Don't be fooled by a driver</span> <span class="comment"> scaling 768 square pixels to 720. */</span> rd.<a name="a7"></a><a class="code" href="structvbi__raw__decoder.html#72596d7bf3dd5f3fedf8ce51f25f6377">sampling_rate</a> = 768 * 14.75e6 / 768; rd.<a class="code" href="structvbi__raw__decoder.html#0610feb3dba297670cadb678d8370e80">bytes_per_line</a> = 768 * 2; <span class="comment">/* Should be calculated from VIDIOC_CROPCAP information. */</span> rd.<a name="a8"></a><a class="code" href="structvbi__raw__decoder.html#ec686bff8271a5304417cdb2e84dd198">offset</a> = 0; rd.<a name="a9"></a><a class="code" href="structvbi__raw__decoder.html#b8a8df50593ebc6ab7d9f52f0cc8275d">start</a>[0] = 23; rd.<a name="a10"></a><a class="code" href="structvbi__raw__decoder.html#b77ddf5224b63d84d66c36daded1ab90">count</a>[0] = 1; rd.<a class="code" href="structvbi__raw__decoder.html#b8a8df50593ebc6ab7d9f52f0cc8275d">start</a>[1] = 0; rd.<a class="code" href="structvbi__raw__decoder.html#b77ddf5224b63d84d66c36daded1ab90">count</a>[1] = 0; rd.<a name="a11"></a><a class="code" href="structvbi__raw__decoder.html#b21be06e2fb0141314311d820c51b35f">interlaced</a> = FALSE; <span class="comment">/* just one line */</span> rd.<a name="a12"></a><a class="code" href="structvbi__raw__decoder.html#dbeef46d32445684cdf52c4cfbe8f3ac">synchronous</a> = TRUE; services = <a name="a13"></a><a class="code" href="group__Rawdec.html#g18c46d4a4885261c45e32e8eb509d1b9">vbi_raw_decoder_add_services</a> (&rd, VBI_SLICED_WSS_625, <span class="comment">/* strict */</span> 2); <span class="keywordflow">if</span> (0 == services) { fprintf (stderr, <span class="stringliteral">"Cannot decode WSS\n"</span>); exit (EXIT_FAILURE); } } <span class="keyword">static</span> <span class="keywordtype">void</span> mainloop (<span class="keywordtype">void</span>) { quit = 0; <span class="keywordflow">while</span> (!quit) { <span class="keyword">struct </span>v4l2_buffer buf; <span class="keywordflow">for</span> (;;) { fd_set fds; <span class="keyword">struct </span>timeval tv; <span class="keywordtype">int</span> r; FD_ZERO (&fds); FD_SET (fd, &fds); tv.tv_sec = 2; tv.tv_usec = 0; r = select (fd + 1, &fds, NULL, NULL, &tv); <span class="keywordflow">if</span> (-1 == r) { <span class="keywordflow">if</span> (EINTR == errno) { <span class="comment">/* XXX should subtract the elapsed</span> <span class="comment"> time from timeout here. */</span> <span class="keywordflow">continue</span>; } errno_exit (<span class="stringliteral">"select"</span>); } <span class="keywordflow">if</span> (0 == r) { fprintf (stderr, <span class="stringliteral">"select timeout\n"</span>); exit (EXIT_FAILURE); } <span class="keywordflow">break</span>; } CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) { <span class="keywordflow">if</span> (EAGAIN == errno) <span class="keywordflow">continue</span>; errno_exit (<span class="stringliteral">"VIDIOC_DQBUF"</span>); } assert (buf.index < n_buffers); process_image (buffers[buf.index].start); <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) errno_exit (<span class="stringliteral">"VIDIOC_QBUF"</span>); } } <span class="keyword">static</span> <span class="keywordtype">void</span> start_capturing (<span class="keywordtype">void</span>) { <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i; <span class="keyword">enum</span> v4l2_buf_type type; <span class="keywordflow">for</span> (i = 0; i < n_buffers; ++i) { <span class="keyword">struct </span>v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) errno_exit (<span class="stringliteral">"VIDIOC_QBUF"</span>); } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_STREAMON, &type)) errno_exit (<span class="stringliteral">"VIDIOC_STREAMON"</span>); } <span class="keyword">static</span> <span class="keywordtype">void</span> init_device (<span class="keywordtype">void</span>) { <span class="keyword">struct </span>v4l2_capability cap; v4l2_std_id std_id; <span class="keyword">struct </span>v4l2_format fmt; <span class="keyword">struct </span>v4l2_requestbuffers req; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) { <span class="keywordflow">if</span> (EINVAL == errno) { fprintf (stderr, <span class="stringliteral">"%s is no V4L2 device\n"</span>, dev_name); exit (EXIT_FAILURE); } <span class="keywordflow">else</span> { errno_exit (<span class="stringliteral">"VIDIOC_QUERYCAP"</span>); } } <span class="keywordflow">if</span> (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf (stderr, <span class="stringliteral">"%s is no video capture device\n"</span>, dev_name); exit (EXIT_FAILURE); } <span class="keywordflow">if</span> (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf (stderr, <span class="stringliteral">"%s does not support streaming I/O\n"</span>, dev_name); exit (EXIT_FAILURE); } std_id = V4L2_STD_PAL; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_S_STD, &std_id)) errno_exit (<span class="stringliteral">"VIDIOC_S_STD"</span>); CLEAR (fmt); <span class="comment">/* We need the top field without vertical scaling,</span> <span class="comment"> width must be at least 320 pixels. */</span> fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = 768; fmt.fmt.pix.height = 576; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) errno_exit (<span class="stringliteral">"VIDIOC_S_FMT"</span>); <span class="comment">/* XXX the driver may adjust width and height, some</span> <span class="comment"> even change the pixelformat, that should be checked here. */</span> CLEAR (req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) { <span class="keywordflow">if</span> (EINVAL == errno) { fprintf (stderr, <span class="stringliteral">"%s does not support "</span> <span class="stringliteral">"memory mapping\n"</span>, dev_name); exit (EXIT_FAILURE); } <span class="keywordflow">else</span> { errno_exit (<span class="stringliteral">"VIDIOC_REQBUFS"</span>); } } <span class="keywordflow">if</span> (req.count < 2) { fprintf (stderr, <span class="stringliteral">"Insufficient buffer memory on %s\n"</span>, dev_name); exit (EXIT_FAILURE); } buffers = calloc (req.count, sizeof (*buffers)); <span class="keywordflow">if</span> (!buffers) { fprintf (stderr, <span class="stringliteral">"Out of memory\n"</span>); exit (EXIT_FAILURE); } <span class="keywordflow">for</span> (n_buffers = 0; n_buffers < req.count; ++n_buffers) { <span class="keyword">struct </span>v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffers; <span class="keywordflow">if</span> (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf)) errno_exit (<span class="stringliteral">"VIDIOC_QUERYBUF"</span>); buffers[n_buffers].length = buf.length; buffers[n_buffers].start = mmap (NULL <span class="comment">/* start anywhere */</span>, buf.length, PROT_READ | PROT_WRITE <span class="comment">/* required */</span>, MAP_SHARED <span class="comment">/* recommended */</span>, fd, buf.m.offset); <span class="keywordflow">if</span> (MAP_FAILED == buffers[n_buffers].start) errno_exit (<span class="stringliteral">"mmap"</span>); } } <span class="keyword">static</span> <span class="keywordtype">void</span> open_device (<span class="keywordtype">void</span>) { <span class="keyword">struct </span>stat st; <span class="keywordflow">if</span> (-1 == stat (dev_name, &st)) { fprintf (stderr, <span class="stringliteral">"Cannot identify '%s': %d, %s\n"</span>, dev_name, errno, strerror (errno)); exit (EXIT_FAILURE); } <span class="keywordflow">if</span> (!S_ISCHR (st.st_mode)) { fprintf (stderr, <span class="stringliteral">"%s is no device\n"</span>, dev_name); exit (EXIT_FAILURE); } fd = open (dev_name, O_RDWR | O_NONBLOCK, 0); <span class="keywordflow">if</span> (-1 == fd) { fprintf (stderr, <span class="stringliteral">"Cannot open '%s': %d, %s\n"</span>, dev_name, errno, strerror (errno)); exit (EXIT_FAILURE); } } <span class="keywordtype">int</span> main (<span class="keywordtype">void</span>) { <span class="comment">/* Helps debugging. */</span> <a name="a14"></a><a class="code" href="group__Basic.html#g594dbe49c85f00a11c3586a131203b61">vbi_set_log_fn</a> (<span class="comment">/* mask: log everything */</span> -1, <a name="a15"></a><a class="code" href="group__Basic.html#g892c64da1c60919512f0c4db6641a708">vbi_log_on_stderr</a>, <span class="comment">/* user_data */</span> NULL); open_device (); init_device (); init_decoder (); start_capturing (); mainloop (); exit (EXIT_SUCCESS); <span class="keywordflow">return</span> 0; } <span class="preprocessor">#else </span><span class="comment">/* !ENABLE_V4L2 */</span> <span class="keywordtype">int</span> main (<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> ** argv) { fprintf (stderr, <span class="stringliteral">"Sorry, V4L2 only. Patches welcome.\n"</span>); exit (EXIT_FAILURE); <span class="keywordflow">return</span> 0; } <span class="preprocessor">#endif </span><span class="comment">/* !ENABLE_V4L2 */</span> </pre></div> </div> <hr size="1"><address style="text-align: right;"><small>Generated on Wed May 27 04:47:58 2009 for ZVBI Library by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.9 </small></address> </body> </html>