summaryrefslogtreecommitdiff
path: root/examples/rawout.c (plain)
blob: b8dcecfa98f294af265fa179dc74ed4c49abd3f7
1/*
2 * libzvbi raw VBI output example
3 *
4 * Copyright (C) 2006 Michael H. Schimek
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28/* $Id: rawout.c,v 1.8 2008/02/19 00:52:04 mschimek Exp $ */
29
30/* This example shows how to convert VBI data in a DVB PES stream
31 to raw VBI data.
32
33 gcc -o rawout rawout.c `pkg-config zvbi-0.2 --cflags --libs`
34
35 ./rawout <pes | mplayer - -rawvideo on:w=720:h=34:format=0x32595559 */
36
37#undef NDEBUG
38#include <assert.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <unistd.h>
43
44#include <libzvbi.h>
45
46static vbi_dvb_demux * dvb;
47static uint8_t pes_buffer[2048];
48static vbi_sampling_par sp;
49static uint8_t * image;
50static unsigned int image_size;
51static unsigned int pixel_mask;
52static int64_t last_pts;
53static vbi_raw_decoder rd;
54
55static void
56raw_test (const vbi_sliced * expect_sliced,
57 unsigned int expect_n_lines)
58{
59 vbi_sliced sliced[50];
60 unsigned int n_lines;
61 unsigned int i;
62
63 n_lines = vbi_raw_decode (&rd, image, sliced);
64 assert (n_lines == expect_n_lines);
65
66 for (i = 0; i < n_lines; ++i) {
67 unsigned int payload;
68
69 assert (sliced[i].id == expect_sliced[i].id);
70 assert (sliced[i].line == expect_sliced[i].line);
71
72 payload = (vbi_sliced_payload_bits (sliced[i].id) + 7) / 8;
73 assert (0 == memcmp (sliced[i].data,
74 expect_sliced[i].data,
75 payload));
76 }
77}
78
79static vbi_bool
80convert (vbi_dvb_demux * dx,
81 void * user_data,
82 const vbi_sliced * sliced,
83 unsigned int n_lines,
84 int64_t pts)
85{
86 vbi_bool success;
87 ssize_t actual;
88
89 dx = dx; /* unused */
90 user_data = user_data;
91
92 pts &= ((int64_t) 1 << 33) - 1;
93
94 /* Handle PTS wrap-around. */
95 if (0 == last_pts) {
96 last_pts = pts;
97 } else if (pts < last_pts) {
98 last_pts -= (int64_t) 1 << 33;
99 }
100
101 while (pts - last_pts > 90000 / 25 * 3 / 2) {
102 /* No data for this frame. */
103
104 success = vbi_raw_video_image (image, image_size, &sp,
105 0, 0, 0, pixel_mask, FALSE,
106 NULL, /* n_lines */ 0);
107 assert (success);
108
109 raw_test (NULL, 0);
110
111 actual = write (STDOUT_FILENO, image, image_size);
112 assert (actual == (ssize_t) image_size);
113
114 last_pts += 90000 / 25;
115 }
116
117 success = vbi_raw_video_image (image, image_size, &sp,
118 /* blank_level: default */ 0,
119 /* black_level: default */ 0,
120 /* white_level: default */ 0,
121 pixel_mask,
122 /* swap_fields */ FALSE,
123 sliced, n_lines);
124 assert (success);
125
126 raw_test (sliced, n_lines);
127
128 actual = write (STDOUT_FILENO, image, image_size);
129 assert (actual == (ssize_t) image_size);
130
131 last_pts = pts;
132
133 return TRUE; /* success */
134}
135
136static void
137mainloop (void)
138{
139 while (1 == fread (pes_buffer, sizeof (pes_buffer), 1, stdin)) {
140 vbi_bool success;
141
142 success = vbi_dvb_demux_feed (dvb,
143 pes_buffer,
144 sizeof (pes_buffer));
145 assert (success);
146 }
147
148 fprintf (stderr, "End of stream.\n");
149}
150
151int
152main (void)
153{
154 if (isatty (STDIN_FILENO)) {
155 fprintf (stderr, "No DVB PES on standard input.\n");
156 exit (EXIT_FAILURE);
157 }
158
159 if (isatty (STDOUT_FILENO)) {
160 fprintf (stderr, "Output is binary image data. Pipe to "
161 "another tool or redirect to a file.\n");
162 exit (EXIT_FAILURE);
163 }
164
165 /* Helps debugging. */
166 vbi_set_log_fn ((VBI_LOG_NOTICE |
167 VBI_LOG_WARNING |
168 VBI_LOG_ERROR),
169 vbi_log_on_stderr,
170 /* user_data */ NULL);
171
172 dvb = vbi_dvb_pes_demux_new (convert, /* user_data */ NULL);
173 assert (NULL != dvb);
174
175 memset (&sp, 0, sizeof (sp));
176
177#if 1
178 /* ITU BT.601 YUYV. */
179
180 sp.scanning = 625; /* PAL/SECAM */
181 sp.sampling_format = VBI_PIXFMT_YUYV;
182 sp.sampling_rate = 13.5e6;
183 sp.bytes_per_line = 720 * 2; /* 2 bpp */
184 sp.offset = 9.5e-6 * 13.5e6;
185 sp.start[0] = 6;
186 sp.count[0] = 17;
187 sp.start[1] = 319;
188 sp.count[1] = 17;
189 sp.interlaced = TRUE;
190 sp.synchronous = TRUE;
191
192 /* Other bytes are left unmodified. */
193 pixel_mask = 0x000000FF; /* 0xAAVVUUYY */
194#else
195 /* PAL square pixels BGRA32. */
196
197 sp.scanning = 625; /* PAL/SECAM */
198 sp.sampling_format = VBI_PIXFMT_BGRA32_LE;
199 sp.sampling_rate = 14.75e6;
200 sp.bytes_per_line = 768 * 4; /* 4 bpp */
201 sp.offset = 10.2e-6 * 14.75e6;
202 sp.start[0] = 6;
203 sp.count[0] = 17;
204 sp.start[1] = 319;
205 sp.count[1] = 17;
206 sp.interlaced = TRUE;
207 sp.synchronous = TRUE;
208
209 pixel_mask = 0x0000FF00; /* 0xAABBGGRR */
210#endif
211
212 image_size = (sp.count[0] + sp.count[1]) * sp.bytes_per_line;
213 image = malloc (image_size);
214 assert (NULL != image);
215
216 if (VBI_PIXFMT_YUYV == sp.sampling_format) {
217 /* Reset Cb/Cr bytes. */
218 memset (image, 0x80, image_size);
219 } else {
220 memset (image, 0x00, image_size);
221 }
222
223 /* To verify the generated raw VBI data we feed it back
224 into a decoder and compare the sliced VBI data. */
225
226 vbi_raw_decoder_init (&rd);
227
228 rd.scanning = sp.scanning;
229 rd.sampling_format = sp.sampling_format;
230 rd.sampling_rate = sp.sampling_rate;
231 rd.bytes_per_line = sp.bytes_per_line;
232 rd.offset = sp.offset;
233 rd.start[0] = sp.start[0];
234 rd.start[1] = sp.start[1];
235 rd.count[0] = sp.count[0];
236 rd.count[1] = sp.count[1];
237 rd.interlaced = sp.interlaced;
238 rd.synchronous = sp.synchronous;
239
240 /* Strict 0 because the function would consider the
241 square pixel timing too tight to reliably decode
242 Teletext. */
243 vbi_raw_decoder_add_services (&rd,
244 (VBI_SLICED_TELETEXT_B |
245 VBI_SLICED_VPS |
246 VBI_SLICED_CAPTION_625),
247 /* strict */ 0);
248
249 mainloop ();
250
251 vbi_dvb_demux_delete (dvb);
252
253 exit (EXIT_SUCCESS);
254
255 return 0;
256}
257