Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2017 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 
     17 package android.media.cts;
     18 
     19 import android.media.MediaCodec;
     20 import android.media.MediaCodec.BufferInfo;
     21 import android.media.MediaCodec.Callback;
     22 import android.media.MediaFormat;
     23 import android.os.Bundle;
     24 import android.util.Log;
     25 import android.view.Surface;
     26 import java.nio.ByteBuffer;
     27 
     28 public class NdkMediaCodec implements MediaCodecWrapper {
     29 
     30     private static final String CSD_0 = "csd-0";
     31     private long mNdkMediaCodec;
     32     private final String mName;
     33 
     34     static {
     35         Log.i("@@@", "before loadlibrary");
     36         System.loadLibrary("ctsmediacodec_jni");
     37         Log.i("@@@", "after loadlibrary");
     38     }
     39 
     40     private static native long AMediaCodecCreateCodecByName(String name);
     41     private static native boolean AMediaCodecDelete(long ndkMediaCodec);
     42     private static native boolean AMediaCodecStart(long ndkMediaCodec);
     43     private static native boolean AMediaCodecStop(long ndkMediaCodec);
     44     private static native String AMediaCodecGetOutputFormatString(long ndkMediaCodec);
     45     private static native boolean AMediaCodecSetInputSurface(long ndkMediaCodec, Surface surface);
     46     private static native boolean AMediaCodecSetNativeInputSurface(long ndkMediaCodec, long aNativeWindow);
     47     private static native long AMediaCodecCreateInputSurface(long ndkMediaCodec);
     48     private static native long AMediaCodecCreatePersistentInputSurface();
     49     private static native boolean AMediaCodecSignalEndOfInputStream(long ndkMediaCodec);
     50     private static native boolean AMediaCodecReleaseOutputBuffer(long ndkMediaCodec, int index, boolean render);
     51     private static native ByteBuffer AMediaCodecGetOutputBuffer(long ndkMediaCodec, int index);
     52     private static native long[] AMediaCodecDequeueOutputBuffer(long ndkMediaCodec, long timeoutUs);
     53     private static native ByteBuffer AMediaCodecGetInputBuffer(long ndkMediaCodec, int index);
     54     private static native int AMediaCodecDequeueInputBuffer(long ndkMediaCodec, long timeoutUs);
     55     private static native boolean AMediaCodecSetParameter(long ndkMediaCodec, String key, int value);
     56 
     57     private static native boolean AMediaCodecConfigure(
     58             long ndkMediaCodec,
     59             String mime,
     60             int width,
     61             int height,
     62             int colorFormat,
     63             int bitRate,
     64             int frameRate,
     65             int iFrameInterval,
     66             ByteBuffer csd,
     67             int flags);
     68 
     69     private static native boolean AMediaCodecQueueInputBuffer(
     70             long ndkMediaCodec,
     71             int index,
     72             int offset,
     73             int size,
     74             long presentationTimeUs,
     75             int flags);
     76 
     77     public NdkMediaCodec(String name) {
     78         mName = name;
     79         mNdkMediaCodec = AMediaCodecCreateCodecByName(name);
     80     }
     81 
     82     @Override
     83     protected void finalize() throws Throwable {
     84         AMediaCodecDelete(mNdkMediaCodec);
     85     }
     86 
     87     @Override
     88     public void release() {
     89         AMediaCodecDelete(mNdkMediaCodec);
     90         mNdkMediaCodec = 0;
     91     }
     92 
     93     @Override
     94     public void start() {
     95         AMediaCodecStart(mNdkMediaCodec);
     96     }
     97 
     98     @Override
     99     public void stop() {
    100         AMediaCodecStop(mNdkMediaCodec);
    101     }
    102 
    103     @Override
    104     public void configure(MediaFormat format, int flags) {
    105 
    106         int width = format.getInteger(MediaFormat.KEY_WIDTH, -1);
    107         int height = format.getInteger(MediaFormat.KEY_HEIGHT, -1);
    108         int colorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT, -1);
    109         int bitRate = format.getInteger(MediaFormat.KEY_BIT_RATE, -1);
    110         int frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE, -1);
    111         int iFrameInterval = format.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL, -1);
    112 
    113         ByteBuffer csdBufCopy = null;
    114         if (format.containsKey(CSD_0)) {
    115             ByteBuffer csdBufOld = format.getByteBuffer(CSD_0);
    116             csdBufCopy = ByteBuffer.allocateDirect(csdBufOld.remaining());
    117             csdBufCopy.put(csdBufOld);
    118             csdBufCopy.position(0);
    119         }
    120 
    121         AMediaCodecConfigure(
    122                 mNdkMediaCodec,
    123                 format.getString(MediaFormat.KEY_MIME),
    124                 width,
    125                 height,
    126                 colorFormat,
    127                 bitRate,
    128                 frameRate,
    129                 iFrameInterval ,
    130                 csdBufCopy,
    131                 flags);
    132     }
    133 
    134     @Override
    135     public void setInputSurface(InputSurfaceInterface surface) {
    136         surface.configure(this);
    137     }
    138 
    139     public void setInputSurface(Surface surface) {
    140         AMediaCodecSetInputSurface(mNdkMediaCodec, surface);
    141     }
    142 
    143     public void setInputSurface(long aNativeWindow) {
    144         AMediaCodecSetNativeInputSurface(mNdkMediaCodec, aNativeWindow);
    145     }
    146 
    147     @Override
    148     public InputSurfaceInterface createInputSurface() {
    149         return new NdkInputSurface(AMediaCodecCreateInputSurface(mNdkMediaCodec));
    150     }
    151 
    152     public static InputSurfaceInterface createPersistentInputSurface() {
    153         return new NdkInputSurface(AMediaCodecCreatePersistentInputSurface());
    154     }
    155 
    156     @Override
    157     public int dequeueOutputBuffer(BufferInfo info, long timeoutUs) {
    158         long[] ret = AMediaCodecDequeueOutputBuffer(mNdkMediaCodec, timeoutUs);
    159         if (ret[0] >= 0) {
    160             info.offset = (int)ret[1];
    161             info.size = (int)ret[2];
    162             info.presentationTimeUs = ret[3];
    163             info.flags = (int)ret[4];
    164         }
    165         return (int)ret[0];
    166     }
    167 
    168     @Override
    169     public ByteBuffer getOutputBuffer(int index) {
    170         return AMediaCodecGetOutputBuffer(mNdkMediaCodec, index);
    171     }
    172 
    173     @Override
    174     public void releaseOutputBuffer(int index, boolean render) {
    175         AMediaCodecReleaseOutputBuffer(mNdkMediaCodec, index, render);
    176     }
    177 
    178     @Override
    179     public void signalEndOfInputStream() {
    180         AMediaCodecSignalEndOfInputStream(mNdkMediaCodec);
    181     }
    182 
    183     @Override
    184     public String getOutputFormatString() {
    185         return AMediaCodecGetOutputFormatString(mNdkMediaCodec);
    186     }
    187 
    188     @Override
    189     public ByteBuffer[] getOutputBuffers() {
    190         return null;
    191     }
    192 
    193     @Override
    194     public ByteBuffer getInputBuffer(int index) {
    195         return AMediaCodecGetInputBuffer(mNdkMediaCodec, index);
    196     }
    197 
    198     @Override
    199     public ByteBuffer[] getInputBuffers() {
    200         return null;
    201     }
    202 
    203     @Override
    204     public void queueInputBuffer(
    205             int index,
    206             int offset,
    207             int size,
    208             long presentationTimeUs,
    209             int flags) {
    210 
    211         AMediaCodecQueueInputBuffer(mNdkMediaCodec, index, offset, size, presentationTimeUs, flags);
    212 
    213     }
    214 
    215     @Override
    216     public int dequeueInputBuffer(long timeoutUs) {
    217         return AMediaCodecDequeueInputBuffer(mNdkMediaCodec, timeoutUs);
    218     }
    219 
    220     @Override
    221     public void setParameters(Bundle params) {
    222 
    223         String keys[] = new String[] {
    224                 MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME,
    225                 MediaCodec.PARAMETER_KEY_VIDEO_BITRATE};
    226 
    227         for (String key : keys) {
    228             if (params.containsKey(key)) {
    229                 int value = params.getInt(key);
    230                 AMediaCodecSetParameter(mNdkMediaCodec, key, value);
    231             }
    232         }
    233 
    234     }
    235 
    236     @Override
    237     public void setCallback(Callback mCallback) {
    238         throw new UnsupportedOperationException(mCallback.toString());
    239     }
    240 
    241     @Override
    242     public String toString() {
    243         return String.format("%s(%s, %x)", getClass(), mName, mNdkMediaCodec);
    244     }
    245 }
    246