1 /* 2 * @(#)VBI.java - carries various stuff 3 * 4 * Copyright (c) 2005 by dvb.matt, All Rights Reserved. 5 * 6 * This file is part of ProjectX, a free Java based demux utility. 7 * By the authors, ProjectX is intended for educational purposes only, 8 * as a non-commercial test project. 9 * 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 * 25 */ 26 27 package net.sourceforge.dvb.projectx.parser; 28 29 import net.sourceforge.dvb.projectx.common.Common; 30 import net.sourceforge.dvb.projectx.common.Resource; 31 import net.sourceforge.dvb.projectx.common.Keys; 32 33 import net.sourceforge.dvb.projectx.video.Video; 34 35 public final class VBI extends Object { 36 37 private static long source_pts = 0; 38 39 private static String vps_str = ""; 40 private static String vps_sound_mode[] = { "n/a", "mono", "stereo", "dual" }; 41 42 private static byte[] wss = new byte[3]; 43 44 /** 45 * 46 */ VBI()47 private VBI() 48 {} 49 50 51 /** 52 * 53 */ reset()54 public static void reset() 55 { 56 source_pts = 0; 57 vps_str = ""; 58 wss = new byte[3]; 59 } 60 61 /** 62 * 63 */ 64 // mpg2 pes expected parsePES(byte[] pes_packet, int pes_packetoffset)65 public static void parsePES(byte[] pes_packet, int pes_packetoffset) throws ArrayIndexOutOfBoundsException 66 { 67 if (pes_packet[pes_packetoffset] != 0 || pes_packet[1 + pes_packetoffset] != 0 || pes_packet[2 + pes_packetoffset] != 1) 68 return; 69 70 int pes_id = 0xFF & pes_packet[3 + pes_packetoffset]; 71 int pes_packetlength = (0xFF & pes_packet[4 + pes_packetoffset])<<8 | (0xFF & pes_packet[5 + pes_packetoffset]); 72 int pes_mpeg_flag = 0xC0 & pes_packet[6 + pes_packetoffset]; 73 74 if (pes_mpeg_flag != 0x80 && pes_mpeg_flag != 0x40) // neither mpeg2 nor mpeg1 75 return; 76 77 int pes_extensionlength = 0xFF & pes_packet[8 + pes_packetoffset]; 78 boolean pts_flag = (0x80 & pes_packet[7 + pes_packetoffset]) != 0; 79 80 source_pts = pts_flag ? CommonParsing.getPTSfromBytes(pes_packet, 9 + pes_packetoffset) : 0; 81 82 decodeVBI(pes_packet, 9 + pes_extensionlength + pes_packetoffset); 83 } 84 85 /** 86 * 87 */ decodeVBI(byte[] packet, int offs)88 private static void decodeVBI(byte[] packet, int offs) throws ArrayIndexOutOfBoundsException 89 { 90 String str; 91 92 boolean wss_online = false; 93 94 /** 95 * 0x99..0x9B -> PES contains one or multiple VBI Data definitions 96 */ 97 if ((0xFC & packet[offs]) != 0x98 || (3 & packet[offs]) == 0) 98 return; 99 100 for (int i = offs + 1, data_unit_id, len; i < packet.length - 1; ) 101 { 102 data_unit_id = 0xFF & packet[i++]; 103 len = 0xFF & packet[i++]; 104 105 /** 106 * VPS 107 */ 108 if (data_unit_id == 0xC3) 109 { 110 str = decodeVPS(packet, i); 111 112 if (str != null && !str.equals(vps_str)) 113 { 114 vps_str = str; 115 Common.setMessage(Resource.getString("teletext.msg.vps", str) + " " + Common.formatTime_1(source_pts / 90)); 116 } 117 } 118 119 /** 120 * WSS 121 */ 122 else if (data_unit_id == 0xC4) 123 { 124 str = decodeWSS(packet, i); 125 126 if (str != null) 127 { 128 wss_online = true; 129 130 if (str.length() > 0) 131 { 132 Common.setMessage("-> WSS Status - changed @ PTS " + Common.formatTime_1(source_pts / 90)); 133 Common.setMessage(str); 134 } 135 136 else if (wss[2] == 0) 137 { 138 Common.setMessage("-> WSS Status - no change @ PTS " + Common.formatTime_1(source_pts / 90)); 139 wss[2] = -2; 140 } 141 } 142 } 143 144 else if (data_unit_id == 0xFF) 145 {} 146 147 i += len; 148 } 149 150 if (!wss_online && wss[2] == -1) 151 { 152 wss[2] = 0; 153 154 Common.setMessage("-> WSS Status - offline @ PTS " + Common.formatTime_1(source_pts / 90)); 155 } 156 } 157 158 /** 159 * 160 */ decodeVPS(byte[] packet, int offs)161 public static String decodeVPS(byte[] packet, int offs) 162 { 163 if (!Common.getSettings().getBooleanProperty(Keys.KEY_MessagePanel_Msg6)) 164 return null; 165 166 String vps_status = ""; 167 168 if (packet.length - 1 < offs + 12) 169 return null; 170 171 int vps_data = (0x3F & packet[offs + 9])<<24 | 172 (0xFF & packet[offs + 10])<<16 | 173 (0xFF & packet[offs + 11])<<8 | 174 (0xFF & packet[offs + 12]); 175 176 switch (0x1F & vps_data>>>16) 177 { 178 case 0x1C: 179 vps_status = "Contin."; 180 break; 181 182 case 0x1D: 183 vps_status = "Pause "; 184 break; 185 186 case 0x1E: 187 vps_status = "Stop "; 188 break; 189 190 case 0x1F: 191 vps_status = "Timer "; 192 break; 193 194 default: 195 vps_status = "" + formatString(0x1F & (vps_data>>>25)) + "." + 196 formatString(0xF & (vps_data>>>21)) + ". " + 197 formatString(0x1F & (vps_data>>>16)) + ":" + 198 formatString(0x3F & (vps_data>>>10)) + " "; 199 } 200 201 vps_status += vps_sound_mode[(3 & packet[offs + 3]>>>6)] + " " + 202 Integer.toHexString(0xF & vps_data>>>6).toUpperCase() + " " + 203 Integer.toHexString(0x3F & vps_data).toUpperCase(); 204 205 return vps_status; 206 } 207 208 /** 209 * 210 */ formatString(int value)211 private static String formatString(int value) 212 { 213 String str = "00" + String.valueOf(value); 214 215 return str.substring(str.length() - 2); 216 } 217 218 219 /** 220 * 221 */ decodeWSS(byte[] packet, int offs)222 public static String decodeWSS(byte[] packet, int offs) 223 { 224 if (!Common.getSettings().getBooleanProperty(Keys.KEY_MessagePanel_Msg5)) 225 return null; 226 227 if (packet.length - 1 < offs + 2) 228 return null; 229 230 if (packet[offs + 1] == wss[0] && packet[offs + 2] == wss[1]) 231 return ""; 232 233 System.arraycopy(packet, offs + 1, wss, 0, 2); 234 wss[2] = -1; 235 236 // read PAL-625line WSS 237 String str = getGroup1(wss); 238 str += getGroup2(wss); 239 str += getGroup3(wss); 240 str += getGroup4(wss); 241 242 return str; 243 } 244 245 /** 246 * 247 */ getGroup1(byte[] packet)248 private static String getGroup1(byte[] packet) 249 { 250 String str = ""; 251 252 switch (0xF & packet[0]>>4) 253 { 254 case 1: // 0001 Biphase 01010110 255 str = " " + Resource.getString("wss.group_1.0001"); 256 break; 257 258 case 8: // 1000 Biphase 10010101 259 str = " " + Resource.getString("wss.group_1.1000"); 260 break; 261 262 case 4: // 0100 Biphase 01100101 263 str = " " + Resource.getString("wss.group_1.0100"); 264 break; 265 266 case 0xD: // 1101 Biphase 10100110 267 str = " " + Resource.getString("wss.group_1.1101"); 268 break; 269 270 case 2: // 0010 Biphase 01011001 271 str = " " + Resource.getString("wss.group_1.0010"); 272 break; 273 274 case 7: // 0111 Biphase 01101010 275 str = " " + Resource.getString("wss.group_1.0111"); 276 break; 277 278 case 0xE: // 1110 Biphase 10101001 279 str = " " + Resource.getString("wss.group_1.1110"); 280 break; 281 282 default: 283 str = " " + Resource.getString("wss.group_1.error"); 284 } 285 286 str += "\n"; 287 288 return str; 289 } 290 291 /** 292 * 293 */ getGroup2(byte[] packet)294 private static String getGroup2(byte[] packet) 295 { 296 String str = ""; 297 298 switch (1 & packet[0]>>3) 299 { 300 case 0: // 0 Biphase 01 301 str += " " + Resource.getString("wss.group_2.0.01"); 302 break; 303 304 case 1: // 1 Biphase 10 305 str += " " + Resource.getString("wss.group_2.0.10"); 306 } 307 308 str += ","; 309 310 switch (1 & packet[0]>>2) 311 { 312 case 0: // 0 Biphase 01 313 str += " " + Resource.getString("wss.group_2.1.01"); 314 break; 315 316 case 1: // 1 Biphase 10 317 str += " " + Resource.getString("wss.group_2.1.10"); 318 } 319 320 str += ","; 321 322 switch (1 & packet[0]>>1) 323 { 324 case 0: // 0 Biphase 01 325 str += " " + Resource.getString("wss.group_2.2.01"); 326 break; 327 328 case 1: // 1 Biphase 10 329 str += " " + Resource.getString("wss.group_2.2.10"); 330 } 331 332 str += ","; 333 334 switch (1 & packet[0]) 335 { 336 case 0: // 0 Biphase 01 337 str += " " + Resource.getString("wss.group_2.3.01"); 338 break; 339 340 case 1: // 1 Biphase 10 341 str += " " + Resource.getString("wss.group_2.3.10"); 342 } 343 344 str += "\n"; 345 346 return str; 347 } 348 349 /** 350 * 351 */ getGroup3(byte[] packet)352 private static String getGroup3(byte[] packet) 353 { 354 String str = ""; 355 356 switch (1 & packet[1]>>7) 357 { 358 case 0: // 0 Biphase 01 359 str += " " + Resource.getString("wss.group_3.0.01"); 360 break; 361 362 case 1: // 1 Biphase 10 363 str += " " + Resource.getString("wss.group_3.0.10"); 364 } 365 366 str += ","; 367 368 switch (3 & packet[1]>>5) 369 { 370 case 0: // 00 Biphase 0101 371 str += " " + Resource.getString("wss.group_3.1.00"); 372 break; 373 374 case 1: // 01 Biphase 0110 375 str += " " + Resource.getString("wss.group_3.1.01"); 376 break; 377 378 case 2: // 10 Biphase 1001 379 str += " " + Resource.getString("wss.group_3.1.10"); 380 break; 381 382 case 3: // 11 Biphase 1010 383 str += " " + Resource.getString("wss.group_3.1.11"); 384 } 385 386 str += "\n"; 387 388 return str; 389 } 390 391 /** 392 * 393 */ getGroup4(byte[] packet)394 private static String getGroup4(byte[] packet) 395 { 396 String str = ""; 397 398 switch (1 & packet[1]>>4) 399 { 400 case 0: // 0 Biphase 01 401 str += " " + Resource.getString("wss.group_4.0.01"); 402 break; 403 404 case 1: // 1 Biphase 10 405 str += " " + Resource.getString("wss.group_4.0.10"); 406 } 407 408 str += ","; 409 410 switch (1 & packet[1]>>3) 411 { 412 case 0: // 0 Biphase 01 413 str += " " + Resource.getString("wss.group_4.1.01"); 414 break; 415 416 case 1: // 1 Biphase 10 417 str += " " + Resource.getString("wss.group_4.1.10"); 418 } 419 420 str += ","; 421 422 switch (1 & packet[1]>>2) 423 { 424 case 0: // 0 Biphase 01 425 str += " " + Resource.getString("wss.group_4.2.01"); 426 break; 427 428 case 1: // 1 Biphase 10 429 str += " " + Resource.getString("wss.group_4.2.10"); 430 } 431 432 return str; 433 } 434 435 }