| 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 | |
|---|
| 109 | BDBG_MODULE(message); |
|---|
| 110 | |
|---|
| 111 | static 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 |
|---|
| 120 | struct message_t { |
|---|
| 121 | unsigned short pid; |
|---|
| 122 | NEXUS_MessageHandle message; |
|---|
| 123 | NEXUS_PidChannelHandle pidChannel; |
|---|
| 124 | } g_message[MAX_MESSAGE_FILTERS]; |
|---|
| 125 | |
|---|
| 126 | static void message_callback(void *context, int param) |
|---|
| 127 | { |
|---|
| 128 | BSTD_UNUSED(param); |
|---|
| 129 | BKNI_SetEvent((BKNI_EventHandle)context); |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | static 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 | |
|---|
| 138 | struct 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 | |
|---|
| 151 | void 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 | |
|---|
| 160 | static 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 | |
|---|
| 206 | static 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 | |
|---|
| 214 | void 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 | |
|---|
| 229 | int 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 | |
|---|
| 272 | int 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 | } |
|---|