private void parseHeader() throws IOException { LOGGER.trace("Parsing AVI stream"); String id = getString(stream, 4); getBytes(stream, 4); String type = getString(stream, 4); if (!"RIFF".equalsIgnoreCase(id) || !"AVI ".equalsIgnoreCase(type)) { throw new IOException("Not AVI file"); } byte[] hdrl = null; while (true) { String command = getString(stream, 4); int length = (readBytes(stream, 4) + 1) & ~1; if ("LIST".equalsIgnoreCase(command)) { command = getString(stream, 4); length -= 4; if ("movi".equalsIgnoreCase(command)) { break; } if ("hdrl".equalsIgnoreCase(command)) { hdrl = getBytes(stream, length); } if ("idx1".equalsIgnoreCase(command)) { /*idx = */ getBytes(stream, length); } if ("iddx".equalsIgnoreCase(command)) { /*idx = */ getBytes(stream, length); } } else { getBytes(stream, length); } } int streamNumber = 0; int lastTagID = 0; for (int i = 0; i < hdrl.length; ) { String command = new String(hdrl, i, 4); int size = str2ulong(hdrl, i + 4); if ("LIST".equalsIgnoreCase(command)) { i += 12; continue; } String command2 = new String(hdrl, i + 8, 4); if ("strh".equalsIgnoreCase(command)) { lastTagID = 0; if ("vids".equalsIgnoreCase(command2)) { String compressor = new String(hdrl, i + 12, 4); int scale = str2ulong(hdrl, i + 28); int rate = str2ulong(hdrl, i + 32); track[0] = new Track(compressor, scale, rate, -1); streamVideoTag = new String( new char[] { (char) ((streamNumber / 10) + '0'), (char) ((streamNumber % 10) + '0'), 'd', 'b' }); streamNumber++; lastTagID = 1; } if ("auds".equalsIgnoreCase(command2)) { int scale = str2ulong(hdrl, i + 28); int rate = str2ulong(hdrl, i + 32); int sampleSize = str2ulong(hdrl, i + 52); track[1 + numberOfAudioChannels++] = new Track(null, scale, rate, sampleSize); streamNumber++; lastTagID = 2; } } if ("strf".equalsIgnoreCase(command)) { if (lastTagID == 1) { byte[] information = new byte[size]; // formerly size-4 System.arraycopy(hdrl, i + 8, information, 0, information.length); // formerly i+4 track[0].setBih(information); } if (lastTagID == 2) { byte[] information = new byte[size]; // formerly size-4 System.arraycopy(hdrl, i + 8, information, 0, information.length); // formerly i+4 Track aud = track[1 + numberOfAudioChannels - 1]; aud.setBih(information); int bitsPerSample = str2ushort(information, 14); aud.setBitsPerSample(bitsPerSample); int nbAudio = str2ushort(information, 2); aud.setNbAudio(nbAudio); long fileLength = 100; if (params.losslessaudio) { aOut = new PCMAudioOutputStream(aOut, nbAudio, 48000, bitsPerSample); } if (!params.lossyaudio && params.losslessaudio) { writePCMHeader( aOut, fileLength, nbAudio, aud.getRate(), aud.getSampleSize(), bitsPerSample); } } } if (size % 2 != 0) { size++; } i += size + 8; } LOGGER.trace("Found " + streamNumber + " stream(s)"); boolean init = false; while (true) { String command; try { command = getString(stream, 4); } catch (Exception e) { LOGGER.trace("Error reading stream: " + e.getMessage()); break; } if (command == null) { break; } command = command.toUpperCase(); int size = readBytes(stream, 4); boolean framed = false; while ("LIST".equals(command) || "RIFF".equals(command) || "JUNK".equals(command)) { if (size < 0) { size = 4; } getBytes(stream, "RIFF".equals(command) ? 4 : size); command = getString(stream, 4).toUpperCase(); size = readBytes(stream, 4); if (("LIST".equals(command) || "RIFF".equals(command) || "JUNK".equals(command)) && (size % 2 != 0)) { readByte(stream); } } String videoTag = streamVideoTag.substring(0, 3); if (command.substring(0, 3).equalsIgnoreCase(videoTag) && (command.charAt(3) == 'B' || command.charAt(3) == 'C')) { byte[] buffer = getBytes(stream, size); if (!command.equalsIgnoreCase("IDX1")) { vOut.write(buffer); videosize += size; } framed = true; } if (!framed) { for (int i = 0; i < numberOfAudioChannels; i++) { byte[] buffer = getBytes(stream, size); if (!command.equalsIgnoreCase("IDX1")) { aOut.write(buffer, init ? 4 : 0, init ? (size - 4) : size); init = false; audiosize += size; } framed = true; } } if (!framed) { throw new IOException("Not header: " + command); } if (size % 2 != 0) { readByte(stream); } } LOGGER.trace("output pipes closed"); aOut.close(); vOut.close(); }