Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fdacc8be authored by Gil Dobjanschi's avatar Gil Dobjanschi
Browse files

Initial Video Editor API

Change-Id: Iaa91e78d0e50f45ceb943bab93c4f1ea1bdee003
parent d0fa371f
Loading
Loading
Loading
Loading
+326 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.videoeditor;

import java.io.IOException;

/**
 * This class allows to handle an audio track. This audio file is mixed with the
 * audio samples of the MediaItems.
 * {@hide}
 */
public class AudioTrack {
    // Instance variables
    private final String mUniqueId;
    private final String mFilename;
    private final long mDurationMs;
    private long mStartTimeMs;
    private long mTimelineDurationMs;
    private int mVolumePercent;
    private long mBeginBoundaryTimeMs;
    private long mEndBoundaryTimeMs;
    private boolean mLoop;

    // Ducking variables
    private int mDuckingThreshold;
    private int mDuckingLowVolume;
    private boolean mIsDuckingEnabled;

    // The audio waveform filename
    private String mAudioWaveformFilename;

    /**
     * An object of this type cannot be instantiated by using the default
     * constructor
     */
    @SuppressWarnings("unused")
    private AudioTrack() throws IOException {
        this(null, null);
    }

    /**
     * Constructor
     *
     * @param audioTrackId The AudioTrack id
     * @param filename The absolute file name
     *
     * @throws IOException if file is not found
     * @throws IllegalArgumentException if file format is not supported or if
     *             the codec is not supported
     */
    public AudioTrack(String audioTrackId, String filename) throws IOException {
        mUniqueId = audioTrackId;
        mFilename = filename;
        mStartTimeMs = 0;
        // TODO: This value represents to the duration of the audio file
        mDurationMs = 300000;
        mTimelineDurationMs = mDurationMs;
        mVolumePercent = 100;

        // Play the entire audio track
        mBeginBoundaryTimeMs = 0;
        mEndBoundaryTimeMs = mDurationMs;

        // By default loop is disabled
        mLoop = false;

        // Ducking is enabled by default
        mDuckingThreshold = 0;
        mDuckingLowVolume = 0;
        mIsDuckingEnabled = true;

        // The audio waveform file is generated later
        mAudioWaveformFilename = null;
    }

    /**
     * @return The id of the media item
     */
    public String getId() {
        return mUniqueId;
    }

    /**
     * Get the filename source for this audio track.
     *
     * @return The filename as an absolute file name
     */
    public String getFilename() {
        return mFilename;
    }

    /**
     * Set the volume of this audio track as percentage of the volume in the
     * original audio source file.
     *
     * @param volumePercent Percentage of the volume to apply. If it is set to
     *            0, then volume becomes mute. It it is set to 100, then volume
     *            is same as original volume. It it is set to 200, then volume
     *            is doubled (provided that volume amplification is supported)
     *
     * @throws UnsupportedOperationException if volume amplification is requested
     *             and is not supported.
     */
    public void setVolume(int volumePercent) {
        mVolumePercent = volumePercent;
    }

    /**
     * Get the volume of the audio track as percentage of the volume in the
     * original audio source file.
     *
     * @return The volume in percentage
     */
    public int getVolume() {
        return mVolumePercent;
    }

    /**
     * Set the start time of this audio track relative to the storyboard
     * timeline. Default value is 0.
     *
     * @param startTimeMs the start time in milliseconds
     */
    public void setStartTime(long startTimeMs) {
        mStartTimeMs = startTimeMs;
    }

    /**
     * Get the start time of this audio track relative to the storyboard
     * timeline.
     *
     * @return The start time in milliseconds
     */
    public long getStartTime() {
        return mStartTimeMs;
    }

    /**
     * @return The duration in milliseconds. This value represents the audio
     *         track duration (not looped)
     */
    public long getDuration() {
        return mDurationMs;
    }

    /**
     * @return The timeline duration. If looping is enabled this value
     *         represents the duration of the looped audio track, otherwise it
     *         is the duration of the audio track (mDurationMs).
     */
    public long getTimelineDuration() {
        return mTimelineDurationMs;
    }

    /**
     * Sets the start and end marks for trimming an audio track
     *
     * @param beginMs start time in the audio track in milliseconds (relative to
     *            the beginning of the audio track)
     * @param endMs end time in the audio track in milliseconds (relative to the
     *            beginning of the audio track)
     */
    public void setExtractBoundaries(long beginMs, long endMs) {
        if (beginMs > mDurationMs) {
            throw new IllegalArgumentException("Invalid start time");
        }
        if (endMs > mDurationMs) {
            throw new IllegalArgumentException("Invalid end time");
        }

        mBeginBoundaryTimeMs = beginMs;
        mEndBoundaryTimeMs = endMs;
        if (mLoop) {
            // TODO: Compute mDurationMs (from the beginning of the loop until
            // the end of all the loops.
            mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
        } else {
            mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
        }
    }

    /**
     * @return The boundary begin time
     */
    public long getBoundaryBeginTime() {
        return mBeginBoundaryTimeMs;
    }

    /**
     * @return The boundary end time
     */
    public long getBoundaryEndTime() {
        return mEndBoundaryTimeMs;
    }

    /**
     * Enable the loop mode for this audio track. Note that only one of the
     * audio tracks in the timeline can have the loop mode enabled. When
     * looping is enabled the samples between mBeginBoundaryTimeMs and
     * mEndBoundaryTimeMs are looped.
     */
    public void enableLoop() {
        mLoop = true;
    }

    /**
     * Disable the loop mode
     */
    public void disableLoop() {
        mLoop = false;
    }

    /**
     * @return true if looping is enabled
     */
    public boolean isLooping() {
        return mLoop;
    }

    /**
     * Disable the audio duck effect
     */
    public void disableDucking() {
        mIsDuckingEnabled = false;
    }

    /**
     * TODO DEFINE
     *
     * @param threshold
     * @param lowVolume
     * @param volume
     */
    public void enableDucking(int threshold, int lowVolume, int volume) {
        mDuckingThreshold = threshold;
        mDuckingLowVolume = lowVolume;
        mIsDuckingEnabled = true;
    }

    /**
     * @return true if ducking is enabled
     */
    public boolean isDuckingEnabled() {
        return mIsDuckingEnabled;
    }

    /**
     * @return The ducking threshold
     */
    public int getDuckingThreshhold() {
        return mDuckingThreshold;
    }

    /**
     * @return The ducking low level
     */
    public int getDuckingLowVolume() {
        return mDuckingLowVolume;
    }

    /**
     * This API allows to generate a file containing the sample volume levels of
     * this audio track object. This function may take significant time and is
     * blocking. The filename can be retrieved using getAudioWaveformFilename().
     *
     * @param listener The progress listener
     *
     * @throws IOException if the output file cannot be created
     * @throws IllegalArgumentException if the audio file does not have a valid
     *             audio track
     */
    public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
            throws IOException {
        // TODO: Set mAudioWaveformFilename at the end once the extract is complete
    }

    /**
     * Get the audio waveform file name if extractAudioWaveform was successful.
     * The file format is as following:
     * <ul>
     *  <li>first 4 bytes provide the number of samples for each value, as
     *      big-endian signed</li>
     *  <li>4 following bytes is the total number of values in the file, as
     *      big-endian signed</li>
     *  <li>then, all values follow as bytes</li>
     * </ul>
     *
     * @return the name of the file, null if the file does not exist
     */
    public String getAudioWaveformFilename() {
        return mAudioWaveformFilename;
    }

    /*
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object object) {
        if (!(object instanceof AudioTrack)) {
            return false;
        }
        return mUniqueId.equals(((AudioTrack)object).mUniqueId);
    }

    /*
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return mUniqueId.hashCode();
    }
}
+119 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.videoeditor;

/**
 * This is the super class for all effects. An effect can only be applied to a
 * single media item. If one wants to apply the same effect to multiple media
 * items, multiple @{MediaItem.addEffect(Effect)} call must be invoked on each
 * of the MediaItem objects.
 * {@hide}
 */
public abstract class Effect {
    // Instance variables
    private final String mUniqueId;
    protected long mDurationMs;
    // The start time of the effect relative to the media item timeline
    protected long mStartTimeMs;

    /**
     * Default constructor
     */
    @SuppressWarnings("unused")
    private Effect() {
        mUniqueId = null;
        mStartTimeMs = 0;
        mDurationMs = 0;
    }

    /**
     * Constructor
     *
     * @param effectId The effect id
     * @param startTimeMs The start time relative to the media item to which it
     *            is applied
     * @param durationMs The effect duration in milliseconds
     */
    public Effect(String effectId, long startTimeMs, long durationMs) {
        mUniqueId = effectId;
        mStartTimeMs = startTimeMs;
        mDurationMs = durationMs;
    }

    /**
     * @return The id of the effect
     */
    public String getId() {
        return mUniqueId;
    }

    /**
     * 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
     *
     * @param durationMs of the effect in milliseconds
     */
    public void setDuration(long durationMs) {
        mDurationMs = durationMs;
    }

    /**
     * Get the duration of the effect
     *
     * @return The duration of the effect in milliseconds
     */
    public long getDuration() {
        return mDurationMs;
    }

    /**
     * Set start time of the effect. If a preview or export is in progress, then
     * this change is effective for next preview or export session.
     *
     * @param startTimeMs The start time of the effect relative to the begining
     *            of the media item in milliseconds
     */
    public void setStartTime(long startTimeMs) {
        mStartTimeMs = startTimeMs;
    }

    /**
     * @return The start time in milliseconds
     */
    public long getStartTime() {
        return mStartTimeMs;
    }

    /*
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object object) {
        if (!(object instanceof Effect)) {
            return false;
        }
        return mUniqueId.equals(((Effect)object).mUniqueId);
    }

    /*
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return mUniqueId.hashCode();
    }
}
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.videoeditor;

/**
 * This class allows to apply color on a media item.
 * {@hide}
 */
public class EffectColor extends Effect {

    /**
     * Change the video frame color to the RGB color value provided
     */
    public static final int TYPE_COLOR = 1; // color as 888 RGB
    /**
     * Change the video frame color to a gradation from RGB color (at the top of
     * the frame) to black (at the bottom of the frame).
     */
    public static final int TYPE_GRADIENT = 2;
    /**
     * Change the video frame color to sepia
     */
    public static final int TYPE_SEPIA = 3;
    /**
     * Invert the video frame color
     */
    public static final int TYPE_NEGATIVE = 4;
    /**
     * Make the video look like as if it was recorded in 50's
     */
    public static final int TYPE_FIFTIES = 5;

    // Colors for the color effect
    public static final int GREEN = 0x0000ff00;
    public static final int PINK = 0x00ff66cc;
    public static final int GRAY = 0x007f7f7f;

    // The effect type
    private final int mType;

    // The effect parameter
    private final int mParam;

    /**
     * An object of this type cannot be instantiated by using the default
     * constructor
     */
    @SuppressWarnings("unused")
    private EffectColor() {
        this(null, 0, 0, 0, 0);
    }

    /**
     * Constructor
     *
     * @param effectId The effect id
     * @param startTimeMs The start time relative to the media item to which it
     *            is applied
     * @param durationMs The duration of this effect in milliseconds
     * @param type type of the effect. type is one of: TYPE_COLOR,
     *            TYPE_GRADIENT, TYPE_SEPIA, TYPE_NEGATIVE, TYPE_FIFTIES. If
     *            type is not supported, the argument is ignored
     * @param param if type is TYPE_COLOR, param is the RGB color as 888.
     *            Otherwise, param is ignored
     */
    public EffectColor(String effectId, long startTimeMs, long durationMs,
            int type, int param) {
        super(effectId, startTimeMs, durationMs);
        mType = type;
        mParam = param;
    }

    /**
     * @return The type of this effect
     */
    public int getType() {
        return mType;
    }

    /**
     * @return the color as RGB 888 if type is TYPE_COLOR. Otherwise, ignore.
     */
    public int getParam() {
        return mParam;
    }
}
+90 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.videoeditor;

import java.io.IOException;

import android.graphics.Rect;

/**
 * This class represents a Ken Burns effect.
 * {@hide}
 */
public class EffectKenBurns extends Effect {
    // Instance variables
    private Rect mStartRect;
    private Rect mEndRect;

    /**
     * Objects of this type cannot be instantiated by using the default
     * constructor
     */
    @SuppressWarnings("unused")
    private EffectKenBurns() throws IOException {
        this(null, null, null, 0, 0);
    }

    /**
     * Constructor
     *
     * @param effectId The effect id
     * @param startRect The start rectangle
     * @param endRect The end rectangle
     * @param startTimeMs The start time
     * @param durationMs The duration of the Ken Burns effect in milliseconds
     */
    public EffectKenBurns(String effectId, Rect startRect, Rect endRect, long startTime,
            long durationMs)
            throws IOException {
        super(effectId, startTime, durationMs);

        mStartRect = startRect;
        mEndRect = endRect;
    }

    /**
     * @param startRect The start rectangle
     *
     * @throws IllegalArgumentException if start rectangle is incorrectly set.
     */
    public void setStartRect(Rect startRect) {
        mStartRect = startRect;
    }

    /**
     * @return The start rectangle
     */
    public Rect getStartRect() {
        return mStartRect;
    }

    /**
     * @param endRect The end rectangle
     *
     * @throws IllegalArgumentException if end rectangle is incorrectly set.
     */
    public void setEndRect(Rect endRect) {
        mEndRect = endRect;
    }

    /**
     * @return The end rectangle
     */
    public Rect getEndRect() {
        return mEndRect;
    }
}
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.videoeditor;

/**
 * This listener interface is used by
 * {@link MediaVideoItem#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
 * or
 * {@link AudioTrack#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
 * {@hide}
 */
public interface ExtractAudioWaveformProgressListener {
    /**
     * This method notifies the listener of the progress status of
     * an extractAudioWaveform operation.
     * This method may be called maximum 100 times for one operation.
     *
     * @param progress The progress in %. At the beginning of the operation,
     *          this value is set to 0; at the end, the value is set to 100.
     */
    public void onProgress(int progress);
}
Loading