io.card.development.recording.Recording.java Source code

Java tutorial

Introduction

Here is the source code for io.card.development.recording.Recording.java

Source

package io.card.development.recording;

/* Recording.java
 * See the file "LICENSE.md" for the full license governing this code.
 */

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Represents captured recording sequences.
 * <p/>
 * Test recordings are fed directly into the video frame callback for testing of the vision pipeline.
 * <p/>
 * This package should be striped from released code. (e.g. via Proguard)
 */

public class Recording implements Iterator<byte[]> {
    private final String TAG = this.getClass().getName();

    private ManifestEntry[] manifestEntries;

    private Recording(ManifestEntry[] manifestEntries) {
        this.manifestEntries = manifestEntries;
    }

    public ManifestEntry[] getManifestEntries() {
        return manifestEntries;
    }

    public void setManifestEntries(ManifestEntry[] manifestEntries) {
        this.manifestEntries = manifestEntries;
    }

    private int currentFrameIdx = 0;
    private Hashtable<String, byte[]> recordingContents;

    public Recording(File zipfile) {
        try {
            FileInputStream fileStream = new FileInputStream(zipfile);
            BufferedInputStream bufStream = new BufferedInputStream(fileStream);
            recordingContents = unzipFiles(bufStream);

            assert recordingContents != null;

            Log.d(TAG, String.format("recording has %d items", recordingContents.size()));
            Log.d(TAG, "keys: ");

            manifestEntries = ManifestEntry.getManifest(recordingContents);

        } catch (FileNotFoundException e) {
            Log.e(TAG, e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    @Override
    public boolean hasNext() {
        return (currentFrameIdx < manifestEntries.length - 1);
    }

    @Override
    public byte[] next() {
        byte[] frame = getFrame(currentFrameIdx);
        currentFrameIdx++;
        return frame;
    }

    public byte[] getFrame(int frameIdx) {
        ManifestEntry me = manifestEntries[frameIdx];

        byte[] Y = me.getYImage();
        byte[] Cb = me.getCbImage();
        byte[] Cr = me.getCrImage();

        assert Cb.length == Cr.length;
        assert Y.length == Cb.length * 4;

        byte[] frame = new byte[Y.length + Cb.length + Cr.length];
        System.arraycopy(Y, 0, frame, 0, Y.length);
        for (int i = 0; i < Cb.length; i++) {
            frame[Y.length + 2 * i + 1] = Cb[i];
            frame[Y.length + 2 * i] = Cr[i];
        }

        return frame;
    }

    @Override
    public void remove() throws UnsupportedOperationException {
        throw new UnsupportedOperationException("Frames cannot be removed from a recording");
    }

    public int getCurrentFrameIndex() {
        return currentFrameIdx;
    }

    public static Recording[] parseRecordings(InputStream recordingStream) throws IOException, JSONException {
        Hashtable<String, byte[]> recordingFiles = unzipFiles(recordingStream);
        Hashtable<String, byte[]> manifestFiles = findManifestFiles(recordingFiles);

        int recordingIndex = 0;
        Recording[] recordings = new Recording[manifestFiles.size()];
        Enumeration<String> manifestFilenames = manifestFiles.keys();
        while (manifestFilenames.hasMoreElements()) {
            String manifestFilename = manifestFilenames.nextElement();
            String manifestDirName = manifestFilename.substring(0, manifestFilename.lastIndexOf("/"));
            byte[] manifestData = manifestFiles.get(manifestFilename);

            ManifestEntry[] manifestEntries = buildManifest(manifestDirName, manifestData, recordingFiles);
            recordings[recordingIndex] = new Recording(manifestEntries);
            recordingIndex++;
        }

        return recordings;
    }

    private static Hashtable<String, byte[]> unzipFiles(InputStream recordingStream) throws IOException {
        ZipEntry zipEntry;
        ZipInputStream zis = new ZipInputStream(recordingStream);
        Hashtable<String, byte[]> fileHash = new Hashtable<String, byte[]>();
        byte[] buffer = new byte[512];

        while ((zipEntry = zis.getNextEntry()) != null) {
            if (!zipEntry.isDirectory()) {
                int read = 0;
                ByteArrayOutputStream fileStream = new ByteArrayOutputStream();

                do {
                    read = zis.read(buffer, 0, buffer.length);
                    if (read != -1) {
                        fileStream.write(buffer, 0, read);
                    }
                } while (read != -1);

                byte[] fileData = fileStream.toByteArray();
                fileHash.put(zipEntry.getName(), fileData);
            }
        }

        return fileHash;
    }

    private static Hashtable<String, byte[]> findManifestFiles(Hashtable<String, byte[]> recordingFiles) {
        Hashtable<String, byte[]> manifestFiles = new Hashtable<String, byte[]>();
        Enumeration<String> fileNames = recordingFiles.keys();

        while (fileNames.hasMoreElements()) {
            String fileName = fileNames.nextElement();
            if (fileName.endsWith("manifest.json")) {
                manifestFiles.put(fileName, recordingFiles.get(fileName));
            }
        }

        return manifestFiles;
    }

    private static ManifestEntry[] buildManifest(String manifestDirName, byte[] manifestData,
            Hashtable<String, byte[]> recordingFiles) throws JSONException {
        String manifestString = new String(manifestData);
        JSONArray manifestJson = new JSONArray(manifestString);

        ManifestEntry[] manifestEntries = new ManifestEntry[manifestJson.length()];
        for (int i = 0; i < manifestEntries.length; i++) {
            JSONObject manifestEntryJson = manifestJson.getJSONObject(i);
            manifestEntries[i] = new ManifestEntry(manifestDirName, manifestEntryJson, recordingFiles);
        }

        return manifestEntries;
    }
}