00001 /* 00002 * libzvbi raw VBI output example. 00003 * 00004 * Copyright (C) 2006 Michael H. Schimek 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 */ 00020 00021 /* $Id: rawout.c,v 1.5 2006/10/27 04:52:08 mschimek Exp $ */ 00022 00023 /* This example shows how to convert VBI data in a DVB PES stream 00024 to raw VBI data. 00025 00026 gcc -o rawout rawout.c `pkg-config zvbi-0.2 --cflags --libs` 00027 00028 ./rawout <pes | mplayer - -rawvideo on:w=720:h=34:format=0x32595559 */ 00029 00030 #undef NDEBUG 00031 #include <assert.h> 00032 #include <stdio.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <unistd.h> 00036 00037 #include <libzvbi.h> 00038 00039 static vbi_dvb_demux * dvb; 00040 static uint8_t pes_buffer[2048]; 00041 static vbi_sampling_par sp; 00042 static uint8_t * image; 00043 static unsigned int image_size; 00044 static unsigned int pixel_mask; 00045 static int64_t last_pts; 00046 static vbi_raw_decoder rd; 00047 00048 static void 00049 raw_test (const vbi_sliced * expect_sliced, 00050 unsigned int expect_n_lines) 00051 { 00052 vbi_sliced sliced[50]; 00053 unsigned int n_lines; 00054 unsigned int i; 00055 00056 n_lines = vbi_raw_decode (&rd, image, sliced); 00057 assert (n_lines == expect_n_lines); 00058 00059 for (i = 0; i < n_lines; ++i) { 00060 unsigned int payload; 00061 00062 assert (sliced[i].id == expect_sliced[i].id); 00063 assert (sliced[i].line == expect_sliced[i].line); 00064 00065 payload = (vbi_sliced_payload_bits (sliced[i].id) + 7) / 8; 00066 assert (0 == memcmp (sliced[i].data, 00067 expect_sliced[i].data, 00068 payload)); 00069 } 00070 } 00071 00072 static vbi_bool 00073 convert (vbi_dvb_demux * dx, 00074 void * user_data, 00075 const vbi_sliced * sliced, 00076 unsigned int n_lines, 00077 int64_t pts) 00078 { 00079 vbi_bool success; 00080 ssize_t actual; 00081 00082 dx = dx; /* unused */ 00083 user_data = user_data; 00084 00085 pts &= ((int64_t) 1 << 33) - 1; 00086 00087 /* Handle PTS wrap-around. */ 00088 if (0 == last_pts) { 00089 last_pts = pts; 00090 } else if (pts < last_pts) { 00091 last_pts -= (int64_t) 1 << 33; 00092 } 00093 00094 while (pts - last_pts > 90000 / 25 * 3 / 2) { 00095 /* No data for this frame. */ 00096 00097 success = vbi_raw_video_image (image, image_size, &sp, 00098 0, 0, 0, pixel_mask, FALSE, 00099 NULL, /* n_lines */ 0); 00100 assert (success); 00101 00102 raw_test (NULL, 0); 00103 00104 actual = write (STDOUT_FILENO, image, image_size); 00105 assert (actual == (ssize_t) image_size); 00106 00107 last_pts += 90000 / 25; 00108 } 00109 00110 success = vbi_raw_video_image (image, image_size, &sp, 00111 /* blank_level: default */ 0, 00112 /* black_level: default */ 0, 00113 /* white_level: default */ 0, 00114 pixel_mask, 00115 /* swap_fields */ FALSE, 00116 sliced, n_lines); 00117 assert (success); 00118 00119 raw_test (sliced, n_lines); 00120 00121 actual = write (STDOUT_FILENO, image, image_size); 00122 assert (actual == (ssize_t) image_size); 00123 00124 last_pts = pts; 00125 00126 return TRUE; /* success */ 00127 } 00128 00129 static void 00130 mainloop (void) 00131 { 00132 while (1 == fread (pes_buffer, sizeof (pes_buffer), 1, stdin)) { 00133 vbi_bool success; 00134 00135 success = vbi_dvb_demux_feed (dvb, 00136 pes_buffer, 00137 sizeof (pes_buffer)); 00138 assert (success); 00139 } 00140 00141 fprintf (stderr, "End of stream.\n"); 00142 } 00143 00144 int 00145 main (void) 00146 { 00147 if (isatty (STDIN_FILENO)) { 00148 fprintf (stderr, "No DVB PES on standard input.\n"); 00149 exit (EXIT_FAILURE); 00150 } 00151 00152 if (isatty (STDOUT_FILENO)) { 00153 fprintf (stderr, "Output is binary image data. Pipe to " 00154 "another tool or redirect to a file.\n"); 00155 exit (EXIT_FAILURE); 00156 } 00157 00158 /* Helps debugging. */ 00159 vbi_set_log_fn ((VBI_LOG_NOTICE | 00160 VBI_LOG_WARNING | 00161 VBI_LOG_ERROR), 00162 vbi_log_on_stderr, 00163 /* user_data */ NULL); 00164 00165 dvb = vbi_dvb_pes_demux_new (convert, /* user_data */ NULL); 00166 assert (NULL != dvb); 00167 00168 memset (&sp, 0, sizeof (sp)); 00169 00170 #if 1 00171 /* ITU BT.601 YUYV. */ 00172 00173 sp.scanning = 625; /* PAL/SECAM */ 00174 sp.sampling_format = VBI_PIXFMT_YUYV; 00175 sp.sampling_rate = 13.5e6; 00176 sp.bytes_per_line = 720 * 2; /* 2 bpp */ 00177 sp.offset = 9.5e-6 * 13.5e6; 00178 sp.start[0] = 6; 00179 sp.count[0] = 17; 00180 sp.start[1] = 319; 00181 sp.count[1] = 17; 00182 sp.interlaced = TRUE; 00183 sp.synchronous = TRUE; 00184 00185 /* Other bytes are left unmodified. */ 00186 pixel_mask = 0x000000FF; /* 0xAAVVUUYY */ 00187 #else 00188 /* PAL square pixels BGRA32. */ 00189 00190 sp.scanning = 625; /* PAL/SECAM */ 00191 sp.sampling_format = VBI_PIXFMT_BGRA32_LE; 00192 sp.sampling_rate = 14.75e6; 00193 sp.bytes_per_line = 768 * 4; /* 4 bpp */ 00194 sp.offset = 10.2e-6 * 14.75e6; 00195 sp.start[0] = 6; 00196 sp.count[0] = 17; 00197 sp.start[1] = 319; 00198 sp.count[1] = 17; 00199 sp.interlaced = TRUE; 00200 sp.synchronous = TRUE; 00201 00202 pixel_mask = 0x0000FF00; /* 0xAABBGGRR */ 00203 #endif 00204 00205 image_size = (sp.count[0] + sp.count[1]) * sp.bytes_per_line; 00206 image = malloc (image_size); 00207 assert (NULL != image); 00208 00209 if (VBI_PIXFMT_YUYV == sp.sampling_format) { 00210 /* Reset Cb/Cr bytes. */ 00211 memset (image, 0x80, image_size); 00212 } else { 00213 memset (image, 0x00, image_size); 00214 } 00215 00216 /* To verify the generated raw VBI data we feed it back 00217 into a decoder and compare the sliced VBI data. */ 00218 00219 vbi_raw_decoder_init (&rd); 00220 00221 rd.scanning = sp.scanning; 00222 rd.sampling_format = sp.sampling_format; 00223 rd.sampling_rate = sp.sampling_rate; 00224 rd.bytes_per_line = sp.bytes_per_line; 00225 rd.offset = sp.offset; 00226 rd.start[0] = sp.start[0]; 00227 rd.start[1] = sp.start[1]; 00228 rd.count[0] = sp.count[0]; 00229 rd.count[1] = sp.count[1]; 00230 rd.interlaced = sp.interlaced; 00231 rd.synchronous = sp.synchronous; 00232 00233 /* Strict 0 because the function would consider the 00234 square pixel timing too tight to reliably decode 00235 Teletext. */ 00236 vbi_raw_decoder_add_services (&rd, 00237 (VBI_SLICED_TELETEXT_B | 00238 VBI_SLICED_VPS | 00239 VBI_SLICED_CAPTION_625), 00240 /* strict */ 0); 00241 00242 mainloop (); 00243 00244 vbi_dvb_demux_delete (dvb); 00245 00246 exit (EXIT_SUCCESS); 00247 00248 return 0; 00249 }