19bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava/*
29bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * Copyright (C) 2010 The Android Open Source Project
39bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava *
49bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * Licensed under the Apache License, Version 2.0 (the "License");
59bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * you may not use this file except in compliance with the License.
69bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * You may obtain a copy of the License at
79bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava *
89bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava *      http://www.apache.org/licenses/LICENSE-2.0
99bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava *
109bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * Unless required by applicable law or agreed to in writing, software
119bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * distributed under the License is distributed on an "AS IS" BASIS,
129bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * See the License for the specific language governing permissions and
149bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * limitations under the License.
159bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava */
169bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
179bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavapackage android.media.videoeditor;
189bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
199bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport android.graphics.Bitmap;
209bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport android.graphics.BitmapFactory;
219bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.io.DataOutputStream;
229bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.io.File;
239bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.io.FileOutputStream;
249bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.io.IOException;
259bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.nio.ByteBuffer;
269bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavaimport java.nio.IntBuffer;
279bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
289bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava/**
299bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * This class allows to render an "alpha blending" transition according to a
309bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * bitmap mask. The mask shows the shape of the transition all along the
319bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * duration of the transition: just before the transition, video 1 is fully
329bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * displayed. When the transition starts, as the time goes on, pixels of video 2
339bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * replace pixels of video 1 according to the gray scale pixel value of the
349bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * mask.
359bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava * {@hide}
369bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava */
379bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhavapublic class TransitionAlpha extends Transition {
389bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /** This is the input JPEG file for the mask */
399bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private final String mMaskFilename;
409bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
419bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
429bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * This is percentage (between 0 and 100) of blending between video 1 and
439bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * video 2 if this value equals 0, then the mask is strictly applied if this
449bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * value equals 100, then the mask is not at all applied (no transition
459bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * effect)
469bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
479bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private final int mBlendingPercent;
489bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
499bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
509bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * If true, this value inverts the direction of the mask: white pixels of
519bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * the mask show video 2 pixels first black pixels of the mask show video 2
529bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * pixels last.
539bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
549bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private final boolean mIsInvert;
559bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
569bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
579bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private int mWidth;
589bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private int mHeight;
599bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private String mRGBMaskFile;
609bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
619bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
629bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * An object of this type cannot be instantiated by using the default
639bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * constructor
649bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
659bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    @SuppressWarnings("unused")
669bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    private TransitionAlpha() {
679bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        this(null, null, null, 0, 0, null, 0, false);
689bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
699bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
709bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
719bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * Constructor
729bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *
739bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param transitionId The transition id
749bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param afterMediaItem The transition is applied to the end of this media
759bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *            item
769bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param beforeMediaItem The transition is applied to the beginning of this
779bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *            media item
789bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param durationMs duration of the transition in milliseconds
799bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param behavior behavior is one of the behavior defined in Transition
809bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *            class
819bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param maskFilename JPEG file name. The dimension of the image
829bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *           corresponds to 720p (16:9 aspect ratio). Mask files are
839bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *           shared between video editors and can be created in the
849bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *           projects folder (the parent folder for all projects).
859bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param blendingPercent The blending percent applied
869bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @param invert true to invert the direction of the alpha blending
879bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @throws IllegalArgumentException if behavior is not supported, or if
889bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *             direction are not supported.
899bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
909bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public TransitionAlpha(String transitionId, MediaItem afterMediaItem,
919bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            MediaItem beforeMediaItem, long durationMs, int behavior,
929bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            String maskFilename, int blendingPercent, boolean invert) {
939bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
949bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
959bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        /**
969bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava         * Generate a RGB file for the supplied mask file
979bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava         */
989bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        final BitmapFactory.Options dbo = new BitmapFactory.Options();
999bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        dbo.inJustDecodeBounds = true;
1009bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        if (!new File(maskFilename).exists())
1019bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            throw new IllegalArgumentException("File not Found " + maskFilename);
1029bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        BitmapFactory.decodeFile(maskFilename, dbo);
1039bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1049bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mWidth = dbo.outWidth;
1059bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mHeight = dbo.outHeight;
1069bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1079bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mRGBMaskFile = String.format(mNativeHelper.getProjectPath() +
1089bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                "/" + "mask" + transitionId+ ".rgb");
1099bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1109bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1119bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        FileOutputStream fl = null;
1129bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1139bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        try{
1149bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava             fl = new FileOutputStream(mRGBMaskFile);
1159bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        } catch (IOException e) {
1169bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            /* catch IO exception */
1179bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        }
1189bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        final DataOutputStream dos = new DataOutputStream(fl);
1199bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1209bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        if (fl != null) {
1219bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            /**
1229bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava             * Write to rgb file
1239bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava             */
1249bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            Bitmap imageBitmap = BitmapFactory.decodeFile(maskFilename);
1259bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            final int [] framingBuffer = new int[mWidth];
1269bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
1279bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            IntBuffer intBuffer;
1289bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1299bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            byte[] array = byteBuffer.array();
1309bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            int tmp = 0;
1319bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            while (tmp < mHeight) {
1329bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                imageBitmap.getPixels(framingBuffer, 0, mWidth, 0, tmp,mWidth, 1);
1339bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                intBuffer = byteBuffer.asIntBuffer();
1349bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                intBuffer.put(framingBuffer,0,mWidth);
1359bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                try {
1369bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                    dos.write(array);
1379bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                } catch (IOException e) {
1389bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                    /* catch file write error */
1399bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                }
1409bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                tmp += 1;
1419bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            }
1429bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1439bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            imageBitmap.recycle();
1449bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            try{
1459bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                fl.close();
1469bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            }catch (IOException e) {
1479bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava                /* file close error */
1489bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava            }
1499bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        }
1509bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1519bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        /**
1529bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava         * Capture the details
1539bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava         */
1549bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mMaskFilename = maskFilename;
1559bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mBlendingPercent = blendingPercent;
1569bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        mIsInvert = invert;
1579bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1589bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1599bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public int getRGBFileWidth() {
1609bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mWidth;
1619bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1629bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1639bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public int getRGBFileHeight() {
1649bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mHeight;
1659bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1669bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1679bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public String getPNGMaskFilename() {
1689bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mRGBMaskFile;
1699bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1709bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1719bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
1729bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * Get the blending percentage
1739bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *
1749bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @return The blending percentage
1759bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
1769bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public int getBlendingPercent() {
1779bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mBlendingPercent;
1789bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1799bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1809bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
1819bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * Get the filename of the mask.
1829bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *
1839bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @return The mask filename
1849bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
1859bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public String getMaskFilename() {
1869bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mMaskFilename;
1879bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1889bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1899bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /**
1909bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * Check if the alpha blending direction is inverted.
1919bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     *
1929bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * @return true if the direction of the alpha blending is inverted
1939bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
1949bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public boolean isInvert() {
1959bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        return mIsInvert;
1969bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
1979bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava
1989bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    /*
1999bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     * {@inheritDoc}
2009bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava     */
2019bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    @Override
2029bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    public void generate() {
2039bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava        super.generate();
2049bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava    }
2059bcedf7cf3e9c981837f2d8ec98cd118efad3f01Santosh Madhava}
206