11abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/*
21abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Copyright (C) 2015 The Android Open Source Project
31abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
41abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
51abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * you may not use this file except in compliance with the License.
61abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * You may obtain a copy of the License at
71abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
81abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
91abddd9f6225298066094e20a6c29061b6af4590Nick Chalko *
101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Unless required by applicable law or agreed to in writing, software
111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * See the License for the specific language governing permissions and
141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * limitations under the License.
151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1748dadb49248271b01997862e1335912a4f2e189fYoungsang Chopackage com.android.usbtuner.exoplayer.cache;
181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
191abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.MediaFormat;
201abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.util.Pair;
211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
221abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.DataInputStream;
231abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.DataOutputStream;
241abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.File;
251abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.FileInputStream;
261abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.FileOutputStream;
271abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.IOException;
281abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.nio.ByteBuffer;
291abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.nio.charset.StandardCharsets;
301abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.util.ArrayList;
311abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.util.SortedMap;
321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/**
341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Manages DVR storage.
351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
361abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopublic class DvrStorageManager implements CacheManager.StorageManager {
371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // TODO: make serializable classes and use protobuf after internal data structure is finalized.
391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final String KEY_PIXEL_WIDTH_HEIGHT_RATIO =
401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            "com.google.android.videos.pixelWidthHeightRatio";
411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final String META_FILE_SUFFIX = ".meta";
421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final String IDX_FILE_SUFFIX = ".idx";
431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // Size of minimum reserved storage buffer which will be used to save meta files
451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // and index files after actual recording finished.
46ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private static final long MIN_BUFFER_BYTES = 256L * 1024 * 1024;
471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final int NO_VALUE = -1;
481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final long NO_VALUE_LONG = -1L;
491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final File mCacheDir;
511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // {@code true} when this is for recording, {@code false} when this is for replaying.
531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final boolean mIsRecording;
541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public DvrStorageManager(File file, boolean isRecording) {
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mCacheDir = file;
571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mCacheDir.mkdirs();
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mIsRecording = isRecording;
591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void clearStorage() {
631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mIsRecording) {
641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            for (File file : mCacheDir.listFiles()) {
651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                file.delete();
661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public File getCacheDir() {
721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mCacheDir;
731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean isPersistent() {
771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return true;
781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean reachedStorageMax(long cacheSize, long pendingDelete) {
821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return false;
831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean hasEnoughBuffer(long pendingDelete) {
87ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return !mIsRecording || mCacheDir.getUsableSpace() >= MIN_BUFFER_BYTES;
881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void readFormatInt(DataInputStream in, MediaFormat format, String key)
911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        int val = in.readInt();
931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (val != NO_VALUE) {
941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            format.setInteger(key, val);
951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void readFormatLong(DataInputStream in, MediaFormat format, String key)
991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        long val = in.readLong();
1011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (val != NO_VALUE_LONG) {
1021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            format.setLong(key, val);
1031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void readFormatFloat(DataInputStream in, MediaFormat format, String key)
1071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        float val = in.readFloat();
1091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (val != NO_VALUE) {
1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            format.setFloat(key, val);
1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private String readString(DataInputStream in) throws IOException {
1151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        int len = in.readInt();
1161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (len <= 0) {
1171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return null;
1181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        byte [] strBytes = new byte[len];
1201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        in.readFully(strBytes);
1211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return new String(strBytes, StandardCharsets.UTF_8);
1221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void readFormatString(DataInputStream in, MediaFormat format, String key)
1251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        String str = readString(in);
1271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (str != null) {
1281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            format.setString(key, str);
1291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private ByteBuffer readByteBuffer(DataInputStream in) throws IOException {
1331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        int len = in.readInt();
1341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (len <= 0) {
1351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return null;
1361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        byte [] bytes = new byte[len];
1381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        in.readFully(bytes);
1391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ByteBuffer buffer = ByteBuffer.allocate(len);
1401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        buffer.put(bytes);
1411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        buffer.flip();
1421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return buffer;
1441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void readFormatByteBuffer(DataInputStream in, MediaFormat format, String key)
1471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ByteBuffer buffer = readByteBuffer(in);
1491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (buffer != null) {
1501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            format.setByteBuffer(key, buffer);
1511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
1551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public Pair<String, MediaFormat> readTrackInfoFile(boolean isAudio) throws IOException {
1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        File file = new File(getCacheDir(), (isAudio ? "audio" : "video") + META_FILE_SUFFIX);
1571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
1581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            String name = readString(in);
1591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            MediaFormat format = new MediaFormat();
1601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatString(in, format, MediaFormat.KEY_MIME);
1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatInt(in, format, MediaFormat.KEY_MAX_INPUT_SIZE);
1621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatInt(in, format, MediaFormat.KEY_WIDTH);
1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatInt(in, format, MediaFormat.KEY_HEIGHT);
1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatInt(in, format, MediaFormat.KEY_CHANNEL_COUNT);
1651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatInt(in, format, MediaFormat.KEY_SAMPLE_RATE);
1661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatFloat(in, format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            for (int i = 0; i < 3; ++i) {
1681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                readFormatByteBuffer(in, format, "csd-" + i);
1691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
1701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            readFormatLong(in, format, MediaFormat.KEY_DURATION);
171ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            return new Pair<>(name, format);
1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
1761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public ArrayList<Long> readIndexFile(String trackId) throws IOException {
1771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        ArrayList<Long> indices = new ArrayList<>();
1781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        File file = new File(getCacheDir(), trackId + IDX_FILE_SUFFIX);
1791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
1801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            long count = in.readLong();
1811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            for (long i = 0; i < count; ++i) {
1821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                indices.add(in.readLong());
1831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
1841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return indices;
1851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeFormatInt(DataOutputStream out, MediaFormat format, String key)
1891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (format.containsKey(key)) {
1911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeInt(format.getInteger(key));
1921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
1931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeInt(NO_VALUE);
1941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeFormatLong(DataOutputStream out, MediaFormat format, String key)
1981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
1991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (format.containsKey(key)) {
2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeLong(format.getLong(key));
2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeLong(NO_VALUE_LONG);
2031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeFormatFloat(DataOutputStream out, MediaFormat format, String key)
2071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
2081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (format.containsKey(key)) {
2091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeFloat(format.getFloat(key));
2101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeFloat(NO_VALUE);
2121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeString(DataOutputStream out, String str) throws IOException {
2161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        byte [] data = str.getBytes(StandardCharsets.UTF_8);
2171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        out.writeInt(data.length);
2181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (data.length > 0) {
2191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.write(data);
2201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeFormatString(DataOutputStream out, MediaFormat format, String key)
2241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
2251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (format.containsKey(key)) {
2261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeString(out, format.getString(key));
2271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeInt(0);
2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeByteBuffer(DataOutputStream out, ByteBuffer buffer) throws IOException {
2331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        byte [] data = new byte[buffer.limit()];
2341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        buffer.get(data);
2351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        buffer.flip();
2361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        out.writeInt(data.length);
2371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (data.length > 0) {
2381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.write(data);
2391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeInt(0);
2411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void writeFormatByteBuffer(DataOutputStream out, MediaFormat format, String key)
2451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
2461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (format.containsKey(key)) {
2471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeByteBuffer(out, format.getByteBuffer(key));
2481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
2491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeInt(0);
2501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void writeTrackInfoFile(String trackId, MediaFormat format, boolean isAudio)
2551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
2561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        File file = new File(getCacheDir(), (isAudio ? "audio" : "video") + META_FILE_SUFFIX);
2571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
2581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeString(out, trackId);
2591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatString(out, format, MediaFormat.KEY_MIME);
2601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatInt(out, format, MediaFormat.KEY_MAX_INPUT_SIZE);
2611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatInt(out, format, MediaFormat.KEY_WIDTH);
2621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatInt(out, format, MediaFormat.KEY_HEIGHT);
2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatInt(out, format, MediaFormat.KEY_CHANNEL_COUNT);
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatInt(out, format, MediaFormat.KEY_SAMPLE_RATE);
2651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatFloat(out, format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            for (int i = 0; i < 3; ++i) {
2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                writeFormatByteBuffer(out, format, "csd-" + i);
2681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            writeFormatLong(out, format, MediaFormat.KEY_DURATION);
2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
2741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void writeIndexFile(String trackName, SortedMap<Long, SampleCache> index)
2751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            throws IOException {
2761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        File indexFile  = new File(getCacheDir(), trackName + IDX_FILE_SUFFIX);
2771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(indexFile))) {
2781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            out.writeLong(index.size());
2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            for (Long key : index.keySet()) {
2801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                out.writeLong(key);
2811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
2821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
285