class LookAhead {
        private final int corePresent;
        long bufferStartPos;
        int inBufferPos = 0;
        DataSource dataSource;
        long dataEnd;
        ByteBuffer buffer;

        long start;

        LookAhead(DataSource dataSource, long bufferStartPos, long dataSize, int corePresent) throws IOException {
            this.dataSource = dataSource;
            this.bufferStartPos = bufferStartPos;
            this.dataEnd = dataSize + bufferStartPos;
            this.corePresent = corePresent;
            fillBuffer();
        }

        public ByteBuffer findNextStart() throws IOException {
            try {
                // If core DTS stream is present then sync word is 0x7FFE8001
                // otherwise 0x64582025
                while (corePresent == 1 ? !this.nextFourEquals0x7FFE8001() : !nextFourEquals0x64582025()) {
                    this.discardByte();
                }
                this.discardNext4AndMarkStart();

                while (corePresent == 1 ? !this.nextFourEquals0x7FFE8001orEof() : !nextFourEquals0x64582025orEof()) {
                    this.discardQWord();
                }
                return this.getSample();
            } catch (EOFException e) {
                return null;
            }
        }


        private void fillBuffer() throws IOException {
            System.err.println("Fill Buffer");
            buffer = dataSource.map(bufferStartPos, Math.min(dataEnd - bufferStartPos, BUFFER));
        }

        private boolean nextFourEquals0x64582025() throws IOException {
            return nextFourEquals((byte) 100, (byte) 88, (byte) 32, (byte) 37);
        }

        private boolean nextFourEquals0x7FFE8001() throws IOException {
            return nextFourEquals((byte) 127, (byte) -2, (byte) -128, (byte) 1);
        }

        private boolean nextFourEquals(byte a, byte b, byte c, byte d) throws IOException {
            if (buffer.limit() - inBufferPos >= 4) {
                return ((buffer.get(inBufferPos) == a &&
                        buffer.get(inBufferPos + 1) == b &&
                        buffer.get(inBufferPos + 2) == c &&
                        (buffer.get(inBufferPos + 3) == d)));
            }
            if (bufferStartPos + inBufferPos + 4 >= dataSource.size()) {
                throw new EOFException();
            }
            return false;
        }

        private boolean nextFourEquals0x64582025orEof() throws IOException {
            return nextFourEqualsOrEof((byte) 100, (byte) 88, (byte) 32, (byte) 37);
        }


        private boolean nextFourEquals0x7FFE8001orEof() throws IOException {
            return nextFourEqualsOrEof((byte) 127, (byte) -2, (byte) -128, (byte) 1);
        }

        private boolean nextFourEqualsOrEof(byte a, byte b, byte c, byte d) throws IOException {
            if (buffer.limit() - inBufferPos >= 4) {
                if (((bufferStartPos + inBufferPos) % (1024 * 1024)) == 0) {
                    System.err.println("" + ((bufferStartPos + inBufferPos) / 1024 / 1024));
                }
                return ((buffer.get(inBufferPos) == a /*0x7F */ &&
                        buffer.get(inBufferPos + 1) == b/*0xfe*/ &&
                        buffer.get(inBufferPos + 2) == c /*0x80*/ &&
                        (buffer.get(inBufferPos + 3) == d)));
            } else {
                if (bufferStartPos + inBufferPos + 4 > dataEnd) {
                    return bufferStartPos + inBufferPos == dataEnd;
                } else {
                    bufferStartPos = start;
                    inBufferPos = 0;
                    fillBuffer();
                    return nextFourEquals0x7FFE8001();
                }
            }
        }


        private void discardByte() {
            inBufferPos += 1;
        }

        private void discardQWord() {
            inBufferPos += 4;
        }


        private void discardNext4AndMarkStart() {
            start = bufferStartPos + inBufferPos;
            inBufferPos += 4;
        }

        private ByteBuffer getSample() {<FILL_FUNCTION_BODY>}
    }

            if (start >= bufferStartPos) {
                ((Buffer)buffer).position((int) (start - bufferStartPos));
                Buffer sample = buffer.slice();
                ((Buffer)sample).limit((int) (inBufferPos - (start - bufferStartPos)));
                return (ByteBuffer) sample;
            } else {
                throw new RuntimeException("damn! NAL exceeds buffer");
                // this can only happen if NAL is bigger than the buffer
            }

        
<methods>public void <init>(java.lang.String) ,public List<org.mp4parser.boxes.iso14496.part12.CompositionTimeToSample.Entry> getCompositionTimeEntries() ,public long getDuration() ,public List<org.mp4parser.muxer.Edit> getEdits() ,public java.lang.String getName() ,public List<org.mp4parser.boxes.iso14496.part12.SampleDependencyTypeBox.Entry> getSampleDependencies() ,public Map<org.mp4parser.boxes.samplegrouping.GroupEntry,long[]> getSampleGroups() ,public org.mp4parser.boxes.iso14496.part12.SubSampleInformationBox getSubsampleInformationBox() ,public long[] getSyncSamples() <variables>List<org.mp4parser.muxer.Edit> edits,java.lang.String name,Map<org.mp4parser.boxes.samplegrouping.GroupEntry,long[]> sampleGroups