165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/* 265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Copyright (C) 2016 The Android Open Source Project 365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * you may not use this file except in compliance with the License. 665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * You may obtain a copy of the License at 765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 1065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Unless required by applicable law or agreed to in writing, software 1165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 1265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * See the License for the specific language governing permissions and 1465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * limitations under the License. 1565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 1665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 1765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopackage com.android.tv.tuner.exoplayer.buffer; 1865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.Nullable; 2065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.annotation.VisibleForTesting; 2165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.util.Log; 2265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 2365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.google.android.exoplayer.SampleHolder; 2465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 2565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.io.File; 2665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.io.IOException; 2765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.io.RandomAccessFile; 2865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.nio.channels.FileChannel; 2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 3065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/** 3165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@link SampleChunk} stores samples into file and makes them available for read. 3265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Stored file = { Header, Sample } * N 3365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Header = sample size : int, sample flag : int, sample PTS in micro second : long 3465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 3565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopublic class SampleChunk { 3665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static final String TAG = "SampleChunk"; 3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static final boolean DEBUG = false; 3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 3965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final long mCreatedTimeMs; 4065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final long mStartPositionUs; 4165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private SampleChunk mNextChunk; 4265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 4365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Header = sample size : int, sample flag : int, sample PTS in micro second : long 4465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private static final int SAMPLE_HEADER_LENGTH = 16; 4565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final File mFile; 4765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final ChunkCallback mChunkCallback; 4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final SamplePool mSamplePool; 4965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private RandomAccessFile mAccessFile; 5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private long mWriteOffset; 5165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private boolean mWriteFinished; 5265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private boolean mIsReading; 5365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private boolean mIsWriting; 5465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 5565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 5665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * A callback for chunks being committed to permanent storage. 5765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 5865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public static abstract class ChunkCallback { 5965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 6065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 6165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Notifies when writing a SampleChunk is completed. 6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 6365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunk SampleChunk which is written completely 6465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 6565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void onChunkWrite(SampleChunk chunk) { 6665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 6765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 6865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 6965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Notifies when a SampleChunk is deleted. 7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 7265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunk SampleChunk which is deleted from storage 7365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 7465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public void onChunkDelete(SampleChunk chunk) { 7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 7665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 7765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 7865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 7965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * A class for SampleChunk creation. 8065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 8165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public static class SampleChunkCreator { 8265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 8365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 8465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns a newly created SampleChunk to read & write samples. 8565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 8665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param samplePool sample allocator 8765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param file filename which will be created newly 8865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param startPositionUs the start position of the earliest sample to be stored 8965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunkCallback for total storage usage change notification 9065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 9165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleChunk createSampleChunk(SamplePool samplePool, File file, 9265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long startPositionUs, ChunkCallback chunkCallback) { 9365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return new SampleChunk(samplePool, file, startPositionUs, System.currentTimeMillis(), 9465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko chunkCallback); 9565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 9665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 9765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 9865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns a newly created SampleChunk which is backed by an existing file. 9965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Created SampleChunk is read-only. 10065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 10165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param samplePool sample allocator 10265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param bufferDir the directory where the file to read is located 10365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param filename the filename which will be read afterwards 10465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param startPositionUs the start position of the earliest sample in the file 10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunkCallback for total storage usage change notification 10665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param prev the previous SampleChunk just before the newly created SampleChunk 10765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 10865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 10965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleChunk loadSampleChunkFromFile(SamplePool samplePool, File bufferDir, 11065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko String filename, long startPositionUs, ChunkCallback chunkCallback, 11165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleChunk prev) throws IOException { 11265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko File file = new File(bufferDir, filename); 11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleChunk chunk = 11465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko new SampleChunk(samplePool, file, startPositionUs, chunkCallback); 11565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (prev != null) { 11665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko prev.mNextChunk = chunk; 11765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 11865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return chunk; 11965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 12065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 12165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 12265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Handles I/O for SampleChunk. 12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Maintains current SampleChunk and the current offset for next I/O operation. 12565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 12665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko static class IoState { 12765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private SampleChunk mChunk; 12865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private long mCurrentOffset; 12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 13065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private boolean equals(SampleChunk chunk, long offset) { 13165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return chunk == mChunk && mCurrentOffset == offset; 13265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 13365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 13465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 13565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns whether read I/O operation is finished. 13665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 13765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko boolean isReadFinished() { 13865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mChunk == null; 13965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 14165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 14265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the start position of the current SampleChunk 14365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 14465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long getStartPositionUs() { 14565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mChunk == null ? 0 : mChunk.getStartPositionUs(); 14665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 14765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 14865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void reset(@Nullable SampleChunk chunk) { 14965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk = chunk; 15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mCurrentOffset = 0; 15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 15265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 1536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private void reset(SampleChunk chunk, long offset) { 1546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mChunk = chunk; 1556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCurrentOffset = offset; 1566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 1576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 15965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Prepares for read I/O operation from a new SampleChunk. 16065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 16165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunk the new SampleChunk to read from 16265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 16365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 1646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko void openRead(SampleChunk chunk, long offset) throws IOException { 16565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk != null) { 16665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.closeRead(); 16765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 16865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko chunk.openRead(); 1696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko reset(chunk, offset); 17065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 17165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 17265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 17365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Prepares for write I/O operation to a new SampleChunk. 17465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 17565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunk the new SampleChunk to write samples afterwards 17665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 17765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 17865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko void openWrite(SampleChunk chunk) throws IOException{ 17965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk != null) { 18065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.closeWrite(chunk); 18165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko chunk.openWrite(); 18365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko reset(chunk); 18465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Reads a sample if it is available. 18865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 18965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @return Returns a sample if it is available, null otherwise. 19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 19165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 19265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleHolder read() throws IOException { 19365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk != null && mChunk.isReadFinished(this)) { 19465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleChunk next = mChunk.mNextChunk; 19565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.closeRead(); 19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (next != null) { 19765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko next.openRead(); 19865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 19965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko reset(next); 20065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 20165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk != null) { 20265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko try { 20365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mChunk.read(this); 20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } catch (IllegalStateException e) { 20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Write is finished and there is no additional buffer to read. 20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.w(TAG, "Tried to read sample over EOS."); 20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 21265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 21465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 21565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Writes a sample. 21665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 21765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param sample to write 21865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param nextChunk if this is {@code null} writes at the current SampleChunk, 21965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * otherwise close current SampleChunk and writes at this 22065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 22165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 22265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko void write(SampleHolder sample, SampleChunk nextChunk) 22365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throws IOException { 22465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (nextChunk != null) { 22565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk == null || mChunk.mNextChunk != null) { 22665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Requested write for wrong SampleChunk"); 22765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 22865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.closeWrite(nextChunk); 22965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.mChunkCallback.onChunkWrite(mChunk); 23065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko nextChunk.openWrite(); 23165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko reset(nextChunk); 23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.write(sample, this); 23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 23665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Finishes write I/O operation. 23865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 23965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @throws IOException 24065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 24165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko void closeWrite() throws IOException { 24265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mChunk != null) { 24365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunk.closeWrite(null); 24465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 24565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 24665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 24765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 2486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Returns the current SampleChunk for subsequent I/O operation. 2496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 2506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko SampleChunk getChunk() { 2516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mChunk; 2526ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2536ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** 2556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko * Returns the current offset of the current SampleChunk for subsequent I/O operation. 2566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko */ 2576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko long getOffset() { 2586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko return mCurrentOffset; 2596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2606ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko 2616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko /** 26265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Releases SampleChunk. the SampleChunk will not be used anymore. 26365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * 26465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param chunk to release 26565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * @param delete {@code true} when the backed file needs to be deleted, 26665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@code false} otherwise. 26765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 26865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko static void release(SampleChunk chunk, boolean delete) { 26965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko chunk.release(delete); 27065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 27165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 27265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 27365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @VisibleForTesting 27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected SampleChunk(SamplePool samplePool, File file, long startPositionUs, 27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long createdTimeMs, ChunkCallback chunkCallback) { 27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mStartPositionUs = startPositionUs; 27765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mCreatedTimeMs = createdTimeMs; 27865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mSamplePool = samplePool; 27965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mFile = file; 28065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunkCallback = chunkCallback; 28165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 28265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 28365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Constructor of SampleChunk which is backed by the given existing file. 28465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private SampleChunk(SamplePool samplePool, File file, long startPositionUs, 28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko ChunkCallback chunkCallback) throws IOException { 28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mStartPositionUs = startPositionUs; 28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mCreatedTimeMs = mStartPositionUs / 1000; 28865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mSamplePool = samplePool; 28965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mFile = file; 29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunkCallback = chunkCallback; 29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mWriteFinished = true; 29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 29365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 29465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void openRead() throws IOException { 29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mIsReading) { 29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mAccessFile == null) { 29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile = new RandomAccessFile(mFile, "r"); 29865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 29965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mWriteFinished && mWriteOffset == 0) { 30065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Lazy loading of write offset, in order not to load 30165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // all SampleChunk's write offset at start time of recorded playback. 30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mWriteOffset = mAccessFile.length(); 30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mIsReading = true; 30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 30765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void openWrite() throws IOException { 30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mWriteFinished) { 31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Opened for write though write is already finished"); 31165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mIsWriting) { 31365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mIsReading) { 31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Write is requested for " 31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko + "an already opened SampleChunk"); 31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile = new RandomAccessFile(mFile, "rw"); 31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mIsWriting = true; 31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 32265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void CloseAccessFileIfNeeded() throws IOException { 32365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (!mIsReading && !mIsWriting) { 32465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko try { 32565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mAccessFile != null) { 32665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.close(); 32765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 32865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } finally { 32965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile = null; 33065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 33465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void closeRead() throws IOException{ 33565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mIsReading) { 33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mIsReading = false; 33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko CloseAccessFileIfNeeded(); 33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 34065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 34165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void closeWrite(SampleChunk nextChunk) 34265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throws IOException { 34365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mIsWriting) { 34465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mNextChunk = nextChunk; 34565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mIsWriting = false; 34665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mWriteFinished = true; 34765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko CloseAccessFileIfNeeded(); 34865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 34965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 35065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 35165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private boolean isReadFinished(IoState state) { 35265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mWriteFinished && state.equals(this, mWriteOffset); 35365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 35465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 35565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private SampleHolder read(IoState state) throws IOException { 35665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mAccessFile == null || state.mChunk != this) { 35765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Requested read for wrong SampleChunk"); 35865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 35965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko long offset = state.mCurrentOffset; 36065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (offset >= mWriteOffset) { 36165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mWriteFinished) { 36265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Requested read for wrong range"); 36365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } else { 36465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (offset != mWriteOffset) { 36565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Log.e(TAG, "This should not happen!"); 36665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 36765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return null; 36865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 36965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 37065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.seek(offset); 37165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko int size = mAccessFile.readInt(); 37265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko SampleHolder sample = mSamplePool.acquireSample(size); 37365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.size = size; 37465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.flags = mAccessFile.readInt(); 37565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.timeUs = mAccessFile.readLong(); 37665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.clearData(); 37765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.data.put(mAccessFile.getChannel().map(FileChannel.MapMode.READ_ONLY, 37865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko offset + SAMPLE_HEADER_LENGTH, sample.size)); 37965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko offset += sample.size + SAMPLE_HEADER_LENGTH; 38065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko state.mCurrentOffset = offset; 38165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return sample; 38265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 38365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 38465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko @VisibleForTesting 38565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko protected void write(SampleHolder sample, IoState state) 38665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throws IOException { 38765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mAccessFile == null || mNextChunk != null || !state.equals(this, mWriteOffset)) { 38865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko throw new IllegalStateException("Requested write for wrong SampleChunk"); 38965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 39065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 39165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.seek(mWriteOffset); 39265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.writeInt(sample.size); 39365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.writeInt(sample.flags); 39465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.writeLong(sample.timeUs); 39565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko sample.data.position(0).limit(sample.size); 39665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.getChannel().position(mWriteOffset + SAMPLE_HEADER_LENGTH).write(sample.data); 39765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mWriteOffset += sample.size + SAMPLE_HEADER_LENGTH; 39865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko state.mCurrentOffset = mWriteOffset; 39965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 40065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 40165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private void release(boolean delete) { 40265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mWriteFinished = true; 40365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mIsReading = mIsWriting = false; 40465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko try { 40565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (mAccessFile != null) { 40665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mAccessFile.close(); 40765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 40865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } catch (IOException e) { 40965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko // Since the SampleChunk will not be reused, ignore exception. 41065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 41165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko if (delete) { 41265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mFile.delete(); 41365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mChunkCallback.onChunkDelete(this); 41465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 41565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 41665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 41765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 41865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the start position. 41965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 42065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public long getStartPositionUs() { 42165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mStartPositionUs; 42265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 42365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 42465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 42565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the creation time. 42665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 42765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public long getCreatedTimeMs() { 42865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mCreatedTimeMs; 42965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 43065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko 43165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko /** 43265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * Returns the current size. 43365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */ 43465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko public long getSize() { 43565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mWriteOffset; 43665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko } 43765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko} 438