/*
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.cts;

import com.android.cts.media.R;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.cts.util.MediaUtils;
import android.graphics.Rect;
import android.graphics.ImageFormat;
import android.media.cts.CodecUtils;
import android.media.Image;
import android.media.Image.Plane;
import android.media.ImageReader;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.VideoCapabilities;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.Log;
import android.view.Surface;

import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * Basic test for ImageReader APIs.
 * <p>
 * It uses MediaCodec to decode a short video stream, send the video frames to
 * the surface provided by ImageReader. Then compare if output buffers of the
 * ImageReader matches the output buffers of the MediaCodec. The video format
 * used here is AVC although the compression format doesn't matter for this
 * test. For decoder test, hw and sw decoders are tested,
 * </p>
 */
public class ImageReaderDecoderTest extends AndroidTestCase {
    private static final String TAG = "ImageReaderDecoderTest";
    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
    private static final long DEFAULT_TIMEOUT_US = 10000;
    private static final long WAIT_FOR_IMAGE_TIMEOUT_MS = 1000;
    private static final String DEBUG_FILE_NAME_BASE = "/sdcard/";
    private static final int NUM_FRAME_DECODED = 100;
    // video decoders only support a single outstanding image with the consumer
    private static final int MAX_NUM_IMAGES = 1;
    private static final float COLOR_STDEV_ALLOWANCE = 5f;
    private static final float COLOR_DELTA_ALLOWANCE = 5f;

    private final static int MODE_IMAGEREADER = 0;
    private final static int MODE_IMAGE       = 1;

    private Resources mResources;
    private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
    private ImageReader mReader;
    private Surface mReaderSurface;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private ImageListener mImageListener;

    @Override
    public void setContext(Context context) {
        super.setContext(context);
        mResources = mContext.getResources();
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mHandlerThread = new HandlerThread(TAG);
        mHandlerThread.start();
        mHandler = new Handler(mHandlerThread.getLooper());
        mImageListener = new ImageListener();
    }

    @Override
    protected void tearDown() throws Exception {
        mHandlerThread.quitSafely();
        mHandler = null;
    }

    static class MediaAsset {
        public MediaAsset(int resource, int width, int height) {
            mResource = resource;
            mWidth = width;
            mHeight = height;
        }

        public int getWidth() {
            return mWidth;
        }

        public int getHeight() {
            return mHeight;
        }

        public int getResource() {
            return mResource;
        }

        private final int mResource;
        private final int mWidth;
        private final int mHeight;
    }

    static class MediaAssets {
        public MediaAssets(String mime, MediaAsset... assets) {
            mMime = mime;
            mAssets = assets;
        }

        public String getMime() {
            return mMime;
        }

        public MediaAsset[] getAssets() {
            return mAssets;
        }

        private final String mMime;
        private final MediaAsset[] mAssets;
    }

    private static MediaAssets H263_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_H263,
            new MediaAsset(R.raw.swirl_176x144_h263, 176, 144),
            new MediaAsset(R.raw.swirl_352x288_h263, 352, 288),
            new MediaAsset(R.raw.swirl_128x96_h263, 128, 96));

    private static MediaAssets MPEG4_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_MPEG4,
            new MediaAsset(R.raw.swirl_128x128_mpeg4, 128, 128),
            new MediaAsset(R.raw.swirl_144x136_mpeg4, 144, 136),
            new MediaAsset(R.raw.swirl_136x144_mpeg4, 136, 144),
            new MediaAsset(R.raw.swirl_132x130_mpeg4, 132, 130),
            new MediaAsset(R.raw.swirl_130x132_mpeg4, 130, 132));

    private static MediaAssets H264_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_AVC,
            new MediaAsset(R.raw.swirl_128x128_h264, 128, 128),
            new MediaAsset(R.raw.swirl_144x136_h264, 144, 136),
            new MediaAsset(R.raw.swirl_136x144_h264, 136, 144),
            new MediaAsset(R.raw.swirl_132x130_h264, 132, 130),
            new MediaAsset(R.raw.swirl_130x132_h264, 130, 132));

    private static MediaAssets H265_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_HEVC,
            new MediaAsset(R.raw.swirl_128x128_h265, 128, 128),
            new MediaAsset(R.raw.swirl_144x136_h265, 144, 136),
            new MediaAsset(R.raw.swirl_136x144_h265, 136, 144),
            new MediaAsset(R.raw.swirl_132x130_h265, 132, 130),
            new MediaAsset(R.raw.swirl_130x132_h265, 130, 132));

    private static MediaAssets VP8_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_VP8,
            new MediaAsset(R.raw.swirl_128x128_vp8, 128, 128),
            new MediaAsset(R.raw.swirl_144x136_vp8, 144, 136),
            new MediaAsset(R.raw.swirl_136x144_vp8, 136, 144),
            new MediaAsset(R.raw.swirl_132x130_vp8, 132, 130),
            new MediaAsset(R.raw.swirl_130x132_vp8, 130, 132));

    private static MediaAssets VP9_ASSETS = new MediaAssets(
            MediaFormat.MIMETYPE_VIDEO_VP9,
            new MediaAsset(R.raw.swirl_128x128_vp9, 128, 128),
            new MediaAsset(R.raw.swirl_144x136_vp9, 144, 136),
            new MediaAsset(R.raw.swirl_136x144_vp9, 136, 144),
            new MediaAsset(R.raw.swirl_132x130_vp9, 132, 130),
            new MediaAsset(R.raw.swirl_130x132_vp9, 130, 132));

    static final float SWIRL_FPS = 12.f;

    class Decoder {
        final private String mName;
        final private String mMime;
        final private VideoCapabilities mCaps;
        final private ArrayList<MediaAsset> mAssets;

        boolean isFlexibleFormatSupported(CodecCapabilities caps) {
            for (int c : caps.colorFormats) {
                if (c == COLOR_FormatYUV420Flexible) {
                    return true;
                }
            }
            return false;
        }

        Decoder(String name, MediaAssets assets, CodecCapabilities caps) {
            mName = name;
            mMime = assets.getMime();
            mCaps = caps.getVideoCapabilities();
            mAssets = new ArrayList<MediaAsset>();

            for (MediaAsset asset : assets.getAssets()) {
                if (mCaps.areSizeAndRateSupported(asset.getWidth(), asset.getHeight(), SWIRL_FPS)
                        && isFlexibleFormatSupported(caps)) {
                    mAssets.add(asset);
                }
            }
        }

        public boolean videoDecode(int mode, boolean checkSwirl) {
            boolean skipped = true;
            for (MediaAsset asset: mAssets) {
                // TODO: loop over all supported image formats
                int imageFormat = ImageFormat.YUV_420_888;
                int colorFormat = COLOR_FormatYUV420Flexible;
                videoDecode(asset, imageFormat, colorFormat, mode, checkSwirl);
                skipped = false;
            }
            return skipped;
        }

        private void videoDecode(
                MediaAsset asset, int imageFormat, int colorFormat, int mode, boolean checkSwirl) {
            int video = asset.getResource();
            int width = asset.getWidth();
            int height = asset.getHeight();

            if (DEBUG) Log.d(TAG, "videoDecode " + mName + " " + width + "x" + height);

            MediaCodec decoder = null;
            AssetFileDescriptor vidFD = null;

            MediaExtractor extractor = null;
            File tmpFile = null;
            InputStream is = null;
            FileOutputStream os = null;
            MediaFormat mediaFormat = null;
            try {
                extractor = new MediaExtractor();

                try {
                    vidFD = mResources.openRawResourceFd(video);
                    extractor.setDataSource(
                            vidFD.getFileDescriptor(), vidFD.getStartOffset(), vidFD.getLength());
                } catch (NotFoundException e) {
                    // resource is compressed, uncompress locally
                    String tmpName = "tempStream";
                    tmpFile = File.createTempFile(tmpName, null, mContext.getCacheDir());
                    is = mResources.openRawResource(video);
                    os = new FileOutputStream(tmpFile);
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = is.read(buf, 0, buf.length)) > 0) {
                        os.write(buf, 0, len);
                    }
                    os.close();
                    is.close();

                    extractor.setDataSource(tmpFile.getAbsolutePath());
                }

                mediaFormat = extractor.getTrackFormat(0);
                mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);

                // Create decoder
                decoder = MediaCodec.createByCodecName(mName);
                assertNotNull("couldn't create decoder" + mName, decoder);

                decodeFramesToImage(
                        decoder, extractor, mediaFormat,
                        width, height, imageFormat, mode, checkSwirl);

                decoder.stop();
                if (vidFD != null) {
                    vidFD.close();
                }
            } catch (Throwable e) {
                throw new RuntimeException("while " + mName + " decoding "
                        + mResources.getResourceEntryName(video) + ": " + mediaFormat, e);
            } finally {
                if (decoder != null) {
                    decoder.release();
                }
                if (extractor != null) {
                    extractor.release();
                }
                if (tmpFile != null) {
                    tmpFile.delete();
                }
            }
        }
    }

    private Decoder[] decoders(MediaAssets assets, boolean goog) {
        String mime = assets.getMime();
        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        ArrayList<Decoder> result = new ArrayList<Decoder>();

        for (MediaCodecInfo info : mcl.getCodecInfos()) {
            if (info.isEncoder()
                    || info.getName().toLowerCase().startsWith("omx.google.") != goog) {
                continue;
            }
            CodecCapabilities caps = null;
            try {
                caps = info.getCapabilitiesForType(mime);
            } catch (IllegalArgumentException e) { // mime is not supported
                continue;
            }
            assertNotNull(info.getName() + " capabilties for " + mime + " returned null", caps);
            result.add(new Decoder(info.getName(), assets, caps));
        }
        return result.toArray(new Decoder[result.size()]);
    }

    private Decoder[] goog(MediaAssets assets) {
        return decoders(assets, true /* goog */);
    }

    private Decoder[] other(MediaAssets assets) {
        return decoders(assets, false /* goog */);
    }

    private Decoder[] googH265()  { return goog(H265_ASSETS); }
    private Decoder[] googH264()  { return goog(H264_ASSETS); }
    private Decoder[] googH263()  { return goog(H263_ASSETS); }
    private Decoder[] googMpeg4() { return goog(MPEG4_ASSETS); }
    private Decoder[] googVP8()   { return goog(VP8_ASSETS); }
    private Decoder[] googVP9()   { return goog(VP9_ASSETS); }

    private Decoder[] otherH265()  { return other(H265_ASSETS); }
    private Decoder[] otherH264()  { return other(H264_ASSETS); }
    private Decoder[] otherH263()  { return other(H263_ASSETS); }
    private Decoder[] otherMpeg4() { return other(MPEG4_ASSETS); }
    private Decoder[] otherVP8()   { return other(VP8_ASSETS); }
    private Decoder[] otherVP9()   { return other(VP9_ASSETS); }

    public void testGoogH265Image()   { swirlTest(googH265(),   MODE_IMAGE); }
    public void testGoogH264Image()   { swirlTest(googH264(),   MODE_IMAGE); }
    public void testGoogH263Image()   { swirlTest(googH263(),   MODE_IMAGE); }
    public void testGoogMpeg4Image()  { swirlTest(googMpeg4(),  MODE_IMAGE); }
    public void testGoogVP8Image()    { swirlTest(googVP8(),    MODE_IMAGE); }
    public void testGoogVP9Image()    { swirlTest(googVP9(),    MODE_IMAGE); }

    public void testOtherH265Image()  { swirlTest(otherH265(),  MODE_IMAGE); }
    public void testOtherH264Image()  { swirlTest(otherH264(),  MODE_IMAGE); }
    public void testOtherH263Image()  { swirlTest(otherH263(),  MODE_IMAGE); }
    public void testOtherMpeg4Image() { swirlTest(otherMpeg4(), MODE_IMAGE); }
    public void testOtherVP8Image()   { swirlTest(otherVP8(),   MODE_IMAGE); }
    public void testOtherVP9Image()   { swirlTest(otherVP9(),   MODE_IMAGE); }

    public void testGoogH265ImageReader()   { swirlTest(googH265(),   MODE_IMAGEREADER); }
    public void testGoogH264ImageReader()   { swirlTest(googH264(),   MODE_IMAGEREADER); }
    public void testGoogH263ImageReader()   { swirlTest(googH263(),   MODE_IMAGEREADER); }
    public void testGoogMpeg4ImageReader()  { swirlTest(googMpeg4(),  MODE_IMAGEREADER); }
    public void testGoogVP8ImageReader()    { swirlTest(googVP8(),    MODE_IMAGEREADER); }
    public void testGoogVP9ImageReader()    { swirlTest(googVP9(),    MODE_IMAGEREADER); }

    public void testOtherH265ImageReader()  { swirlTest(otherH265(),  MODE_IMAGEREADER); }
    public void testOtherH264ImageReader()  { swirlTest(otherH264(),  MODE_IMAGEREADER); }
    public void testOtherH263ImageReader()  { swirlTest(otherH263(),  MODE_IMAGEREADER); }
    public void testOtherMpeg4ImageReader() { swirlTest(otherMpeg4(), MODE_IMAGEREADER); }
    public void testOtherVP8ImageReader()   { swirlTest(otherVP8(),   MODE_IMAGEREADER); }
    public void testOtherVP9ImageReader()   { swirlTest(otherVP9(),   MODE_IMAGEREADER); }

    /**
     * Test ImageReader with 480x360 non-google AVC decoding for flexible yuv format
     */
    public void testHwAVCDecode360pForFlexibleYuv() throws Exception {
        Decoder[] decoders = other(new MediaAssets(
                MediaFormat.MIMETYPE_VIDEO_AVC,
                new MediaAsset(
                        R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
                        480 /* width */, 360 /* height */)));

        decodeTest(decoders, MODE_IMAGEREADER, false /* checkSwirl */);
    }

    /**
     * Test ImageReader with 480x360 google (SW) AVC decoding for flexible yuv format
     */
    public void testSwAVCDecode360pForFlexibleYuv() throws Exception {
        Decoder[] decoders = goog(new MediaAssets(
                MediaFormat.MIMETYPE_VIDEO_AVC,
                new MediaAsset(
                        R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
                        480 /* width */, 360 /* height */)));

        decodeTest(decoders, MODE_IMAGEREADER, false /* checkSwirl */);
    }

    private void swirlTest(Decoder[] decoders, int mode) {
        decodeTest(decoders, mode, true /* checkSwirl */);
    }

    private void decodeTest(Decoder[] decoders, int mode, boolean checkSwirl) {
        try {
            boolean skipped = true;
            for (Decoder codec : decoders) {
                if (codec.videoDecode(mode, checkSwirl)) {
                    skipped = false;
                }
            }
            if (skipped) {
                MediaUtils.skipTest("decoder does not any of the input files");
            }
        } finally {
            closeImageReader();
        }
    }

    private static class ImageListener implements ImageReader.OnImageAvailableListener {
        private final LinkedBlockingQueue<Image> mQueue =
                new LinkedBlockingQueue<Image>();

        @Override
        public void onImageAvailable(ImageReader reader) {
            try {
                mQueue.put(reader.acquireNextImage());
            } catch (InterruptedException e) {
                throw new UnsupportedOperationException(
                        "Can't handle InterruptedException in onImageAvailable");
            }
        }

        /**
         * Get an image from the image reader.
         *
         * @param timeout Timeout value for the wait.
         * @return The image from the image reader.
         */
        public Image getImage(long timeout) throws InterruptedException {
            Image image = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
            assertNotNull("Wait for an image timed out in " + timeout + "ms", image);
            return image;
        }
    }

    /**
     * Decode video frames to image reader.
     */
    private void decodeFramesToImage(
            MediaCodec decoder, MediaExtractor extractor, MediaFormat mediaFormat,
            int width, int height, int imageFormat, int mode, boolean checkSwirl)
            throws InterruptedException {
        ByteBuffer[] decoderInputBuffers;
        ByteBuffer[] decoderOutputBuffers;

        // Configure decoder.
        if (VERBOSE) Log.v(TAG, "stream format: " + mediaFormat);
        if (mode == MODE_IMAGEREADER) {
            createImageReader(width, height, imageFormat, MAX_NUM_IMAGES, mImageListener);
            decoder.configure(mediaFormat, mReaderSurface, null /* crypto */, 0 /* flags */);
        } else {
            assertEquals(mode, MODE_IMAGE);
            decoder.configure(mediaFormat, null /* surface */, null /* crypto */, 0 /* flags */);
        }

        decoder.start();
        decoderInputBuffers = decoder.getInputBuffers();
        decoderOutputBuffers = decoder.getOutputBuffers();
        extractor.selectTrack(0);

        // Start decoding and get Image, only test the first NUM_FRAME_DECODED frames.
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        boolean sawInputEOS = false;
        boolean sawOutputEOS = false;
        int outputFrameCount = 0;
        while (!sawOutputEOS && outputFrameCount < NUM_FRAME_DECODED) {
            if (VERBOSE) Log.v(TAG, "loop:" + outputFrameCount);
            // Feed input frame.
            if (!sawInputEOS) {
                int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
                if (inputBufIndex >= 0) {
                    ByteBuffer dstBuf = decoderInputBuffers[inputBufIndex];
                    int sampleSize =
                        extractor.readSampleData(dstBuf, 0 /* offset */);

                    if (VERBOSE) Log.v(TAG, "queue a input buffer, idx/size: "
                        + inputBufIndex + "/" + sampleSize);

                    long presentationTimeUs = 0;

                    if (sampleSize < 0) {
                        if (VERBOSE) Log.v(TAG, "saw input EOS.");
                        sawInputEOS = true;
                        sampleSize = 0;
                    } else {
                        presentationTimeUs = extractor.getSampleTime();
                    }

                    decoder.queueInputBuffer(
                            inputBufIndex,
                            0 /* offset */,
                            sampleSize,
                            presentationTimeUs,
                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);

                    if (!sawInputEOS) {
                        extractor.advance();
                    }
                }
            }

            // Get output frame
            int res = decoder.dequeueOutputBuffer(info, DEFAULT_TIMEOUT_US);
            if (VERBOSE) Log.v(TAG, "got a buffer: " + info.size + "/" + res);
            if (res == MediaCodec.INFO_TRY_AGAIN_LATER) {
                // no output available yet
                if (VERBOSE) Log.v(TAG, "no output frame available");
            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                // decoder output buffers changed, need update.
                if (VERBOSE) Log.v(TAG, "decoder output buffers changed");
                decoderOutputBuffers = decoder.getOutputBuffers();
            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                // this happens before the first frame is returned.
                MediaFormat outFormat = decoder.getOutputFormat();
                if (VERBOSE) Log.v(TAG, "decoder output format changed: " + outFormat);
            } else if (res < 0) {
                // Should be decoding error.
                fail("unexpected result from deocder.dequeueOutputBuffer: " + res);
            } else {
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    sawOutputEOS = true;
                }

                // res >= 0: normal decoding case, copy the output buffer.
                // Will use it as reference to valid the ImageReader output
                // Some decoders output a 0-sized buffer at the end. Ignore those.
                boolean doRender = (info.size != 0);

                if (doRender) {
                    outputFrameCount++;
                    String fileName = DEBUG_FILE_NAME_BASE + MediaUtils.getTestName()
                            + (mode == MODE_IMAGE ? "_image_" : "_reader_")
                            + width + "x" + height + "_" + outputFrameCount + ".yuv";

                    Image image = null;
                    try {
                        if (mode == MODE_IMAGE) {
                            image = decoder.getOutputImage(res);
                        } else {
                            decoder.releaseOutputBuffer(res, doRender);
                            res = -1;
                            // Read image and verify
                            image = mImageListener.getImage(WAIT_FOR_IMAGE_TIMEOUT_MS);
                        }
                        validateImage(image, width, height, imageFormat, fileName);

                        if (checkSwirl) {
                            try {
                                validateSwirl(image);
                            } catch (Throwable e) {
                                dumpFile(fileName, getDataFromImage(image));
                                throw e;
                            }
                        }
                    } finally {
                        if (image != null) {
                            image.close();
                        }
                    }
                }

                if (res >= 0) {
                    decoder.releaseOutputBuffer(res, false /* render */);
                }
            }
        }
    }

    /**
     * Validate image based on format and size.
     *
     * @param image The image to be validated.
     * @param width The image width.
     * @param height The image height.
     * @param format The image format.
     * @param filePath The debug dump file path, null if don't want to dump to file.
     */
    public static void validateImage(
            Image image, int width, int height, int format, String filePath) {
        if (VERBOSE) {
            Plane[] imagePlanes = image.getPlanes();
            Log.v(TAG, "Image " + filePath + " Info:");
            Log.v(TAG, "first plane pixelstride " + imagePlanes[0].getPixelStride());
            Log.v(TAG, "first plane rowstride " + imagePlanes[0].getRowStride());
            Log.v(TAG, "Image timestamp:" + image.getTimestamp());
        }

        assertNotNull("Input image is invalid", image);
        assertEquals("Format doesn't match", format, image.getFormat());
        assertEquals("Width doesn't match", width, image.getCropRect().width());
        assertEquals("Height doesn't match", height, image.getCropRect().height());

        if(VERBOSE) Log.v(TAG, "validating Image");
        byte[] data = getDataFromImage(image);
        assertTrue("Invalid image data", data != null && data.length > 0);

        validateYuvData(data, width, height, format, image.getTimestamp());

        if (VERBOSE && filePath != null) {
            dumpFile(filePath, data);
        }
    }

    private static void validateSwirl(Image image) {
        Rect crop = image.getCropRect();
        final int NUM_SIDES = 4;
        final int step = 8;      // the width of the layers
        long[][] rawStats = new long[NUM_SIDES][10];
        int[][] colors = new int[][] {
            { 111, 96, 204 }, { 178, 27, 174 }, { 100, 192, 92 }, { 106, 117, 62 }
        };

        // successively accumulate statistics for each layer of the swirl
        // by using overlapping rectangles, and the observation that
        // layer_i = rectangle_i - rectangle_(i+1)
        int lastLayer = 0;
        int layer = 0;
        boolean lastLayerValid = false;
        for (int pos = 0; ; pos += step) {
            Rect area = new Rect(pos - step, pos, crop.width() / 2, crop.height() + 2 * step - pos);
            if (area.isEmpty()) {
                break;
            }
            area.offset(crop.left, crop.top);
            area.intersect(crop);
            for (int lr = 0; lr < 2; ++lr) {
                long[] oneStat = CodecUtils.getRawStats(image, area);
                if (VERBOSE) Log.v(TAG, "area=" + area + ", layer=" + layer + ", last="
                                    + lastLayer + ": " + Arrays.toString(oneStat));
                for (int i = 0; i < oneStat.length; i++) {
                    rawStats[layer][i] += oneStat[i];
                    if (lastLayerValid) {
                        rawStats[lastLayer][i] -= oneStat[i];
                    }
                }
                if (VERBOSE && lastLayerValid) {
                    Log.v(TAG, "layer-" + lastLayer + ": " + Arrays.toString(rawStats[lastLayer]));
                    Log.v(TAG, Arrays.toString(CodecUtils.Raw2YUVStats(rawStats[lastLayer])));
                }
                // switch to the opposite side
                layer ^= 2;      // NUM_SIDES / 2
                lastLayer ^= 2;  // NUM_SIDES / 2
                area.offset(crop.centerX() - area.left, 2 * (crop.centerY() - area.centerY()));
            }

            lastLayer = layer;
            lastLayerValid = true;
            layer = (layer + 1) % NUM_SIDES;
        }

        for (layer = 0; layer < NUM_SIDES; ++layer) {
            float[] stats = CodecUtils.Raw2YUVStats(rawStats[layer]);
            if (DEBUG) Log.d(TAG, "layer-" + layer + ": " + Arrays.toString(stats));
            if (VERBOSE) Log.v(TAG, Arrays.toString(rawStats[layer]));

            // check layer uniformity
            for (int i = 0; i < 3; i++) {
                assertTrue("color of layer-" + layer + " is not uniform: "
                        + Arrays.toString(stats),
                        stats[3 + i] < COLOR_STDEV_ALLOWANCE);
            }

            // check layer color
            for (int i = 0; i < 3; i++) {
                assertTrue("color of layer-" + layer + " mismatches target "
                        + Arrays.toString(colors[layer]) + " vs "
                        + Arrays.toString(Arrays.copyOf(stats, 3)),
                        Math.abs(stats[i] - colors[layer][i]) < COLOR_DELTA_ALLOWANCE);
            }
        }
    }

    private static void validateYuvData(byte[] yuvData, int width, int height, int format,
            long ts) {

        assertTrue("YUV format must be one of the YUV_420_888, NV21, or YV12",
                format == ImageFormat.YUV_420_888 ||
                format == ImageFormat.NV21 ||
                format == ImageFormat.YV12);

        if (VERBOSE) Log.v(TAG, "Validating YUV data");
        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);
    }

    private static void checkYuvFormat(int format) {
        if ((format != ImageFormat.YUV_420_888) &&
                (format != ImageFormat.NV21) &&
                (format != ImageFormat.YV12)) {
            fail("Wrong formats: " + format);
        }
    }
    /**
     * <p>Check android image format validity for an image, only support below formats:</p>
     *
     * <p>Valid formats are YUV_420_888/NV21/YV12 for video decoder</p>
     */
    private static void checkAndroidImageFormat(Image image) {
        int format = image.getFormat();
        Plane[] planes = image.getPlanes();
        switch (format) {
            case ImageFormat.YUV_420_888:
            case ImageFormat.NV21:
            case ImageFormat.YV12:
                assertEquals("YUV420 format Images should have 3 planes", 3, planes.length);
                break;
            default:
                fail("Unsupported Image Format: " + format);
        }
    }

    /**
     * Get a byte array image data from an Image object.
     * <p>
     * Read data from all planes of an Image into a contiguous unpadded,
     * unpacked 1-D linear byte array, such that it can be write into disk, or
     * accessed by software conveniently. It supports YUV_420_888/NV21/YV12
     * input Image format.
     * </p>
     * <p>
     * For YUV_420_888/NV21/YV12/Y8/Y16, it returns a byte array that contains
     * the Y plane data first, followed by U(Cb), V(Cr) planes if there is any
     * (xstride = width, ystride = height for chroma and luma components).
     * </p>
     */
    private static byte[] getDataFromImage(Image image) {
        assertNotNull("Invalid image:", image);
        Rect crop = image.getCropRect();
        int format = image.getFormat();
        int width = crop.width();
        int height = crop.height();
        int rowStride, pixelStride;
        byte[] data = null;

        // Read image data
        Plane[] planes = image.getPlanes();
        assertTrue("Fail to get image planes", planes != null && planes.length > 0);

        // Check image validity
        checkAndroidImageFormat(image);

        ByteBuffer buffer = null;

        int offset = 0;
        data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
        byte[] rowData = new byte[planes[0].getRowStride()];
        if(VERBOSE) Log.v(TAG, "get data from " + planes.length + " planes");
        for (int i = 0; i < planes.length; i++) {
            int shift = (i == 0) ? 0 : 1;
            buffer = planes[i].getBuffer();
            assertNotNull("Fail to get bytebuffer from plane", buffer);
            rowStride = planes[i].getRowStride();
            pixelStride = planes[i].getPixelStride();
            assertTrue("pixel stride " + pixelStride + " is invalid", pixelStride > 0);
            if (VERBOSE) {
                Log.v(TAG, "pixelStride " + pixelStride);
                Log.v(TAG, "rowStride " + rowStride);
                Log.v(TAG, "width " + width);
                Log.v(TAG, "height " + height);
            }
            // For multi-planar yuv images, assuming yuv420 with 2x2 chroma subsampling.
            int w = crop.width() >> shift;
            int h = crop.height() >> shift;
            buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
            assertTrue("rowStride " + rowStride + " should be >= width " + w , rowStride >= w);
            for (int row = 0; row < h; row++) {
                int bytesPerPixel = ImageFormat.getBitsPerPixel(format) / 8;
                int length;
                if (pixelStride == bytesPerPixel) {
                    // Special case: optimized read of the entire row
                    length = w * bytesPerPixel;
                    buffer.get(data, offset, length);
                    offset += length;
                } else {
                    // Generic case: should work for any pixelStride but slower.
                    // Use intermediate buffer to avoid read byte-by-byte from
                    // DirectByteBuffer, which is very bad for performance
                    length = (w - 1) * pixelStride + bytesPerPixel;
                    buffer.get(rowData, 0, length);
                    for (int col = 0; col < w; col++) {
                        data[offset++] = rowData[col * pixelStride];
                    }
                }
                // Advance buffer the remainder of the row stride
                if (row < h - 1) {
                    buffer.position(buffer.position() + rowStride - length);
                }
            }
            if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
        }
        return data;
    }

    private static void dumpFile(String fileName, byte[] data) {
        assertNotNull("fileName must not be null", fileName);
        assertNotNull("data must not be null", data);

        FileOutputStream outStream;
        try {
            Log.v(TAG, "output will be saved as " + fileName);
            outStream = new FileOutputStream(fileName);
        } catch (IOException ioe) {
            throw new RuntimeException("Unable to create debug output file " + fileName, ioe);
        }

        try {
            outStream.write(data);
            outStream.close();
        } catch (IOException ioe) {
            throw new RuntimeException("failed writing data to file " + fileName, ioe);
        }
    }

    private void createImageReader(
            int width, int height, int format, int maxNumImages,
            ImageReader.OnImageAvailableListener listener)  {
        closeImageReader();

        mReader = ImageReader.newInstance(width, height, format, maxNumImages);
        mReaderSurface = mReader.getSurface();
        mReader.setOnImageAvailableListener(listener, mHandler);
        if (VERBOSE) {
            Log.v(TAG, String.format("Created ImageReader size (%dx%d), format %d", width, height,
                    format));
        }
    }

    /**
     * Close the pending images then close current active {@link ImageReader} object.
     */
    private void closeImageReader() {
        if (mReader != null) {
            try {
                // Close all possible pending images first.
                Image image = mReader.acquireLatestImage();
                if (image != null) {
                    image.close();
                }
            } finally {
                mReader.close();
                mReader = null;
            }
        }
    }
}
