Home | History | Annotate | Download | only in decoder
      1 /*
      2  * Copyright 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package androidx.media.filterfw.decoder;
     17 
     18 import android.annotation.TargetApi;
     19 import android.media.MediaFormat;
     20 import android.util.Log;
     21 
     22 import androidx.media.filterfw.FrameImage2D;
     23 
     24 /**
     25  * Base class for all {@link TrackDecoder} classes that decode video.
     26  */
     27 @TargetApi(16)
     28 public abstract class VideoTrackDecoder extends TrackDecoder {
     29 
     30     private static final String LOG_TAG = "VideoTrackDecoder";
     31 
     32     protected final Object mFrameMonitor = new Object();
     33     protected volatile boolean mFrameAvailable; // Access guarded by mFrameMonitor.
     34 
     35     protected VideoTrackDecoder(int trackIndex, MediaFormat format, Listener listener) {
     36         super(trackIndex, format, listener);
     37         if (!DecoderUtil.isVideoFormat(format)) {
     38             throw new IllegalArgumentException(
     39                     "VideoTrackDecoder can only be used with video formats");
     40         }
     41     }
     42 
     43     public void grabFrame(FrameImage2D outputVideoFrame, int rotation) {
     44         synchronized (mFrameMonitor) {
     45             if (!mFrameAvailable) {
     46                 Log.w(LOG_TAG, "frame is not ready - the caller has to wait for a corresponding " +
     47                         "onDecodedFrameAvailable() call");
     48                 return;
     49             }
     50 
     51             copyFrameDataTo(outputVideoFrame, rotation);
     52 
     53             mFrameAvailable = false;
     54             mFrameMonitor.notifyAll();
     55         }
     56     }
     57 
     58 
     59     /**
     60      * Waits for the frame to be picked up by the MFF thread, i.e. blocks until the
     61      * {@link #grabFrame(FrameImage2D, int)}) method is called.
     62      */
     63     public boolean waitForFrameGrab() {
     64         synchronized (mFrameMonitor) {
     65             try {
     66                 while (mFrameAvailable) {
     67                     mFrameMonitor.wait();
     68                 }
     69                 return true;
     70             } catch (InterruptedException e) {
     71                 return false;
     72             }
     73         }
     74     }
     75 
     76     protected final void markFrameAvailable() {
     77         synchronized (mFrameMonitor) {
     78             mFrameAvailable = true;
     79             mFrameMonitor.notifyAll();
     80         }
     81     }
     82 
     83     /**
     84      * @return if the frame dimension needs to be swapped,
     85      *   i.e. (width,height) becomes (height, width)
     86      */
     87     protected static boolean needSwapDimension(int rotation) {
     88         switch(rotation) {
     89             case MediaDecoder.ROTATE_90_RIGHT:
     90             case MediaDecoder.ROTATE_90_LEFT:
     91                 return true;
     92             case MediaDecoder.ROTATE_NONE:
     93             case MediaDecoder.ROTATE_180:
     94                 return false;
     95             default:
     96                 throw new IllegalArgumentException("Unsupported rotation angle.");
     97         }
     98     }
     99 
    100     /**
    101      * Subclasses must implement this to copy the video frame data to an MFF frame.
    102      *
    103      * @param outputVideoFrame The destination frame
    104      * @param rotation The desired rotation of the frame
    105      */
    106     protected abstract void copyFrameDataTo(FrameImage2D outputVideoFrame, int rotation);
    107 
    108 }
    109