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