📄 javasoundparser.java
字号:
public PullSourceStreamTrack(PullSourceStream pssForFormat, PullSourceStream pssForReadFrame) throws UnsupportedAudioFileException, IOException { super(); // determine format and frame size. { final AudioInputStream aisForFormat; final PullSourceStreamInputStream pssisForFormat; pssisForFormat = new PullSourceStreamInputStream(pssForFormat); aisForFormat = AudioSystem.getAudioInputStream(markSupportedInputStream(pssisForFormat)); this.javaSoundInputFormat = aisForFormat.getFormat(); this.frameLength = aisForFormat.getFrameLength(); this.format = JavaSoundRenderer.convertFormat(javaSoundInputFormat); logger.fine("JavaSoundParser: java sound format: " + javaSoundInputFormat); logger.fine("JavaSoundParser: jmf format: " + format); logger.fine("JavaSoundParser: Frame length=" + frameLength); aisForFormat.close(); pssisForFormat.close(); } setPssForReadFrame(pssForReadFrame); } /** * * @return nanos skipped, 0 if unable to skip. * @throws IOException */ public long skipNanos(long nanos) throws IOException { final long bytes = nanosToBytes(nanos); if (bytes <= 0) { logger.fine("JavaSoundParser: skipping nanos: " + 0); return 0; } final long bytesSkipped = aisForReadFrame.skip(bytes); totalBytesRead += bytesSkipped; if (bytesSkipped == bytes) { logger.fine("JavaSoundParser: skipping nanos: " + nanos); return nanos; } else { final long result = bytesToNanos(bytesSkipped); logger.fine("JavaSoundParser: skipping nanos: " + result); return result; } } public boolean canSkipNanos() { if (javaSoundInputFormat.getFrameSize() > 0 && javaSoundInputFormat.getFrameRate() > 0.f) return true; else return false; } // we can use this to set a new stream public void setPssForReadFrame(PullSourceStream pssForReadFrame) throws UnsupportedAudioFileException, IOException { this.pssForReadFrame = pssForReadFrame; this.pssisForReadFrame = new PullSourceStreamInputStream(pssForReadFrame); this.aisForReadFrame = AudioSystem.getAudioInputStream(markSupportedInputStream(pssisForReadFrame)); this.totalBytesRead = 0; } public Format getFormat() { return format; } /** * * @return -1L if cannot convert, because frame size and frame rate are not known. */ private long bytesToNanos(long bytes) { if (javaSoundInputFormat.getFrameSize() > 0 && javaSoundInputFormat.getFrameRate() > 0.f) { final long frames = bytes / javaSoundInputFormat.getFrameSize(); final double seconds = frames / javaSoundInputFormat.getFrameRate(); final double nanos = secondsToNanos(seconds); return (long) nanos; } else return -1L; } /** * * @return -1L if cannot convert, because frame size and frame rate are not known. */ private long nanosToBytes(long nanos) { if (javaSoundInputFormat.getFrameSize() > 0 && javaSoundInputFormat.getFrameRate() > 0.f) { // TODO: optimize this to avoid loss of precision. final double seconds = nanosToSeconds(nanos); final double frames = seconds * javaSoundInputFormat.getFrameRate(); final double bytes = frames * javaSoundInputFormat.getFrameSize(); return (long) bytes; } else return -1L; } // TODO: from JAVADOC:// This method might block if the data for a complete frame is not available. It might also block if the stream contains intervening data for a different interleaved Track. Once the other Track is read by a readFrame call from a different thread, this method can read the frame. If the intervening Track has been disabled, data for that Track is read and discarded.//// Note: This scenario is necessary only if a PullDataSource Demultiplexer implementation wants to avoid buffering data locally and copying the data to the Buffer passed in as a parameter. Implementations might decide to buffer data and not block (if possible) and incur data copy overhead. public void readFrame(Buffer buffer) { //format.getFrameSizeInBits() * format.getFrameRate(); // TODO: make buffer size an integral number of frames. final int BUFFER_SIZE = 10000; // TODO: how do we determine this size? Is this what the BufferControl control is for? if (buffer.getData() == null) buffer.setData(new byte[BUFFER_SIZE]); final byte[] bytes = (byte[]) buffer.getData(); // TODO: set other buffer fields, like format or sequenceNumber? try { final int result = aisForReadFrame.read(bytes, 0, bytes.length); if (result < 0) { buffer.setEOM(true); buffer.setLength(0); return; } // calculate timestamp for this buffer, if we can. if (javaSoundInputFormat.getFrameSize() > 0 && javaSoundInputFormat.getFrameRate() > 0.f) { buffer.setTimeStamp(bytesToNanos(totalBytesRead)); buffer.setDuration(bytesToNanos(result)); } // TODO: otherwise, set the timestamp/duration to what? 0? -1? totalBytesRead += result; buffer.setLength(result); buffer.setOffset(0); } catch (IOException e) { buffer.setEOM(true); // TODO buffer.setDiscard(true); // TODO buffer.setLength(0); logger.log(Level.WARNING, "" + e, e); } } public Time mapFrameToTime(int frameNumber) { return TIME_UNKNOWN; // this is what audio tracks are supposed to return } public int mapTimeToFrame(Time t) { return FRAME_UNKNOWN; // this is what audio tracks are supposed to return } public Time getDuration() { // TODO: for ogg/mp3, we end up with -1 frame length and return unknown. Maybe only the codec can figure this out. // or maybe we need to open our own converted stream to find the length. final long lengthInFrames = frameLength; if (lengthInFrames < 0) { logger.fine("PullSourceStreamTrack: returning Duration.DURATION_UNKNOWN (1)"); return Duration.DURATION_UNKNOWN; } final double lengthInSeconds = lengthInFrames / javaSoundInputFormat.getFrameRate(); if (lengthInSeconds < 0.0) { logger.fine("PullSourceStreamTrack: returning Duration.DURATION_UNKNOWN (2)"); return Duration.DURATION_UNKNOWN; } final double lengthInNanos = secondsToNanos(lengthInSeconds); logger.fine("PullSourceStreamTrack: returning " + ((long) lengthInNanos)); return new Time((long) lengthInNanos); } } // AudioSystem.getAudioInputStream needs to use marks to determine the format. private static InputStream markSupportedInputStream(InputStream is) { if (is.markSupported()) return is; else return new BufferedInputStream(is); } private static final double secondsToNanos(double secs) { return secs * 1000000000.0; } private static final double nanosToSeconds(double nanos) { return nanos / 1000000000.0; }// private static void dumpHeader()// {// // test code to find the header size// {// File file = new File(source.getLocator().getRemainder());// // RandomAccessFile raf = new RandomAccessFile(file, "r");// final long fileLength = raf.length();// logger.fine("file size: " + fileLength);// raf.close();// // InputStream fis = markSupportedInputStream(new FileInputStream(file));//// // AudioSystem.getAudioInputStream(fis);// int fisLen = 0;// while (true)// {// if (fis.read() == -1)// break;// else// ++fisLen;// }// // logger.fine("current pos: " + fisLen);// final long headerLen = fileLength - fisLen;// logger.fine("header len: " + headerLen);// // FileInputStream fis2 = new FileInputStream(file);// System.out.print("new byte[] {");// for (int i = 0; i < headerLen; ++i)// {// int b = fis2.read();// if (b > 127)// System.out.print("(byte) " + b + ", ");// else// System.out.print(" " + b + ", ");// }// logger.fine("};");// }// } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -