00001 /* 00002 * libzvbi raw VBI output example 00003 * 00004 * Copyright (C) 2006 Michael H. Schimek 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in 00013 * the documentation and/or other materials provided with the 00014 * distribution. 00015 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00016 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00017 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00018 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00019 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00022 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00023 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00025 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 /* $Id: rawout.c,v 1.8 2008/02/19 00:52:04 mschimek Exp $ */ 00029 00030 /* This example shows how to convert VBI data in a DVB PES stream 00031 to raw VBI data. 00032 00033 gcc -o rawout rawout.c `pkg-config zvbi-0.2 --cflags --libs` 00034 00035 ./rawout <pes | mplayer - -rawvideo on:w=720:h=34:format=0x32595559 */ 00036 00037 #undef NDEBUG 00038 #include <assert.h> 00039 #include <stdio.h> 00040 #include <stdlib.h> 00041 #include <string.h> 00042 #include <unistd.h> 00043 00044 #include <libzvbi.h> 00045 00046 static vbi_dvb_demux * dvb; 00047 static uint8_t pes_buffer[2048]; 00048 static vbi_sampling_par sp; 00049 static uint8_t * image; 00050 static unsigned int image_size; 00051 static unsigned int pixel_mask; 00052 static int64_t last_pts; 00053 static vbi_raw_decoder rd; 00054 00055 static void 00056 raw_test (const vbi_sliced * expect_sliced, 00057 unsigned int expect_n_lines) 00058 { 00059 vbi_sliced sliced[50]; 00060 unsigned int n_lines; 00061 unsigned int i; 00062 00063 n_lines = vbi_raw_decode (&rd, image, sliced); 00064 assert (n_lines == expect_n_lines); 00065 00066 for (i = 0; i < n_lines; ++i) { 00067 unsigned int payload; 00068 00069 assert (sliced[i].id == expect_sliced[i].id); 00070 assert (sliced[i].line == expect_sliced[i].line); 00071 00072 payload = (vbi_sliced_payload_bits (sliced[i].id) + 7) / 8; 00073 assert (0 == memcmp (sliced[i].data, 00074 expect_sliced[i].data, 00075 payload)); 00076 } 00077 } 00078 00079 static vbi_bool 00080 convert (vbi_dvb_demux * dx, 00081 void * user_data, 00082 const vbi_sliced * sliced, 00083 unsigned int n_lines, 00084 int64_t pts) 00085 { 00086 vbi_bool success; 00087 ssize_t actual; 00088 00089 dx = dx; /* unused */ 00090 user_data = user_data; 00091 00092 pts &= ((int64_t) 1 << 33) - 1; 00093 00094 /* Handle PTS wrap-around. */ 00095 if (0 == last_pts) { 00096 last_pts = pts; 00097 } else if (pts < last_pts) { 00098 last_pts -= (int64_t) 1 << 33; 00099 } 00100 00101 while (pts - last_pts > 90000 / 25 * 3 / 2) { 00102 /* No data for this frame. */ 00103 00104 success = vbi_raw_video_image (image, image_size, &sp, 00105 0, 0, 0, pixel_mask, FALSE, 00106 NULL, /* n_lines */ 0); 00107 assert (success); 00108 00109 raw_test (NULL, 0); 00110 00111 actual = write (STDOUT_FILENO, image, image_size); 00112 assert (actual == (ssize_t) image_size); 00113 00114 last_pts += 90000 / 25; 00115 } 00116 00117 success = vbi_raw_video_image (image, image_size, &sp, 00118 /* blank_level: default */ 0, 00119 /* black_level: default */ 0, 00120 /* white_level: default */ 0, 00121 pixel_mask, 00122 /* swap_fields */ FALSE, 00123 sliced, n_lines); 00124 assert (success); 00125 00126 raw_test (sliced, n_lines); 00127 00128 actual = write (STDOUT_FILENO, image, image_size); 00129 assert (actual == (ssize_t) image_size); 00130 00131 last_pts = pts; 00132 00133 return TRUE; /* success */ 00134 } 00135 00136 static void 00137 mainloop (void) 00138 { 00139 while (1 == fread (pes_buffer, sizeof (pes_buffer), 1, stdin)) { 00140 vbi_bool success; 00141 00142 success = vbi_dvb_demux_feed (dvb, 00143 pes_buffer, 00144 sizeof (pes_buffer)); 00145 assert (success); 00146 } 00147 00148 fprintf (stderr, "End of stream.\n"); 00149 } 00150 00151 int 00152 main (void) 00153 { 00154 if (isatty (STDIN_FILENO)) { 00155 fprintf (stderr, "No DVB PES on standard input.\n"); 00156 exit (EXIT_FAILURE); 00157 } 00158 00159 if (isatty (STDOUT_FILENO)) { 00160 fprintf (stderr, "Output is binary image data. Pipe to " 00161 "another tool or redirect to a file.\n"); 00162 exit (EXIT_FAILURE); 00163 } 00164 00165 /* Helps debugging. */ 00166 vbi_set_log_fn ((VBI_LOG_NOTICE | 00167 VBI_LOG_WARNING | 00168 VBI_LOG_ERROR), 00169 vbi_log_on_stderr, 00170 /* user_data */ NULL); 00171 00172 dvb = vbi_dvb_pes_demux_new (convert, /* user_data */ NULL); 00173 assert (NULL != dvb); 00174 00175 memset (&sp, 0, sizeof (sp)); 00176 00177 #if 1 00178 /* ITU BT.601 YUYV. */ 00179 00180 sp.scanning = 625; /* PAL/SECAM */ 00181 sp.sampling_format = VBI_PIXFMT_YUYV; 00182 sp.sampling_rate = 13.5e6; 00183 sp.bytes_per_line = 720 * 2; /* 2 bpp */ 00184 sp.offset = 9.5e-6 * 13.5e6; 00185 sp.start[0] = 6; 00186 sp.count[0] = 17; 00187 sp.start[1] = 319; 00188 sp.count[1] = 17; 00189 sp.interlaced = TRUE; 00190 sp.synchronous = TRUE; 00191 00192 /* Other bytes are left unmodified. */ 00193 pixel_mask = 0x000000FF; /* 0xAAVVUUYY */ 00194 #else 00195 /* PAL square pixels BGRA32. */ 00196 00197 sp.scanning = 625; /* PAL/SECAM */ 00198 sp.sampling_format = VBI_PIXFMT_BGRA32_LE; 00199 sp.sampling_rate = 14.75e6; 00200 sp.bytes_per_line = 768 * 4; /* 4 bpp */ 00201 sp.offset = 10.2e-6 * 14.75e6; 00202 sp.start[0] = 6; 00203 sp.count[0] = 17; 00204 sp.start[1] = 319; 00205 sp.count[1] = 17; 00206 sp.interlaced = TRUE; 00207 sp.synchronous = TRUE; 00208 00209 pixel_mask = 0x0000FF00; /* 0xAABBGGRR */ 00210 #endif 00211 00212 image_size = (sp.count[0] + sp.count[1]) * sp.bytes_per_line; 00213 image = malloc (image_size); 00214 assert (NULL != image); 00215 00216 if (VBI_PIXFMT_YUYV == sp.sampling_format) { 00217 /* Reset Cb/Cr bytes. */ 00218 memset (image, 0x80, image_size); 00219 } else { 00220 memset (image, 0x00, image_size); 00221 } 00222 00223 /* To verify the generated raw VBI data we feed it back 00224 into a decoder and compare the sliced VBI data. */ 00225 00226 vbi_raw_decoder_init (&rd); 00227 00228 rd.scanning = sp.scanning; 00229 rd.sampling_format = sp.sampling_format; 00230 rd.sampling_rate = sp.sampling_rate; 00231 rd.bytes_per_line = sp.bytes_per_line; 00232 rd.offset = sp.offset; 00233 rd.start[0] = sp.start[0]; 00234 rd.start[1] = sp.start[1]; 00235 rd.count[0] = sp.count[0]; 00236 rd.count[1] = sp.count[1]; 00237 rd.interlaced = sp.interlaced; 00238 rd.synchronous = sp.synchronous; 00239 00240 /* Strict 0 because the function would consider the 00241 square pixel timing too tight to reliably decode 00242 Teletext. */ 00243 vbi_raw_decoder_add_services (&rd, 00244 (VBI_SLICED_TELETEXT_B | 00245 VBI_SLICED_VPS | 00246 VBI_SLICED_CAPTION_625), 00247 /* strict */ 0); 00248 00249 mainloop (); 00250 00251 vbi_dvb_demux_delete (dvb); 00252 00253 exit (EXIT_SUCCESS); 00254 00255 return 0; 00256 }