close Warning: Can't use blame annotator:
No changeset 2 in the repository

source: svn/newcon3bcm2_21bu/nexus/utils/message.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 16.9 KB
RevLine 
1/******************************************************************************
2 *    (c)2008-2012 Broadcom Corporation
3 *
4 * This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 * and may only be used, duplicated, modified or distributed pursuant to the terms and
6 * conditions of a separate, written license agreement executed between you and Broadcom
7 * (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 * no license (express or implied), right to use, or waiver of any kind with respect to the
9 * Software, and Broadcom expressly reserves all rights in and to the Software and all
10 * intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 * HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 * NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 * Except as expressly set forth in the Authorized License,
15 *
16 * 1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 * secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 * and to use this information only in connection with your use of Broadcom integrated circuit products.
19 *
20 * 2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 * AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 * THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 * LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 * OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 * USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 * 3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 * LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 * EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 * USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 * THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 * ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 * LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 * ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: message.c $
39 * $brcm_Revision: 9 $
40 * $brcm_Date: 2/13/12 5:23p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/utils/message.c $
47 *
48 * 9   2/13/12 5:23p erickson
49 * SW7335-1216: add overflow callback, fix playback pid channel close
50 *
51 * 8   2/8/12 9:51a erickson
52 * SW7335-1216: do actual PMT filtering
53 *
54 * 7   1/24/12 1:10p erickson
55 * SW7425-2199: fix shutdown
56 *
57 * 6   7/11/11 1:13p erickson
58 * SW7335-1216: remove #if 0 around WaitForEvent
59 *
60 * 5   7/1/11 12:50p erickson
61 * SW7335-1216: use default maxContiguousMessageSize so example works with
62 *  SW filtering
63 *
64 * 4   12/8/09 3:00p gmohile
65 * SW7408-1 : Add support for platforms with no frontend
66 *
67 * 3   9/18/09 4:30p erickson
68 * SWDEPRECATED-3717: use NEXUS_MessageSettings.bufferSize
69 *
70 * 2   5/4/09 4:25p erickson
71 * PR54807: add basic psip support
72 *
73 * 1   5/4/09 2:38p erickson
74 * PR54807: added message util
75 *
76 * 7   4/13/09 3:31p erickson
77 * PR54058: remove NEXUS_PidChannelSettings.requireMessageBuffer
78 *
79 * 6   3/16/09 3:01p erickson
80 * PR35457: use app-allocated buffer as recommended in Nexus_Usage.pdf
81 *
82 * 5   7/18/08 11:31a jgarrett
83 * PR 44953: Removing -Wstrict-prototypes warnings
84 *
85 * 4   4/23/08 12:18p erickson
86 * PR35457: parse the PAT to make it a more complete example
87 *
88 * 3   2/25/08 9:34a jgarrett
89 * PR 39435: Fixing includes
90 *
91 * 2   1/24/08 12:52p vsilyaev
92 * PR 38682: fixed return type of NEXUS_Platform_GetStreamerInputBand
93 *
94 *****************************************************************************/
95#include "nexus_platform.h"
96#include "nexus_pid_channel.h"
97#include "nexus_parser_band.h"
98#include "nexus_message.h"
99#include "nexus_playback.h"
100#include "nexus_file.h"
101
102#include "bstd.h"
103#include "bkni.h"
104
105#include <stdio.h>
106#include <stdlib.h>
107#include <string.h>
108
109BDBG_MODULE(message);
110
111static struct {
112    NEXUS_PlaybackHandle playback;
113    NEXUS_PlaypumpHandle playpump;
114    NEXUS_FilePlayHandle file;
115    NEXUS_ParserBand parserBand;
116    BKNI_EventHandle event;
117} app;
118
119#define MAX_MESSAGE_FILTERS 100
120struct message_t {
121    unsigned short pid;
122    NEXUS_MessageHandle message;
123    NEXUS_PidChannelHandle pidChannel;
124} g_message[MAX_MESSAGE_FILTERS];
125
126static void message_callback(void *context, int param)
127{
128    BSTD_UNUSED(param);
129    BKNI_SetEvent((BKNI_EventHandle)context);
130}
131
132static void overflow_callback(void *context, int param)
133{
134    BSTD_UNUSED(context);
135    BDBG_WRN(("overflow on pid %#x", g_message[param].pid));
136}
137
138struct message_opts_t {
139    unsigned short pid;
140    unsigned buffer_size;
141    const char *filename;
142    bool hex;
143    bool ascii;
144    bool psi;
145    bool psip;
146    NEXUS_TransportType transportType;
147    NEXUS_TransportTimestampType tsTimestampType;
148    NEXUS_PlaybackLoopMode endOfStreamAction;
149};
150
151void cmdline_default_message_opts(struct message_opts_t *opts)
152{
153    BKNI_Memset(opts, 0, sizeof(*opts));
154    opts->buffer_size = 4096;
155    opts->transportType = NEXUS_TransportType_eTs;
156    opts->tsTimestampType = NEXUS_TransportTimestampType_eNone;
157    opts->endOfStreamAction = NEXUS_PlaybackLoopMode_eLoop;
158}
159
160static int add_message_filter(const struct message_opts_t *opts, unsigned short pid, const NEXUS_MessageFilter *pFilter)
161{
162    unsigned i;
163    NEXUS_MessageSettings settings;
164    NEXUS_MessageStartSettings startSettings;
165    NEXUS_Error rc;
166    struct message_t *msg = NULL;
167
168    for (i=0;i<MAX_MESSAGE_FILTERS;i++) {
169        if (!g_message[i].message) {
170            msg = &g_message[i];
171            break;
172        }
173    }
174    if (!msg) {
175        return -1;
176    }
177    msg->pid = pid;
178    if (app.playback) {
179        msg->pidChannel = NEXUS_Playback_OpenPidChannel(app.playback, pid, NULL);
180    }
181    else {
182        msg->pidChannel = NEXUS_PidChannel_Open(app.parserBand, pid, NULL);
183    }
184    BDBG_ASSERT(msg->pidChannel);
185
186    NEXUS_Message_GetDefaultSettings(&settings);
187    settings.dataReady.callback = message_callback;
188    settings.dataReady.context = app.event;
189    settings.overflow.callback = overflow_callback;
190    settings.overflow.param = i;
191    /* use default settings.maxContiguousMessageSize */
192    settings.bufferSize = opts->buffer_size;
193    msg->message = NEXUS_Message_Open(&settings);
194
195    NEXUS_Message_GetDefaultStartSettings(msg->message, &startSettings);
196    startSettings.pidChannel = msg->pidChannel;
197    if (pFilter) {
198        startSettings.filter = *pFilter;
199    }
200    rc = NEXUS_Message_Start(msg->message, &startSettings);
201    BDBG_ASSERT(!rc);
202   
203    return 0;
204}
205
206static void remove_message_filter(unsigned i)
207{
208    NEXUS_MessageHandle msg = g_message[i].message;
209    if (!msg) return;
210    g_message[i].message = NULL;
211    NEXUS_Message_Close(msg);
212}
213
214void print_usage(void)
215{
216    printf(
217    "Usage: nexus message [options] [pvrfile]\n"
218    "-buffer_size X   message capture buffer size in bytes\n"
219    "-pid X           PID to filter (default is 0)\n"
220    "-hex             print contents of all messages in hex\n"
221    "-ascii           print contents of all messages in ascii (useful for PSIP)\n"
222    "-psi             parse PSI tables\n"
223    "-psip            parse PSIP tables\n"
224    "\n"
225    "If pvrfile not given, streamer input will be parsed\n"
226    );
227}
228
229int cmdline_parse_message_opts(int argc, char **argv, struct message_opts_t *opts)
230{
231    int curarg = 1;
232
233    while (curarg < argc) {
234        if (!strcmp("--help", argv[curarg]) ||
235            !strcmp("-h", argv[curarg]) ||
236            !strcmp("-?", argv[curarg])) {
237            print_usage();
238            return 1;
239        }
240        else if (!strcmp("-buffer_size", argv[curarg]) && curarg+1 < argc) {
241            opts->buffer_size = atoi(argv[++curarg]);
242        }
243        else if (!strcmp("-pid", argv[curarg]) && curarg+1 < argc) {
244            opts->pid = strtoul(argv[++curarg], NULL, 0);
245        }
246        else if (!strcmp("-hex", argv[curarg])) {
247            opts->hex = true;
248        }
249        else if (!strcmp("-ascii", argv[curarg])) {
250            opts->ascii = true;
251        }
252        else if (!strcmp("-psi", argv[curarg])) {
253            opts->psi = true;
254            opts->pid = 0; /* PID for PAT */
255        }
256        else if (!strcmp("-psip", argv[curarg])) {
257            opts->psip = true;
258            opts->pid = 0x1ffb; /* PID for MGT */
259        }
260        else if (!opts->filename) {
261            opts->filename = argv[curarg];
262        }
263        else {
264            printf("Unknown param: %s\n", argv[curarg]);
265            return -1;
266        }
267        curarg++;
268    }
269    return 0;
270}
271
272int main(int argc, char **argv) {
273    struct message_opts_t opts;
274    NEXUS_Error rc;
275    unsigned count;
276    unsigned i;
277    NEXUS_PlatformSettings platformSettings;
278
279    cmdline_default_message_opts(&opts);
280    if (cmdline_parse_message_opts(argc, argv, &opts)) {
281        return 0;
282    }
283
284    NEXUS_Platform_GetDefaultSettings(&platformSettings);
285    platformSettings.openFrontend = false;
286    rc = NEXUS_Platform_Init(NULL);
287    if (rc) return -1;
288
289    if (opts.filename) {
290        NEXUS_PlaybackSettings playbackSettings;
291
292        app.playpump = NEXUS_Playpump_Open(0, NULL);
293        BDBG_ASSERT(app.playpump);
294        app.playback = NEXUS_Playback_Create();
295        BDBG_ASSERT(app.playback);
296
297        app.file = NEXUS_FilePlay_OpenPosix(opts.filename, NULL);
298        if (!app.file) {
299            fprintf(stderr, "can't open file:%s\n", opts.filename);
300            return -1;
301        }
302
303        NEXUS_Playback_GetSettings(app.playback, &playbackSettings);
304        playbackSettings.playpump = app.playpump;
305        playbackSettings.playpumpSettings.transportType = opts.transportType;
306        playbackSettings.playpumpSettings.timestamp.type = opts.tsTimestampType;
307        playbackSettings.endOfStreamAction = opts.endOfStreamAction;
308        rc = NEXUS_Playback_SetSettings(app.playback, &playbackSettings);
309        BDBG_ASSERT(!rc);
310
311        rc = NEXUS_Playback_Start(app.playback, app.file, NULL);
312        BDBG_ASSERT(!rc);
313    }
314#if NEXUS_NUM_PARSER_BANDS
315    else {
316        NEXUS_InputBand inputBand;
317        NEXUS_ParserBandSettings parserBandSettings;
318
319        app.parserBand = NEXUS_ParserBand_e0;
320        NEXUS_Platform_GetStreamerInputBand(0, &inputBand);
321
322        NEXUS_ParserBand_GetSettings(app.parserBand, &parserBandSettings);
323        parserBandSettings.sourceType = NEXUS_ParserBandSourceType_eInputBand;
324        parserBandSettings.sourceTypeSettings.inputBand = inputBand;
325        rc = NEXUS_ParserBand_SetSettings(app.parserBand, &parserBandSettings);
326        BDBG_ASSERT(!rc);
327    }
328#endif
329
330    BKNI_CreateEvent(&app.event);
331   
332    BDBG_WRN(("starting message filter"));
333
334    add_message_filter(&opts, opts.pid, NULL);
335
336    /* Read the PAT a few times */
337    for (count=0;;count++) {
338        const uint8_t *buffer;
339        size_t size;
340        unsigned programNum, message_length;
341
342        if (count == MAX_MESSAGE_FILTERS) {
343            count = 0;
344        }
345
346        if (!g_message[count].message) {
347            continue;
348        }
349
350        rc = NEXUS_Message_GetBuffer(g_message[count].message, (const void **)&buffer, &size);
351        BDBG_ASSERT(!rc);
352
353        if (!size) {
354            BERR_Code rc = BKNI_WaitForEvent(app.event, 5 * 1000); /* wait 5 seconds */
355            if (rc == NEXUS_TIMEOUT) {
356                BDBG_WRN(("timeout")); 
357                rc = -1; 
358                break;
359            }
360            BDBG_ASSERT(!rc);
361            continue;
362        }
363
364#define TS_READ_16( BUF ) ((uint16_t)((BUF)[0]<<8|(BUF)[1]))
365#define TS_PSI_GET_SECTION_LENGTH( BUF )    (uint16_t)(TS_READ_16( &(BUF)[1] ) & 0x0FFF)
366
367        /* We should always get whole PAT's because maxContiguousMessageSize is 4K */
368        message_length = TS_PSI_GET_SECTION_LENGTH(buffer) + 3;
369        BDBG_ASSERT(size >= (size_t)message_length);
370
371        if (opts.psi) {
372            if (buffer[0] == 0) {
373
374                /* Program Association Table */
375                printf("PAT: size=%d\n", message_length);
376                for (programNum=0;programNum<(unsigned)(TS_PSI_GET_SECTION_LENGTH(buffer)-7)/4;programNum++) {
377                    unsigned byteOffset = 8 + programNum*4;
378                    unsigned program = TS_READ_16( &buffer[byteOffset] );
379                    unsigned short pid = (uint16_t)(TS_READ_16( &buffer[byteOffset+2] ) & 0x1FFF);
380                    NEXUS_MessageFilter filter;
381                   
382                    printf("  program %#x: pid %#x\n", program, pid);
383                    NEXUS_Message_GetDefaultFilter(&filter);
384                    /* these fields must match */
385                    filter.mask[0] = 0x00;
386                    filter.mask[2] = 0x00;
387                    filter.mask[3] = 0x00;
388                    /* they must match these values */
389                    filter.coefficient[0] = 0x02;
390                    filter.coefficient[2] = (program & 0xFF00) >> 8;
391                    filter.coefficient[3] = program & 0xFF;
392                    add_message_filter(&opts, pid, &filter);
393                }
394                remove_message_filter(count);
395            }
396            else if (buffer[0] == 1) {
397                /* Conditional Access Table */
398                printf("CAT: size=%d\n", message_length);
399            }
400            else if (buffer[0] == 2) {
401                unsigned i, byteOffset;
402
403                /* Program Table */
404                printf("PMT: pid=%#x size=%d\n", g_message[count].pid, message_length);
405#if 0
406                for (i=0;i<message_length;i++) {
407                    printf("%02x ", buffer[i]);
408                }
409                printf("\n");
410#endif
411
412#define TS_PSI_LAST_SECTION_NUMBER_OFFSET   7
413#define TS_PSI_MAX_BYTE_OFFSET( buf )               (TS_PSI_GET_SECTION_LENGTH(buf) - 1)
414#define PROGRAM_INFO_LENGTH_OFFSET (TS_PSI_LAST_SECTION_NUMBER_OFFSET+3)
415#define PROGRAM_INFO_LENGTH(buf) (TS_READ_16(&buf[PROGRAM_INFO_LENGTH_OFFSET])&0xFFF)
416#define DESCRIPTOR_BASE(buf) (&buf[TS_PSI_LAST_SECTION_NUMBER_OFFSET+5])
417#define STREAM_BASE(buf) (TS_PSI_LAST_SECTION_NUMBER_OFFSET + 5 + PROGRAM_INFO_LENGTH(buf))
418
419                byteOffset = STREAM_BASE(buffer);
420
421                while (byteOffset < (unsigned)TS_PSI_MAX_BYTE_OFFSET(buffer) && byteOffset < message_length)
422                {
423                    printf("  stream_type 0x%02x, pid 0x%x\n",
424                        buffer[byteOffset], (uint16_t)(TS_READ_16( &buffer[byteOffset+1] ) & 0x1FFF));
425
426                    byteOffset += 5 + (TS_READ_16( &buffer[byteOffset+3] ) & 0xFFF);
427                    i++;
428                }
429                remove_message_filter(count);
430            }
431        }
432        else if (opts.psip) {
433            if (buffer[0] == 0xC7) {
434                printf("Master Guide Table (MGT)\n");
435
436                /* TODO: parse and filter PID's for EIT and ETT */
437            }
438            else if (buffer[0] == 0xC8) {
439                printf("Terrestrial Virtual Channel Table (VCT)\n");
440            }
441            else if (buffer[0] == 0xC9) {
442                printf("Cable Virtual Channel Table (CVCT)\n");
443            }
444            else if (buffer[0] == 0xCA) {
445                printf("Rating Region Table (RRT)\n");
446            }
447            else if (buffer[0] == 0xCB) {
448                printf("Event Information Table (EIT)\n");
449            }
450            else if (buffer[0] == 0xCC) {
451                printf("Extended Text Table (ETT)\n");
452            }
453            else if (buffer[0] == 0xCD) {
454                printf("System Time Table (STT)\n");
455            }
456        }
457        else {
458            printf("Found message: id=%d size=%d\n", buffer[0], message_length);
459        }
460
461        if (opts.hex) {
462            unsigned i;
463            for (i=0;i<message_length;i++) {
464                printf("%02x", buffer[i]);
465            }
466            printf("\n");
467        }
468        if (opts.ascii) {
469            unsigned i;
470            for (i=0;i<message_length;i++) {
471                printf("%c", buffer[i] < 32 ? '.':buffer[i]);
472            }
473            printf("\n");
474        }
475
476        if (g_message[count].message) {
477            /* only complete one message */
478            if (message_length % 4) {
479                message_length += 4 - (message_length % 4);
480            }
481            NEXUS_Message_ReadComplete(g_message[count].message, message_length);
482        }
483    }
484
485    for (i=0;i<MAX_MESSAGE_FILTERS;i++) {
486        remove_message_filter(i);
487        if (g_message[i].pidChannel) {
488            if (app.playback) {
489                NEXUS_Playback_ClosePidChannel(app.playback, g_message[i].pidChannel);
490            }
491            else {
492                NEXUS_PidChannel_Close(g_message[i].pidChannel);
493            }
494        }
495    }
496    if (app.playback) {
497        NEXUS_Playback_Stop(app.playback);
498        NEXUS_FilePlay_Close(app.file);
499        NEXUS_Playback_Destroy(app.playback);
500        NEXUS_Playpump_Close(app.playpump);
501    }
502    BKNI_DestroyEvent(app.event);
503    NEXUS_Platform_Uninit();
504    return 0;
505}
Note: See TracBrowser for help on using the repository browser.