From c4edeb5a60a45af874474ae7244c921a268430f1 Mon Sep 17 00:00:00 2001 From: Gil Dobjanschi Date: Wed, 19 Jan 2011 12:07:01 -0800 Subject: [PATCH] Bug fix: 368813 Transition is regenerated when overlay duration changes outside the transition Change-Id: I8217e7fe00392455427e117dc54c3461301f95c5 --- .../media/videoeditor/MediaImageItem.java | 115 +++++++++++------- .../media/videoeditor/MediaVideoItem.java | 113 +++++++++-------- 2 files changed, 137 insertions(+), 91 deletions(-) diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java index b03588fdf462f..1c028787bed07 100755 --- a/media/java/android/media/videoeditor/MediaImageItem.java +++ b/media/java/android/media/videoeditor/MediaImageItem.java @@ -93,29 +93,28 @@ public class MediaImageItem extends MediaItem { * * @throws IOException */ - public MediaImageItem(VideoEditor editor, String mediaItemId, - String filename, long durationMs, - int renderingMode) throws IOException { + public MediaImageItem(VideoEditor editor, String mediaItemId, String filename, long durationMs, + int renderingMode) throws IOException { super(editor, mediaItemId, filename, renderingMode); mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext(); mVideoEditor = ((VideoEditorImpl)editor); try { - final Properties properties = - mMANativeHelper.getMediaProperties(filename); + final Properties properties = mMANativeHelper.getMediaProperties(filename); switch (mMANativeHelper.getFileType(properties.fileType)) { case MediaProperties.FILE_JPEG: + case MediaProperties.FILE_PNG: { break; - case MediaProperties.FILE_PNG: - break; + } - default: - throw new IllegalArgumentException("Unsupported Input File Type"); + default: { + throw new IllegalArgumentException("Unsupported Input File Type"); + } } } catch (Exception e) { - throw new IllegalArgumentException("Unsupported file or file not found"); + throw new IllegalArgumentException("Unsupported file or file not found: " + filename); } /** @@ -130,13 +129,13 @@ public class MediaImageItem extends MediaItem { mDurationMs = durationMs; mDecodedFilename = String.format(mMANativeHelper.getProjectPath() + "/" + "decoded" + getId()+ ".rgb"); - final FileOutputStream fl = new FileOutputStream(mDecodedFilename); - final DataOutputStream dos = new DataOutputStream(fl); + try { mAspectRatio = mMANativeHelper.getAspectRatio(mWidth, mHeight); } catch(IllegalArgumentException e) { throw new IllegalArgumentException ("Null width and height"); } + mGeneratedClipHeight = 0; mGeneratedClipWidth = 0; @@ -146,9 +145,12 @@ public class MediaImageItem extends MediaItem { */ final Pair[] resolutions = MediaProperties.getSupportedResolutions(mAspectRatio); + /** * Get the highest resolution */ + final FileOutputStream fl = new FileOutputStream(mDecodedFilename); + final DataOutputStream dos = new DataOutputStream(fl); final Pair maxResolution = resolutions[resolutions.length - 1]; if (mHeight > maxResolution.second) { /** @@ -171,16 +173,16 @@ public class MediaImageItem extends MediaItem { int mNewHeight = 0; if ((mScaledWidth % 2 ) != 0) { mNewWidth = mScaledWidth - 1; - } - else { + } else { mNewWidth = mScaledWidth; } + if ((mScaledHeight % 2 ) != 0) { mNewHeight = mScaledHeight - 1; - } - else { + } else { mNewHeight = mScaledHeight; } + final int [] framingBuffer = new int[mNewWidth]; final ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4); IntBuffer intBuffer; @@ -195,6 +197,7 @@ public class MediaImageItem extends MediaItem { dos.write(array); tmp += 1; } + mScaledWidth = mNewWidth; mScaledHeight = mNewHeight; scaledImage.recycle(); @@ -204,10 +207,11 @@ public class MediaImageItem extends MediaItem { + "/" + "scaled" + getId()+ ".JPG"); if (!((new File(mScaledFilename)).exists())) { super.mRegenerateClip = true; - FileOutputStream f1 = new FileOutputStream(mScaledFilename); + final FileOutputStream f1 = new FileOutputStream(mScaledFilename); scaledImage.compress(Bitmap.CompressFormat.JPEG, 50,f1); f1.close(); } + mScaledWidth = scaledImage.getWidth(); mScaledHeight = scaledImage.getHeight(); @@ -215,17 +219,17 @@ public class MediaImageItem extends MediaItem { int mNewheight = 0; if ((mScaledWidth % 2 ) != 0) { mNewWidth = mScaledWidth - 1; - } - else { + } else { mNewWidth = mScaledWidth; } + if ((mScaledHeight % 2 ) != 0) { mNewheight = mScaledHeight - 1; - } - else { + } else { mNewheight = mScaledHeight; } - Bitmap imageBitmap = BitmapFactory.decodeFile(mScaledFilename); + + final Bitmap imageBitmap = BitmapFactory.decodeFile(mScaledFilename); final int [] framingBuffer = new int[mNewWidth]; ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4); IntBuffer intBuffer; @@ -240,10 +244,12 @@ public class MediaImageItem extends MediaItem { dos.write(array); tmp += 1; } + mScaledWidth = mNewWidth; mScaledHeight = mNewheight; imageBitmap.recycle(); } + fl.close(); System.gc(); } @@ -286,7 +292,7 @@ public class MediaImageItem extends MediaItem { /** * @return The file name of image which is decoded and stored - * in rgb format + * in RGB format */ String getDecodedImageFileName() { return mDecodedFilename; @@ -447,7 +453,7 @@ public class MediaImageItem extends MediaItem { * Check if the effect overlaps with the end transition */ if (effect.getStartTime() + effect.getDuration() > - mDurationMs - transitionDurationMs) { + mDurationMs - transitionDurationMs) { mEndTransition.invalidate(); break; } @@ -464,7 +470,7 @@ public class MediaImageItem extends MediaItem { * Check if the overlay overlaps with the end transition */ if (overlay.getStartTime() + overlay.getDuration() > - mDurationMs - transitionDurationMs) { + mDurationMs - transitionDurationMs) { mEndTransition.invalidate(); break; } @@ -648,23 +654,24 @@ public class MediaImageItem extends MediaItem { for (int i = 0; i < thumbnailCount; i++) { thumbnailArray[i] = thumbnail; } + return thumbnailArray; - - - } - else { + } else { if (startMs > endMs) { throw new IllegalArgumentException("Start time is greater than end time"); } + if (endMs > mDurationMs) { throw new IllegalArgumentException("End time is greater than file duration"); } + if (startMs == endMs) { Bitmap[] bitmap = new Bitmap[1]; bitmap[0] = mMANativeHelper.getPixels(getGeneratedImageClip(), width, height,startMs); return bitmap; } + return mMANativeHelper.getPixelsList(getGeneratedImageClip(), width, height,startMs,endMs,thumbnailCount); } @@ -704,31 +711,51 @@ public class MediaImageItem extends MediaItem { */ if (mBeginTransition != null) { final long transitionDurationMs = mBeginTransition.getDuration(); + final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, 0, + transitionDurationMs); + final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, 0, + transitionDurationMs); /** - * If the start time has changed and if the old or the new item - * overlaps with the begin transition, invalidate the transition. + * Invalidate transition if: + * + * 1. New item overlaps the transition, the old one did not + * 2. New item does not overlap the transition, the old one did + * 3. New and old item overlap the transition if begin or end + * time changed */ - if (((oldStartTimeMs != newStartTimeMs) - || (oldDurationMs != newDurationMs) )&& - (isOverlapping(oldStartTimeMs, oldDurationMs, 0, transitionDurationMs) || - isOverlapping(newStartTimeMs, newDurationMs, 0, - transitionDurationMs))) { + if (newOverlap != oldOverlap) { // Overlap has changed mBeginTransition.invalidate(); + } else if (newOverlap) { // Both old and new overlap + if ((oldStartTimeMs != newStartTimeMs) || + !(oldStartTimeMs + oldDurationMs > transitionDurationMs && + newStartTimeMs + newDurationMs > transitionDurationMs)) { + mBeginTransition.invalidate(); + } } } if (mEndTransition != null) { final long transitionDurationMs = mEndTransition.getDuration(); + final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, + mDurationMs - transitionDurationMs, transitionDurationMs); + final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, + mDurationMs - transitionDurationMs, transitionDurationMs); /** - * If the start time + duration has changed and if the old or the new - * item overlaps the end transition, invalidate the transition + * Invalidate transition if: + * + * 1. New item overlaps the transition, the old one did not + * 2. New item does not overlap the transition, the old one did + * 3. New and old item overlap the transition if begin or end + * time changed */ - if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs && - (isOverlapping(oldStartTimeMs, oldDurationMs, - mDurationMs - transitionDurationMs, transitionDurationMs) || - isOverlapping(newStartTimeMs, newDurationMs, - mDurationMs - transitionDurationMs, transitionDurationMs))) { + if (newOverlap != oldOverlap) { // Overlap has changed mEndTransition.invalidate(); + } else if (newOverlap) { // Both old and new overlap + if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) || + ((oldStartTimeMs > mDurationMs - transitionDurationMs) || + newStartTimeMs > mDurationMs - transitionDurationMs)) { + mEndTransition.invalidate(); + } } } } @@ -743,10 +770,12 @@ public class MediaImageItem extends MediaItem { setGeneratedImageClip(null); setRegenerateClip(true); } + if (mScaledFilename != null) { new File(mScaledFilename).delete(); mScaledFilename = null; } + if (mDecodedFilename != null) { new File(mDecodedFilename).delete(); mDecodedFilename = null; diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java index 772b360590b4e..2981b41c0b738 100755 --- a/media/java/android/media/videoeditor/MediaVideoItem.java +++ b/media/java/android/media/videoeditor/MediaVideoItem.java @@ -78,12 +78,9 @@ public class MediaVideoItem extends MediaItem { * * @throws IOException if the file cannot be opened for reading */ - public MediaVideoItem(VideoEditor editor, String mediaItemId, - String filename, - int renderingMode) - throws IOException { - this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, - 100, false, null); + public MediaVideoItem(VideoEditor editor, String mediaItemId, String filename, + int renderingMode) throws IOException { + this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null); } /** @@ -105,20 +102,22 @@ public class MediaVideoItem extends MediaItem { * @throws IOException if the file cannot be opened for reading */ MediaVideoItem(VideoEditor editor, String mediaItemId, String filename, - int renderingMode, - long beginMs, long endMs, int volumePercent, boolean muted, + int renderingMode, long beginMs, long endMs, int volumePercent, boolean muted, String audioWaveformFilename) throws IOException { super(editor, mediaItemId, filename, renderingMode); + if (editor instanceof VideoEditorImpl) { mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext(); mVideoEditor = ((VideoEditorImpl)editor); } - Properties properties = null; + + final Properties properties; try { properties = mMANativeHelper.getMediaProperties(filename); } catch ( Exception e) { - throw new IllegalArgumentException("Unsupported file or file not found"); + throw new IllegalArgumentException("Unsupported file or file not found: " + filename); } + switch (mMANativeHelper.getFileType(properties.fileType)) { case MediaProperties.FILE_3GP: break; @@ -163,8 +162,7 @@ public class MediaVideoItem extends MediaItem { mMuted = muted; mAudioWaveformFilename = audioWaveformFilename; if (audioWaveformFilename != null) { - mWaveformData = - new SoftReference( + mWaveformData = new SoftReference( new WaveformData(audioWaveformFilename)); } else { mWaveformData = null; @@ -190,9 +188,11 @@ public class MediaVideoItem extends MediaItem { if (beginMs > mDurationMs) { throw new IllegalArgumentException("setExtractBoundaries: Invalid start time"); } + if (endMs > mDurationMs) { throw new IllegalArgumentException("setExtractBoundaries: Invalid end time"); } + if ((endMs != -1) && (beginMs >= endMs) ) { throw new IllegalArgumentException("setExtractBoundaries: Start time is greater than end time"); } @@ -255,18 +255,18 @@ public class MediaVideoItem extends MediaItem { */ @Override public Bitmap getThumbnail(int width, int height, long timeMs) { - if (timeMs > mDurationMs) - { + if (timeMs > mDurationMs) { throw new IllegalArgumentException("Time Exceeds duration"); } - if (timeMs < 0) - { + + if (timeMs < 0) { throw new IllegalArgumentException("Invalid Time duration"); } - if ((width <=0) || (height <= 0)) - { + + if ((width <=0) || (height <= 0)) { throw new IllegalArgumentException("Invalid Dimensions"); } + return mMANativeHelper.getPixels(super.getFilename(), width, height,timeMs); } @@ -280,18 +280,21 @@ public class MediaVideoItem extends MediaItem { if (startMs > endMs) { throw new IllegalArgumentException("Start time is greater than end time"); } + if (endMs > mDurationMs) { throw new IllegalArgumentException("End time is greater than file duration"); } + if ((height <= 0) || (width <= 0)) { throw new IllegalArgumentException("Invalid dimension"); } + if (startMs == endMs) { - Bitmap[] bitmap = new Bitmap[1]; - bitmap[0] = mMANativeHelper.getPixels(super.getFilename(), - width, height,startMs); + final Bitmap[] bitmap = new Bitmap[1]; + bitmap[0] = mMANativeHelper.getPixels(super.getFilename(), width, height,startMs); return bitmap; } + return mMANativeHelper.getPixelsList(super.getFilename(), width, height,startMs,endMs,thumbnailCount); } @@ -324,40 +327,58 @@ public class MediaVideoItem extends MediaItem { * {@inheritDoc} */ @Override - void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, - long newStartTimeMs, + void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs, long newDurationMs) { /** * Check if the item overlaps with the beginning and end transitions */ if (mBeginTransition != null) { final long transitionDurationMs = mBeginTransition.getDuration(); + final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, + mBeginBoundaryTimeMs, transitionDurationMs); + final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, + mBeginBoundaryTimeMs, transitionDurationMs); /** - * If the start time has changed and if the old or the new item - * overlaps with the begin transition, invalidate the transition. + * Invalidate transition if: + * + * 1. New item overlaps the transition, the old one did not + * 2. New item does not overlap the transition, the old one did + * 3. New and old item overlap the transition if begin or end + * time changed */ - if (((oldStartTimeMs != newStartTimeMs) - || (oldDurationMs != newDurationMs) )&& - (isOverlapping(oldStartTimeMs, oldDurationMs, - mBeginBoundaryTimeMs, transitionDurationMs) || - isOverlapping(newStartTimeMs, newDurationMs, - mBeginBoundaryTimeMs, transitionDurationMs))) { + if (newOverlap != oldOverlap) { // Overlap has changed mBeginTransition.invalidate(); + } else if (newOverlap) { // Both old and new overlap + if ((oldStartTimeMs != newStartTimeMs) || + !(oldStartTimeMs + oldDurationMs > transitionDurationMs && + newStartTimeMs + newDurationMs > transitionDurationMs)) { + mBeginTransition.invalidate(); + } } } if (mEndTransition != null) { final long transitionDurationMs = mEndTransition.getDuration(); + final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, + mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs); + final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, + mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs); /** - * If the start time + duration has changed and if the old or the new - * item overlaps the end transition, invalidate the transition + * Invalidate transition if: + * + * 1. New item overlaps the transition, the old one did not + * 2. New item does not overlap the transition, the old one did + * 3. New and old item overlap the transition if begin or end + * time changed */ - if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs && - (isOverlapping(oldStartTimeMs, oldDurationMs, - mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs) || - isOverlapping(newStartTimeMs, newDurationMs, - mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs))) { + if (newOverlap != oldOverlap) { // Overlap has changed mEndTransition.invalidate(); + } else if (newOverlap) { // Both old and new overlap + if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) || + ((oldStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs) || + newStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs)) { + mEndTransition.invalidate(); + } } } } @@ -434,7 +455,7 @@ public class MediaVideoItem extends MediaItem { throw new IllegalArgumentException("requested time not correct"); } - Surface surface = surfaceHolder.getSurface(); + final Surface surface = surfaceHolder.getSurface(); if (surface == null) { throw new RuntimeException("Surface could not be retrieved from Surface holder"); } @@ -442,8 +463,7 @@ public class MediaVideoItem extends MediaItem { if (mFilename != null) { return mMANativeHelper.renderMediaItemPreviewFrame(surface, mFilename,timeMs,mWidth,mHeight); - } - else { + } else { return 0; } } @@ -462,7 +482,7 @@ public class MediaVideoItem extends MediaItem { * Audio track */ public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener) - throws IOException { + throws IOException { int frameDuration = 0; int sampleCount = 0; final String projectPath = mMANativeHelper.getProjectPath(); @@ -481,19 +501,17 @@ public class MediaVideoItem extends MediaItem { * Logic to get frame duration = (no. of frames per sample * 1000)/ * sampling frequency */ - if ( mMANativeHelper.getAudioCodecType(mAudioType) == + if (mMANativeHelper.getAudioCodecType(mAudioType) == MediaProperties.ACODEC_AMRNB ) { frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB*1000)/ MediaProperties.DEFAULT_SAMPLING_FREQUENCY; sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB; - } - else if ( mMANativeHelper.getAudioCodecType(mAudioType) == + } else if (mMANativeHelper.getAudioCodecType(mAudioType) == MediaProperties.ACODEC_AMRWB ) { frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)/ MediaProperties.DEFAULT_SAMPLING_FREQUENCY; sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB; - } - else if ( mMANativeHelper.getAudioCodecType(mAudioType) == + } else if (mMANativeHelper.getAudioCodecType(mAudioType) == MediaProperties.ACODEC_AAC_LC ) { frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)/ MediaProperties.DEFAULT_SAMPLING_FREQUENCY; @@ -682,5 +700,4 @@ public class MediaVideoItem extends MediaItem { return clipSettings; } - }