blob: bccf1f9cf186c62e1611df126e8cb933e035d512 [file] [log] [blame]
/*
* Copyright (C) 2012 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;
import android.view.Surface;
import java.nio.ByteBuffer;
import java.util.Map;
/**
* MediaCodec class can be used to access low-level media codec, i.e.
* encoder/decoder components.
* @hide
*/
public class MediaCodec
{
/** Per buffer metadata includes an offset and size specifying
the range of valid data in the associated codec buffer.
*/
public final static class BufferInfo {
public void set(
int offset, int size, long timeUs, int flags) {
mOffset = offset;
mSize = size;
mPresentationTimeUs = timeUs;
mFlags = flags;
}
public int mOffset;
public int mSize;
public long mPresentationTimeUs;
public int mFlags;
};
public static int FLAG_SYNCFRAME = 1;
public static int FLAG_CODECCONFIG = 2;
public static int FLAG_EOS = 4;
/** Instantiate a codec component by mime type. For decoder components
this is the mime type of media that this decoder should be able to
decoder, for encoder components it's the type of media this encoder
should encode _to_.
*/
public static MediaCodec CreateByType(String type, boolean encoder) {
return new MediaCodec(type, true /* nameIsType */, encoder);
}
/** If you know the exact name of the component you want to instantiate
use this method to instantiate it. Use with caution.
*/
public static MediaCodec CreateByComponentName(String name) {
return new MediaCodec(
name, false /* nameIsType */, false /* unused */);
}
private MediaCodec(
String name, boolean nameIsType, boolean encoder) {
native_setup(name, nameIsType, encoder);
}
@Override
protected void finalize() {
native_finalize();
}
// Make sure you call this when you're done to free up any opened
// component instance instead of relying on the garbage collector
// to do this for you at some point in the future.
public native final void release();
public static int CONFIGURE_FLAG_ENCODE = 1;
/** Configures a component.
* @param format A map of string/value pairs describing the input format
* (decoder) or the desired output format.
*
* Video formats have the following fields:
* "mime" - String
* "width" - Integer
* "height" - Integer
* optional "max-input-size" - Integer
*
* Audio formats have the following fields:
* "mime" - String
* "channel-count" - Integer
* "sample-rate" - Integer
* optional "max-input-size" - Integer
*
* If the format is used to configure an encoder, additional
* fields must be included:
* "bitrate" - Integer (in bits/sec)
*
* for video formats:
* "color-format" - Integer
* "frame-rate" - Integer or Float
* "i-frame-interval" - Integer
* optional "stride" - Integer, defaults to "width"
* optional "slice-height" - Integer, defaults to "height"
*
* @param surface Specify a surface on which to render the output of this
* decoder.
* @param flags Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
* component as an encoder.
*/
public void configure(
Map<String, Object> format, Surface surface, int flags) {
String[] keys = null;
Object[] values = null;
if (format != null) {
keys = new String[format.size()];
values = new Object[format.size()];
int i = 0;
for (Map.Entry<String, Object> entry: format.entrySet()) {
keys[i] = entry.getKey();
values[i] = entry.getValue();
++i;
}
}
native_configure(keys, values, surface, flags);
}
private native final void native_configure(
String[] keys, Object[] values, Surface surface, int flags);
/** After successfully configuring the component, call start. On return
* you can query the component for its input/output buffers.
*/
public native final void start();
public native final void stop();
/** Flush both input and output ports of the component, all indices
* previously returned in calls to dequeueInputBuffer and
* dequeueOutputBuffer become invalid.
*/
public native final void flush();
/** After filling a range of the input buffer at the specified index
* submit it to the component.
*
* Many decoders require the actual compressed data stream to be
* preceded by "codec specific data", i.e. setup data used to initialize
* the codec such as PPS/SPS in the case of AVC video or code tables
* in the case of vorbis audio.
* The class MediaExtractor provides codec specific data as part of
* the returned track format in entries named "csd-0", "csd-1" ...
*
* These buffers should be submitted using the flag {@link #FLAG_CODECCONFIG}.
*
* To indicate that this is the final piece of input data (or rather that
* no more input data follows unless the decoder is subsequently flushed)
* specify the flag {@link FLAG_EOS}.
*/
public native final void queueInputBuffer(
int index,
int offset, int size, long presentationTimeUs, int flags);
// Returns the index of an input buffer to be filled with valid data
// or -1 if no such buffer is currently available.
// This method will return immediately if timeoutUs == 0, wait indefinitely
// for the availability of an input buffer if timeoutUs < 0 or wait up
// to "timeoutUs" microseconds if timeoutUs > 0.
public native final int dequeueInputBuffer(long timeoutUs);
// Returns the index of an output buffer that has been successfully
// decoded or one of the INFO_* constants below.
// The provided "info" will be filled with buffer meta data.
public static final int INFO_TRY_AGAIN_LATER = -1;
public static final int INFO_OUTPUT_FORMAT_CHANGED = -2;
public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3;
/** Dequeue an output buffer, block at most "timeoutUs" microseconds. */
public native final int dequeueOutputBuffer(
BufferInfo info, long timeoutUs);
// If you are done with a buffer, use this call to return the buffer to
// the codec. If you previously specified a surface when configuring this
// video decoder you can optionally render the buffer.
public native final void releaseOutputBuffer(int index, boolean render);
/** Call this after dequeueOutputBuffer signals a format change by returning
* {@link #INFO_OUTPUT_FORMAT_CHANGED}
*/
public native final Map<String, Object> getOutputFormat();
/** Call this after start() returns.
*/
public ByteBuffer[] getInputBuffers() {
return getBuffers(true /* input */);
}
/** Call this after start() returns and whenever dequeueOutputBuffer
* signals an output buffer change by returning
* {@link #INFO_OUTPUT_BUFFERS_CHANGED}
*/
public ByteBuffer[] getOutputBuffers() {
return getBuffers(false /* input */);
}
private native final ByteBuffer[] getBuffers(boolean input);
private static native final void native_init();
private native final void native_setup(
String name, boolean nameIsType, boolean encoder);
private native final void native_finalize();
static {
System.loadLibrary("media_jni");
native_init();
}
private int mNativeContext;
}