Merge "Invalidate transitions when the start time or duration of an effect or overlay changes."
diff --git a/media/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
index ef0aeb1..8fd0d27 100755
--- a/media/java/android/media/videoeditor/Effect.java
+++ b/media/java/android/media/videoeditor/Effect.java
@@ -76,7 +76,7 @@
 

     /**

      * Set the duration of the effect. If a preview or export is in progress,

-     * then this change is effective for next preview or export session. s

+     * then this change is effective for next preview or export session.

      *

      * @param durationMs of the effect in milliseconds

      */

@@ -85,9 +85,10 @@
             throw new IllegalArgumentException("Duration is too large");

         }

 

+        final long oldDurationMs = mDurationMs;

         mDurationMs = durationMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

@@ -111,9 +112,10 @@
             throw new IllegalArgumentException("Start time is too large");

         }

 

+        final long oldStartTimeMs = mStartTimeMs;

         mStartTimeMs = startTimeMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

@@ -134,10 +136,13 @@
             throw new IllegalArgumentException("Invalid start time or duration");

         }

 

+        final long oldStartTimeMs = mStartTimeMs;

+        final long oldDurationMs = mDurationMs;

+

         mStartTimeMs = startTimeMs;

         mDurationMs = durationMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index a4b0770..fa8d61b 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -242,15 +242,49 @@
      */

     @Override

     void invalidateTransitions(long startTimeMs, long durationMs) {

-        // Check if the effect overlaps with the beginning and end transitions

+        // Check if the item overlaps with the beginning and end transitions

         if (mBeginTransition != null) {

-            if (startTimeMs < mBeginTransition.getDuration()) {

+            if (isOverlapping(startTimeMs, durationMs, 0, mBeginTransition.getDuration())) {

                 mBeginTransition.invalidate();

             }

         }

 

         if (mEndTransition != null) {

-            if (startTimeMs + durationMs > mDurationMs - mEndTransition.getDuration()) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+            if (isOverlapping(startTimeMs, durationMs,

+                    getDuration() - transitionDurationMs, transitionDurationMs)) {

+                mEndTransition.invalidate();

+            }

+        }

+    }

+

+    /*

+     * {@inheritDoc}

+     */

+    @Override

+    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();

+            // If the start time has changed and if the old or the new item

+            // overlaps with the begin transition, invalidate the transition.

+            if (oldStartTimeMs != newStartTimeMs &&

+                    (isOverlapping(oldStartTimeMs, oldDurationMs, 0, transitionDurationMs) ||

+                    isOverlapping(newStartTimeMs, newDurationMs, 0, transitionDurationMs))) {

+                mBeginTransition.invalidate();

+            }

+        }

+

+        if (mEndTransition != null) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+            // If the start time + duration has changed and if the old or the new

+            // item overlaps the end transition, invalidate the transition/

+            if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs &&

+                    (isOverlapping(oldStartTimeMs, oldDurationMs,

+                            mDurationMs - transitionDurationMs, transitionDurationMs) ||

+                    isOverlapping(newStartTimeMs, newDurationMs,

+                            mDurationMs - transitionDurationMs, transitionDurationMs))) {

                 mEndTransition.invalidate();

             }

         }

diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index 12f6084..20fd6c9 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -455,6 +455,40 @@
     abstract void invalidateTransitions(long startTimeMs, long durationMs);

 

     /**

+     * Invalidate the start and end transitions if necessary. This method is

+     * typically called when the start time and/or duration of an overlay or

+     * effect is changing.

+     *

+     * @param oldStartTimeMs The old start time of the effect or overlay

+     * @param oldDurationMs The old duration of the effect or overlay

+     * @param newStartTimeMs The new start time of the effect or overlay

+     * @param newDurationMs The new duration of the effect or overlay

+     */

+    abstract void invalidateTransitions(long oldStartTimeMs, long oldDurationMs,

+            long newStartTimeMs, long newDurationMs);

+

+    /**

+     * Check if two items overlap in time

+     *

+     * @param startTimeMs1 Item 1 start time

+     * @param durationMs1 Item 1 duration

+     * @param startTimeMs2 Item 2 start time

+     * @param durationMs2 Item 2 end time

+     *

+     * @return true if the two items overlap

+     */

+    protected boolean isOverlapping(long startTimeMs1, long durationMs1,

+            long startTimeMs2, long durationMs2) {

+       if (startTimeMs1 + durationMs1 <= startTimeMs2) {

+           return false;

+       } else if (startTimeMs1 >= startTimeMs2 + durationMs2) {

+           return false;

+       }

+

+       return true;

+    }

+

+    /**

      * Adjust the duration transitions.

      */

     protected void adjustTransitions() {

diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index 745b00a..cb835b5 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -218,15 +218,52 @@
      */

     @Override

     void invalidateTransitions(long startTimeMs, long durationMs) {

-        // Check if the effect overlaps with the beginning and end transitions

+        // Check if the item overlaps with the beginning and end transitions

         if (mBeginTransition != null) {

-            if (startTimeMs < mBeginTransition.getDuration()) {

+            if (isOverlapping(startTimeMs, durationMs,

+                    mBeginBoundaryTimeMs, mBeginTransition.getDuration())) {

                 mBeginTransition.invalidate();

             }

         }

 

         if (mEndTransition != null) {

-            if (startTimeMs + durationMs > mEndBoundaryTimeMs - mEndTransition.getDuration()) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+            if (isOverlapping(startTimeMs, durationMs,

+                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs)) {

+                mEndTransition.invalidate();

+            }

+        }

+    }

+

+    /*

+     * {@inheritDoc}

+     */

+    @Override

+    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();

+            // If the start time has changed and if the old or the new item

+            // overlaps with the begin transition, invalidate the transition.

+            if (oldStartTimeMs != newStartTimeMs &&

+                    (isOverlapping(oldStartTimeMs, oldDurationMs,

+                            mBeginBoundaryTimeMs, transitionDurationMs) ||

+                    isOverlapping(newStartTimeMs, newDurationMs,

+                            mBeginBoundaryTimeMs, transitionDurationMs))) {

+                mBeginTransition.invalidate();

+            }

+        }

+

+        if (mEndTransition != null) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+            // If the start time + duration has changed and if the old or the new

+            // item overlaps the end transition, invalidate the transition/

+            if (oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs &&

+                    (isOverlapping(oldStartTimeMs, oldDurationMs,

+                            mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs) ||

+                    isOverlapping(newStartTimeMs, newDurationMs,

+                            mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs))) {

                 mEndTransition.invalidate();

             }

         }

diff --git a/media/java/android/media/videoeditor/Overlay.java b/media/java/android/media/videoeditor/Overlay.java
index e43f229..0174ba8 100755
--- a/media/java/android/media/videoeditor/Overlay.java
+++ b/media/java/android/media/videoeditor/Overlay.java
@@ -96,9 +96,10 @@
             throw new IllegalArgumentException("Duration is too large");

         }

 

+        final long oldDurationMs = mDurationMs;

         mDurationMs = durationMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

@@ -120,9 +121,10 @@
             throw new IllegalArgumentException("Start time is too large");

         }

 

+        final long oldStartTimeMs = mStartTimeMs;

         mStartTimeMs = startTimeMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

@@ -136,10 +138,13 @@
             throw new IllegalArgumentException("Invalid start time or duration");

         }

 

+        final long oldStartTimeMs = mStartTimeMs;

+        final long oldDurationMs = mDurationMs;

+

         mStartTimeMs = startTimeMs;

         mDurationMs = durationMs;

 

-        mMediaItem.invalidateTransitions(mStartTimeMs, mDurationMs);

+        mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);

     }

 

     /**

diff --git a/media/java/android/media/videoeditor/WaveformData.java b/media/java/android/media/videoeditor/WaveformData.java
index b53bd7d..5791046 100644
--- a/media/java/android/media/videoeditor/WaveformData.java
+++ b/media/java/android/media/videoeditor/WaveformData.java
@@ -16,6 +16,8 @@
 
 package android.media.videoeditor;
 
+import java.io.IOException;
+
 /**
  * Class which describes the waveform data of an audio track. The gain values
  * represent the average gain for an audio frame. For audio codecs which do
@@ -33,7 +35,7 @@
      * This constructor shall not be used
      */
     @SuppressWarnings("unused")
-    private WaveformData() {
+    private WaveformData() throws IOException {
         mFrameDurationMs = 0;
         mFramesCount = 0;
         mGains = null;