~ubuntu-branches/ubuntu/gutsy/amsn/gutsy

« back to all changes in this revision

Viewing changes to utils/linux/capture/libng/parse-dvb.c

  • Committer: Bazaar Package Importer
  • Author(s): Theodore Karkoulis
  • Date: 2006-01-04 15:26:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104152602-ipe1yg00rl3nlklv
Tags: 0.95-1
New Upstream Release (closes: #345052, #278575).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * parse various TV stuff out of DVB TS streams.
 
3
 *
 
4
 */
 
5
#include <stdio.h>
 
6
#include <stdlib.h>
 
7
#include <unistd.h>
 
8
#include <string.h>
 
9
#include <ctype.h>
 
10
#include <errno.h>
 
11
#include <iconv.h>
 
12
 
 
13
#include "grab-ng.h"
 
14
#include "parse-mpeg.h"
 
15
 
 
16
/* ----------------------------------------------------------------------- */
 
17
 
 
18
static unsigned int unbcd(unsigned int bcd)
 
19
{
 
20
    unsigned int factor = 1;
 
21
    unsigned int ret = 0;
 
22
    unsigned int digit;
 
23
 
 
24
    while (bcd) {
 
25
        digit   = bcd & 0x0f;
 
26
        ret    += digit * factor;
 
27
        bcd    /= 16;
 
28
        factor *= 10;
 
29
    }
 
30
    return ret;
 
31
}
 
32
 
 
33
static int iconv_string(char *from, char *to,
 
34
                        char *src, size_t len,
 
35
                        char *dst, size_t max)
 
36
{
 
37
    size_t ilen = (-1 != len) ? len : strlen(src);
 
38
    size_t olen = max-1;
 
39
    iconv_t ic;
 
40
 
 
41
    ic = iconv_open(to,from);
 
42
    if (NULL == ic)
 
43
        return 0;
 
44
 
 
45
    while (ilen > 0) {
 
46
        if (-1 == iconv(ic,&src,&ilen,&dst,&olen)) {
 
47
            /* skip + quote broken byte unless we are out of space */
 
48
            if (E2BIG == errno)
 
49
                break;
 
50
            if (olen < 4)
 
51
                break;
 
52
            sprintf(dst,"\\x%02x",(int)(unsigned char)src[0]);
 
53
            src  += 1;
 
54
            dst  += 4;
 
55
            ilen -= 1;
 
56
            olen -= 4;
 
57
        }
 
58
    }
 
59
    dst[0] = 0;
 
60
    iconv_close(ic);
 
61
    return max-1 - olen;
 
62
}
 
63
 
 
64
static int handle_control_8(unsigned char *src,  int slen,
 
65
                            unsigned char *dest, int dlen)
 
66
{
 
67
    int s,d;
 
68
 
 
69
    for (s = 0, d = 0; s < slen && d < dlen;) {
 
70
        if (src[s] >= 0x80  &&  src[s] <= 0x9f) {
 
71
            switch (src[s]) {
 
72
            case 0x86: /* <em>  */
 
73
            case 0x87: /* </em> */
 
74
                s++;
 
75
                break;
 
76
            case 0x1a: /* ^Z    */
 
77
                dest[d++] = ' ';
 
78
                s++;
 
79
                break;
 
80
            case 0x8a: /* <br>  */
 
81
                dest[d++] = '\n';
 
82
                s++;
 
83
                break;
 
84
            default:
 
85
                s++;
 
86
            }
 
87
        } else {
 
88
            dest[d++] = src[s++];
 
89
        }
 
90
    }
 
91
    return d;
 
92
}
 
93
 
 
94
void mpeg_parse_psi_string(unsigned char *src, int slen,
 
95
                           unsigned char *dest, int dlen)
 
96
{
 
97
    unsigned char *tmp;
 
98
    int tlen,ch = 0;
 
99
 
 
100
    if (src[0] < 0x20) {
 
101
        ch = src[0];
 
102
        src++;
 
103
        slen--;
 
104
    }
 
105
 
 
106
    memset(dest,0,dlen);
 
107
    if (ch < 0x10) {
 
108
        /* 8bit charset */
 
109
        tmp = malloc(slen);
 
110
        tlen = handle_control_8(src, slen, tmp, slen);
 
111
        iconv_string(psi_charset[ch], "UTF-8", tmp, tlen, dest, dlen);
 
112
        free(tmp);
 
113
    } else {
 
114
        /* 16bit charset */
 
115
        iconv_string(psi_charset[ch], "UTF-8", src, slen, dest, dlen);
 
116
    }
 
117
}
 
118
 
 
119
static void parse_nit_desc_1(unsigned char *desc, int dlen,
 
120
                             char *dest, int max)
 
121
{
 
122
    int i,t,l;
 
123
 
 
124
    for (i = 0; i < dlen; i += desc[i+1] +2) {
 
125
        t = desc[i];
 
126
        l = desc[i+1];
 
127
 
 
128
        switch (t) {
 
129
        case 0x40:
 
130
            mpeg_parse_psi_string(desc+i+2,l,dest,max);
 
131
            break;
 
132
        }
 
133
    }
 
134
}
 
135
 
 
136
static void parse_nit_desc_2(unsigned char *desc, int dlen,
 
137
                             struct psi_stream *stream)
 
138
{
 
139
    static char *bw[4] = {
 
140
        [ 0 ] = "8",
 
141
        [ 1 ] = "7",
 
142
        [ 2 ] = "6",
 
143
    };
 
144
    static char *co_t[4] = {
 
145
        [ 0 ] = "0",
 
146
        [ 1 ] = "16",
 
147
        [ 2 ] = "64",
 
148
    };
 
149
    static char *co_c[16] = {
 
150
        [ 0 ] = "0",
 
151
        [ 1 ] = "16",
 
152
        [ 2 ] = "32",
 
153
        [ 3 ] = "64",
 
154
        [ 4 ] = "128",
 
155
        [ 5 ] = "256",
 
156
    };
 
157
    static char *hi[4] = {
 
158
        [ 0 ] = "0",
 
159
        [ 1 ] = "1",
 
160
        [ 2 ] = "2",
 
161
        [ 3 ] = "4",
 
162
    };
 
163
    static char *ra_t[8] = {
 
164
        [ 0 ] = "12",
 
165
        [ 1 ] = "23",
 
166
        [ 2 ] = "34",
 
167
        [ 3 ] = "56",
 
168
        [ 4 ] = "78",
 
169
    };
 
170
    static char *ra_sc[8] = {
 
171
        [ 1 ] = "12",
 
172
        [ 2 ] = "23",
 
173
        [ 3 ] = "34",
 
174
        [ 4 ] = "56",
 
175
        [ 5 ] = "78",
 
176
    };
 
177
    static char *gu[4] = {
 
178
        [ 0 ] = "32",
 
179
        [ 1 ] = "16",
 
180
        [ 2 ] = "8",
 
181
        [ 3 ] = "4",
 
182
    };
 
183
    static char *tr[2] = {
 
184
        [ 0 ] = "2",
 
185
        [ 1 ] = "8",
 
186
    };
 
187
    static char *po[4] = {
 
188
        [ 0 ] = "H",
 
189
        [ 1 ] = "V",
 
190
        [ 2 ] = "L",  // circular left
 
191
        [ 3 ] = "R",  // circular right
 
192
    };
 
193
    unsigned int freq,rate,fec;
 
194
    int i,t,l;
 
195
 
 
196
    for (i = 0; i < dlen; i += desc[i+1] +2) {
 
197
        t = desc[i];
 
198
        l = desc[i+1];
 
199
 
 
200
        switch (t) {
 
201
        case 0x43: /* dvb-s */
 
202
            freq = mpeg_getbits(desc+i+2,  0, 32);
 
203
            rate = mpeg_getbits(desc+i+2, 56, 28);
 
204
            fec  = mpeg_getbits(desc+i+2, 85,  3);
 
205
            stream->frequency     = unbcd(freq)    * 10;
 
206
            stream->symbol_rate   = unbcd(rate*16) * 10;
 
207
            stream->fec_inner     = ra_sc[fec];
 
208
            stream->polarization  = po[   mpeg_getbits(desc+i+2, 49, 2) ];
 
209
            break;
 
210
        case 0x44: /* dvb-c */
 
211
            freq = mpeg_getbits(desc+i+2,  0, 32);
 
212
            rate = mpeg_getbits(desc+i+2, 56, 28);
 
213
            fec  = mpeg_getbits(desc+i+2, 85,  3);
 
214
            stream->frequency     = unbcd(freq)    * 100;
 
215
            stream->symbol_rate   = unbcd(rate*16) * 10;
 
216
            stream->fec_inner     = ra_sc[fec];
 
217
            stream->constellation = co_c[ mpeg_getbits(desc+i+2, 52, 4) ];
 
218
            break;
 
219
        case 0x5a: /* dvb-t */
 
220
            stream->frequency     = mpeg_getbits(desc+i+2,  0, 32) * 10;
 
221
            stream->bandwidth     = bw[   mpeg_getbits(desc+i+2, 33, 2) ];
 
222
            stream->constellation = co_t[ mpeg_getbits(desc+i+2, 40, 2) ];
 
223
            stream->hierarchy     = hi[   mpeg_getbits(desc+i+2, 43, 2) ];
 
224
            stream->code_rate_hp  = ra_t[ mpeg_getbits(desc+i+2, 45, 3) ];
 
225
            stream->code_rate_lp  = ra_t[ mpeg_getbits(desc+i+2, 48, 3) ];
 
226
            stream->guard         = gu[   mpeg_getbits(desc+i+2, 51, 2) ];
 
227
            stream->transmission  = tr[   mpeg_getbits(desc+i+2, 54, 1) ];
 
228
            break;
 
229
        }
 
230
    }
 
231
    return;
 
232
}
 
233
 
 
234
static void parse_sdt_desc(unsigned char *desc, int dlen,
 
235
                           struct psi_program *pr)
 
236
{
 
237
    int i,t,l;
 
238
    char *name,*net;
 
239
 
 
240
    for (i = 0; i < dlen; i += desc[i+1] +2) {
 
241
        t = desc[i];
 
242
        l = desc[i+1];
 
243
 
 
244
        switch (t) {
 
245
        case 0x48:
 
246
            pr->type = desc[i+2];
 
247
            pr->updated = 1;
 
248
            net = desc + i+3;
 
249
            name = net + net[0] + 1;
 
250
            mpeg_parse_psi_string(net+1,  net[0],  pr->net,  sizeof(pr->net));
 
251
            mpeg_parse_psi_string(name+1, name[0], pr->name, sizeof(pr->name));
 
252
            break;
 
253
        }
 
254
    }
 
255
}
 
256
 
 
257
/* ----------------------------------------------------------------------- */
 
258
 
 
259
int mpeg_parse_psi_sdt(struct psi_info *info, unsigned char *data, int verbose)
 
260
{
 
261
    static const char *running[] = {
 
262
        [ 0       ] = "undefined",
 
263
        [ 1       ] = "not running",
 
264
        [ 2       ] = "starts soon",
 
265
        [ 3       ] = "pausing",
 
266
        [ 4       ] = "running",
 
267
        [ 5 ... 8 ] = "reserved",
 
268
    };
 
269
    struct psi_program *pr;
 
270
    int tsid,pnr,version,current;
 
271
    int j,len,dlen,run,ca;
 
272
 
 
273
    len     = mpeg_getbits(data,12,12) + 3 - 4;
 
274
    tsid    = mpeg_getbits(data,24,16);
 
275
    version = mpeg_getbits(data,42,5);
 
276
    current = mpeg_getbits(data,47,1);
 
277
    if (!current)
 
278
        return len+4;
 
279
    if (info->tsid == tsid && info->sdt_version == version)
 
280
        return len+4;
 
281
    info->sdt_version = version;
 
282
 
 
283
    if (verbose)
 
284
        fprintf(stderr,
 
285
                "ts [sdt]: tsid %d ver %2d [%d/%d]\n",
 
286
                tsid, version,
 
287
                mpeg_getbits(data,48, 8),
 
288
                mpeg_getbits(data,56, 8));
 
289
    j = 88;
 
290
    while (j < len*8) {
 
291
        pnr  = mpeg_getbits(data,j,16);
 
292
        run  = mpeg_getbits(data,j+24,3);
 
293
        ca   = mpeg_getbits(data,j+27,1);
 
294
        dlen = mpeg_getbits(data,j+28,12);
 
295
        if (verbose > 1) {
 
296
            fprintf(stderr,"   pnr %3d ca %d %s #",
 
297
                    pnr, ca, running[run]);
 
298
            mpeg_dump_desc(data+j/8+5,dlen);
 
299
            fprintf(stderr,"\n");
 
300
        }
 
301
        pr = psi_program_get(info, tsid, pnr, 1);
 
302
        parse_sdt_desc(data+j/8+5,dlen,pr);
 
303
        pr->running = run;
 
304
        pr->ca      = ca;
 
305
        j += 40 + dlen*8;
 
306
    }
 
307
    if (verbose > 1)
 
308
        fprintf(stderr,"\n");
 
309
    return len+4;
 
310
}
 
311
 
 
312
int mpeg_parse_psi_nit(struct psi_info *info, unsigned char *data, int verbose)
 
313
{
 
314
    struct psi_stream *stream;
 
315
    char network[PSI_STR_MAX] = "";
 
316
    int id,version,current,len;
 
317
    int j,dlen,tsid;
 
318
 
 
319
    len     = mpeg_getbits(data,12,12) + 3 - 4;
 
320
    id      = mpeg_getbits(data,24,16);
 
321
    version = mpeg_getbits(data,42,5);
 
322
    current = mpeg_getbits(data,47,1);
 
323
    if (!current)
 
324
        return len+4;
 
325
    if (0 /* info->id == id */ && info->nit_version == version)
 
326
        return len+4;
 
327
    info->nit_version = version;
 
328
 
 
329
    j = 80;
 
330
    dlen = mpeg_getbits(data,68,12);
 
331
    parse_nit_desc_1(data + j/8, dlen, network, sizeof(network));
 
332
    if (verbose) {
 
333
        fprintf(stderr,
 
334
                "ts [nit]: id %3d ver %2d [%d/%d] #",
 
335
                id, version,
 
336
                mpeg_getbits(data,48, 8),
 
337
                mpeg_getbits(data,56, 8));
 
338
        mpeg_dump_desc(data + j/8, dlen);
 
339
        fprintf(stderr,"\n");
 
340
    }
 
341
    j += 16 + 8*dlen;
 
342
 
 
343
    while (j < len*8) {
 
344
        tsid = mpeg_getbits(data,j,16);
 
345
        dlen = mpeg_getbits(data,j+36,12);
 
346
        j += 48;
 
347
        stream = psi_stream_get(info, tsid, 1);
 
348
        stream->updated = 1;
 
349
        if (network)
 
350
            strcpy(stream->net, network);
 
351
        parse_nit_desc_2(data + j/8, dlen, stream);
 
352
        if (verbose > 1) {
 
353
            fprintf(stderr,"   tsid %3d #", tsid);
 
354
            mpeg_dump_desc(data + j/8, dlen);
 
355
            fprintf(stderr,"\n");
 
356
        }
 
357
        j += 8*dlen;
 
358
    }
 
359
    
 
360
    if (verbose > 1)
 
361
        fprintf(stderr,"\n");
 
362
    return len+4;
 
363
}