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.4 2006/05/26 00:45:16 mschimek Exp $ */ 00022 00023 /* This example shows how to convert VBI data in a DVB PES to raw 00024 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, no warning */ 00083 user_data = user_data; 00084 00085 pts &= ((int64_t) 1 << 33) - 1; 00086 00087 if (0 == last_pts) { 00088 last_pts = pts; 00089 } else if (pts < last_pts) { 00090 last_pts -= (int64_t) 1 << 33; 00091 } 00092 00093 while (pts - last_pts > 90000 / 25 * 3 / 2) { 00094 /* No data for this frame. */ 00095 00096 success = vbi_raw_video_image (image, image_size, &sp, 00097 0, 0, 0, pixel_mask, FALSE, 00098 NULL, /* n_lines */ 0); 00099 assert (success); 00100 00101 raw_test (NULL, 0); 00102 00103 actual = write (STDOUT_FILENO, image, image_size); 00104 assert (actual == (ssize_t) image_size); 00105 00106 last_pts += 90000 / 25; 00107 } 00108 00109 success = vbi_raw_video_image (image, image_size, &sp, 00110 /* blank_level: default */ 0, 00111 /* black_level: default */ 0, 00112 /* white_level: default */ 0, 00113 pixel_mask, 00114 /* swap_fields */ FALSE, 00115 sliced, n_lines); 00116 assert (success); 00117 00118 raw_test (sliced, n_lines); 00119 00120 actual = write (STDOUT_FILENO, image, image_size); 00121 assert (actual == (ssize_t) image_size); 00122 00123 last_pts = pts; 00124 00125 return TRUE; /* success */ 00126 } 00127 00128 static void 00129 mainloop (void) 00130 { 00131 while (1 == fread (pes_buffer, sizeof (pes_buffer), 1, stdin)) { 00132 vbi_bool success; 00133 00134 success = vbi_dvb_demux_feed (dvb, 00135 pes_buffer, 00136 sizeof (pes_buffer)); 00137 assert (success); 00138 } 00139 00140 fprintf (stderr, "End of stream.\n"); 00141 } 00142 00143 int 00144 main (void) 00145 { 00146 if (isatty (STDIN_FILENO)) { 00147 fprintf (stderr, "No DVB PES on standard input.\n"); 00148 exit (EXIT_FAILURE); 00149 } 00150 00151 if (isatty (STDOUT_FILENO)) { 00152 fprintf (stderr, "Output is binary image data. Pipe to " 00153 "another tool or redirect to a file.\n"); 00154 exit (EXIT_FAILURE); 00155 } 00156 00157 /* Helps debugging. */ 00158 vbi_set_log_fn (/* mask */ VBI_LOG_NOTICE * 2 - 1, 00159 vbi_log_on_stderr, 00160 /* user_data */ NULL); 00161 00162 dvb = vbi_dvb_pes_demux_new (convert, /* user_data */ NULL); 00163 assert (NULL != dvb); 00164 00165 memset (&sp, 0, sizeof (sp)); 00166 00167 #if 1 00168 /* ITU BT.601 YUYV. */ 00169 00170 sp.scanning = 625; /* PAL/SECAM */ 00171 sp.sampling_format = VBI_PIXFMT_YUYV; 00172 sp.sampling_rate = 13.5e6; 00173 sp.bytes_per_line = 720 * 2; /* 2 bpp */ 00174 sp.offset = 9.5e-6 * 13.5e6; 00175 sp.start[0] = 6; 00176 sp.count[0] = 17; 00177 sp.start[1] = 319; 00178 sp.count[1] = 17; 00179 sp.interlaced = TRUE; 00180 sp.synchronous = TRUE; 00181 00182 pixel_mask = 0x000000FF; /* 0xAAVVUUYY */ 00183 #else 00184 /* PAL square pixels BGRA32. */ 00185 00186 sp.scanning = 625; /* PAL/SECAM */ 00187 sp.sampling_format = VBI_PIXFMT_BGRA32_LE; 00188 sp.sampling_rate = 14.75e6; 00189 sp.bytes_per_line = 768 * 4; /* 4 bpp */ 00190 sp.offset = 10.2e-6 * 14.75e6; 00191 sp.start[0] = 6; 00192 sp.count[0] = 17; 00193 sp.start[1] = 319; 00194 sp.count[1] = 17; 00195 sp.interlaced = TRUE; 00196 sp.synchronous = TRUE; 00197 00198 pixel_mask = 0x0000FF00; /* 0xAABBGGRR */ 00199 #endif 00200 00201 image_size = (sp.count[0] + sp.count[1]) * sp.bytes_per_line; 00202 image = malloc (image_size); 00203 assert (NULL != image); 00204 00205 if (VBI_PIXFMT_YUYV == sp.sampling_format) { 00206 /* Reset U/V bytes. */ 00207 memset (image, 0x80, image_size); 00208 } else { 00209 memset (image, 0x00, image_size); 00210 } 00211 00212 /* Raw image test. */ 00213 00214 vbi_raw_decoder_init (&rd); 00215 00216 rd.scanning = sp.scanning; 00217 rd.sampling_format = sp.sampling_format; 00218 rd.sampling_rate = sp.sampling_rate; 00219 rd.bytes_per_line = sp.bytes_per_line; 00220 rd.offset = sp.offset; 00221 rd.start[0] = sp.start[0]; 00222 rd.start[1] = sp.start[1]; 00223 rd.count[0] = sp.count[0]; 00224 rd.count[1] = sp.count[1]; 00225 rd.interlaced = sp.interlaced; 00226 rd.synchronous = sp.synchronous; 00227 00228 /* Strict 0 because the function would rule out Teletext 00229 with the tight square pixel timing. */ 00230 vbi_raw_decoder_add_services (&rd, 00231 (VBI_SLICED_TELETEXT_B | 00232 VBI_SLICED_VPS | 00233 VBI_SLICED_CAPTION_625), 00234 /* strict */ 0); 00235 00236 mainloop (); 00237 00238 vbi_dvb_demux_delete (dvb); 00239 00240 exit (EXIT_SUCCESS); 00241 00242 return 0; 00243 }