165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.core;
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameFormat;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameManager;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.format.ObjectFormat;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.graphics.Bitmap;
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.InputStream;
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.IOException;
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.ObjectInputStream;
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.ObjectOutputStream;
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.io.OutputStream;
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.nio.ByteBuffer;
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * A frame that serializes any assigned values. Such a frame is used when passing data objects
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * between threads.
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class SerializedFrame extends Frame {
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * The initial capacity of the serialized data stream.
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final static int INITIAL_CAPACITY = 64;
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * The internal data streams.
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private DirectByteOutputStream mByteOutputStream;
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private ObjectOutputStream mObjectOut;
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * An unsynchronized output stream that writes data to an accessible byte array. Callers are
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * responsible for synchronization. This is more efficient than a ByteArrayOutputStream, as
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * there are no array copies or synchronization involved to read back written data.
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class DirectByteOutputStream extends OutputStream {
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private byte[] mBuffer = null;
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private int mOffset = 0;
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private int mDataOffset = 0;
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public DirectByteOutputStream(int size) {
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mBuffer = new byte[size];
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private final void ensureFit(int bytesToWrite) {
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mOffset + bytesToWrite > mBuffer.length) {
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                byte[] oldBuffer = mBuffer;
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                mBuffer = new byte[Math.max(mOffset + bytesToWrite, mBuffer.length * 2)];
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                System.arraycopy(oldBuffer, 0, mBuffer, 0, mOffset);
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                oldBuffer = null;
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final void markHeaderEnd() {
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mDataOffset = mOffset;
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final int getSize() {
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return mOffset;
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public byte[] getByteArray() {
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return mBuffer;
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final void write(byte b[]) {
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            write(b, 0, b.length);
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final void write(byte b[], int off, int len) {
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ensureFit(len);
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            System.arraycopy(b, off, mBuffer, mOffset, len);
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mOffset += len;
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final void write(int b) {
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ensureFit(1);
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mBuffer[mOffset++] = (byte)b;
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final void reset() {
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mOffset = mDataOffset;
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final DirectByteInputStream getInputStream() {
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return new DirectByteInputStream(mBuffer, mOffset);
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    /**
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * An unsynchronized input stream that reads data directly from a provided byte array. Callers
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     * are responsible for synchronization and ensuring that the byte buffer is valid.
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn     */
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private class DirectByteInputStream extends InputStream {
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private byte[] mBuffer;
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private int mPos = 0;
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        private int mSize;
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public DirectByteInputStream(byte[] buffer, int size) {
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mBuffer = buffer;
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mSize = size;
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final int available() {
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return mSize - mPos;
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final int read() {
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return (mPos < mSize) ? (mBuffer[mPos++] & 0xFF) : -1;
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final int read(byte[] b, int off, int len) {
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (mPos >= mSize) {
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                return -1;
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if ((mPos + len) > mSize) {
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                len = mSize - mPos;
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            System.arraycopy(mBuffer, mPos, b, off, len);
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mPos += len;
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return len;
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        @Override
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        public final long skip(long n) {
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if ((mPos + n) > mSize) {
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                n = mSize - mPos;
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (n < 0) {
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                return 0;
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mPos += n;
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return n;
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    SerializedFrame(FrameFormat format, FrameManager frameManager) {
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        super(format, frameManager);
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setReusable(false);
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Setup streams
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        try {
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mByteOutputStream = new DirectByteOutputStream(INITIAL_CAPACITY);
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mObjectOut = new ObjectOutputStream(mByteOutputStream);
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mByteOutputStream.markHeaderEnd();
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (IOException e) {
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not create serialization streams for "
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                + "SerializedFrame!", e);
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    static SerializedFrame wrapObject(Object object, FrameManager frameManager) {
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        FrameFormat format = ObjectFormat.fromObject(object, FrameFormat.TARGET_SIMPLE);
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        SerializedFrame result = new SerializedFrame(format, frameManager);
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        result.setObjectValue(object);
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return result;
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected boolean hasNativeAllocation() {
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return false;
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void releaseNativeAllocation() {
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public Object getObjectValue() {
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return deserializeObjectValue();
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setInts(int[] ints) {
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setGenericObjectValue(ints);
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public int[] getInts() {
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Object result = deserializeObjectValue();
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (result instanceof int[]) ? (int[])result : null;
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setFloats(float[] floats) {
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setGenericObjectValue(floats);
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public float[] getFloats() {
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Object result = deserializeObjectValue();
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (result instanceof float[]) ? (float[])result : null;
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setData(ByteBuffer buffer, int offset, int length) {
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setGenericObjectValue(ByteBuffer.wrap(buffer.array(), offset, length));
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public ByteBuffer getData() {
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Object result = deserializeObjectValue();
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (result instanceof ByteBuffer) ? (ByteBuffer)result : null;
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setBitmap(Bitmap bitmap) {
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        assertFrameMutable();
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setGenericObjectValue(bitmap);
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public Bitmap getBitmap() {
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        Object result = deserializeObjectValue();
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return (result instanceof Bitmap) ? (Bitmap)result : null;
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void setGenericObjectValue(Object object) {
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        serializeObjectValue(object);
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final void serializeObjectValue(Object object) {
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        try {
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mByteOutputStream.reset();
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mObjectOut.writeObject(object);
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mObjectOut.flush();
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            mObjectOut.close();
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (IOException e) {
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not serialize object " + object + " in "
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                + this + "!", e);
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private final Object deserializeObjectValue() {
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        try {
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            InputStream inputStream = mByteOutputStream.getInputStream();
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            ObjectInputStream objectStream = new ObjectInputStream(inputStream);
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            return objectStream.readObject();
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (IOException e) {
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not deserialize object in " + this + "!", e);
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } catch (ClassNotFoundException e) {
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Unable to deserialize object of unknown class in "
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                + this + "!", e);
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public String toString() {
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return "SerializedFrame (" + getFormat() + ")";
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
284