下面列出了android.media.MediaCodec# configure ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
@Nullable MediaCrypto crypto,
float codecOperatingRate) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
codecNeedsEosBufferTimestampWorkaround = codecNeedsEosBufferTimestampWorkaround(codecInfo.name);
passthroughEnabled = codecInfo.passthrough;
String codecMimeType = passthroughEnabled ? MimeTypes.AUDIO_RAW : codecInfo.codecMimeType;
MediaFormat mediaFormat =
getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
if (passthroughEnabled) {
// Store the input MIME type if we're using the passthrough codec.
passthroughMediaFormat = mediaFormat;
passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
} else {
passthroughMediaFormat = null;
}
}
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
MediaCrypto crypto,
float codecOperatingRate) {
String codecMimeType = codecInfo.codecMimeType;
codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
MediaFormat mediaFormat =
getMediaFormat(
format,
codecMimeType,
codecMaxValues,
codecOperatingRate,
deviceNeedsNoPostProcessWorkaround,
tunnelingAudioSessionId);
if (surface == null) {
Assertions.checkState(shouldUseDummySurface(codecInfo));
if (dummySurface == null) {
dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
}
surface = dummySurface;
}
codec.configure(mediaFormat, surface, crypto, 0);
if (Util.SDK_INT >= 23 && tunneling) {
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
}
}
@TargetApi(MIN_API_LEVEL_AUDIO)
public static int checkMediaCodecAudioEncoderSupport(){
if(getApiLevel()<MIN_API_LEVEL_AUDIO){
Log.d(TAG, "checkMediaCodecAudioEncoderSupport: Min API is 16");
return CODEC_REQ_API_NOT_SATISFIED;
}
final MediaFormat audioFormat = MediaFormat.createAudioFormat(MIME_TYPE_AUDIO, TEST_SAMPLE_RATE, 1);
audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_MASK, AudioFormat.CHANNEL_IN_MONO);
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, TEST_AUDIO_BIT_RATE);
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
MediaCodec mediaCodec;
try {
mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE_AUDIO);
mediaCodec.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
mediaCodec.stop();
mediaCodec.release();
mediaCodec = null;
} catch (Exception ex) {
Log.e(TAG, "Failed on creation of codec #", ex);
return CODEC_ERROR;
}
return CODEC_SUPPORTED;
}
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
MediaCrypto crypto,
float codecOperatingRate) {
codecMaxInputSize = getCodecMaxInputSize(codecInfo, format, getStreamFormats());
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
passthroughEnabled = codecInfo.passthrough;
String codecMimeType = codecInfo.mimeType == null ? MimeTypes.AUDIO_RAW : codecInfo.mimeType;
MediaFormat mediaFormat =
getMediaFormat(format, codecMimeType, codecMaxInputSize, codecOperatingRate);
codec.configure(mediaFormat, /* surface= */ null, crypto, /* flags= */ 0);
if (passthroughEnabled) {
// Store the input MIME type if we're using the passthrough codec.
passthroughMediaFormat = mediaFormat;
passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
} else {
passthroughMediaFormat = null;
}
}
@Override
protected MediaCodec createMediaCodec() throws IOException {
parseSps();
MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
format.setInteger(MediaFormat.KEY_COLOR_RANGE, MediaFormat.COLOR_RANGE_FULL);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
format.setInteger(MediaFormat.KEY_OPERATING_RATE, Short.MAX_VALUE);
}
format.setByteBuffer("csd-0", mCsd0);
format.setByteBuffer("csd-1", mCsd1);
if (DEBUG) {
Log.d(TAG, "H264Decoder::createMediaCodec: " + format);
}
MediaCodec mediaCodec = MediaCodec.createDecoderByType(mMimeType);
mediaCodec.configure(format, getSurface(), null, 0);
mediaCodec.setVideoScalingMode(MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
mediaCodec.start();
return mediaCodec;
}
private MediaCodec createMediaCodec(Context context, int bufferSize) throws IOException {
MediaCodec mediaCodec = MediaCodec.createEncoderByType("audio/mp4a-latm");
MediaFormat mediaFormat = new MediaFormat();
mediaFormat.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
mediaFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, SAMPLE_RATE);
mediaFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, CHANNELS);
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, bufferSize);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, Prefs.isHardCompressionEnabled(context)? BIT_RATE_WORSE : BIT_RATE_BALANCED);
mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
try {
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (Exception e) {
Log.w(TAG, e);
mediaCodec.release();
throw new IOException(e);
}
return mediaCodec;
}
/**
* @param media_extractor
* @param trackIndex
* @return
*/
protected MediaCodec internalStartVideo(final MediaExtractor media_extractor, final int trackIndex) {
if (DEBUG) Log.v(TAG, "internalStartVideo:");
MediaCodec codec = null;
if (trackIndex >= 0) {
final MediaFormat format = media_extractor.getTrackFormat(trackIndex);
final String mime = format.getString(MediaFormat.KEY_MIME);
try {
codec = MediaCodec.createDecoderByType(mime);
codec.configure(format, mOutputSurface, null, 0);
codec.start();
} catch (final IOException e) {
Log.w(TAG, e);
codec = null;
}
if (DEBUG) Log.v(TAG, "internalStartVideo:codec started");
}
return codec;
}
/**
* Creates an encoder for the given format using the specified codec, taking input from a
* surface.
*
* <p>The surface to use as input is stored in the given reference.
*
* @param codecName of the codec to use
* @param format of the stream to be produced
* @param surfaceReference to store the surface to use as input
*/
private MediaCodec createVideoEncoder(
String codecName,
MediaFormat format,
AtomicReference<Surface> surfaceReference) {
try {
MediaCodec encoder = MediaCodec.createByCodecName(codecName);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// Must be called before start() is.
surfaceReference.set(encoder.createInputSurface());
encoder.start();
return encoder;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void configureCodec(MediaCodecInfo codecInfo, MediaCodec codec, Format format,
MediaCrypto crypto) {
codecNeedsDiscardChannelsWorkaround = codecNeedsDiscardChannelsWorkaround(codecInfo.name);
if (passthroughEnabled) {
// Override the MIME type used to configure the codec if we are using a passthrough decoder.
passthroughMediaFormat = format.getFrameworkMediaFormatV16();
passthroughMediaFormat.setString(MediaFormat.KEY_MIME, MimeTypes.AUDIO_RAW);
codec.configure(passthroughMediaFormat, null, crypto, 0);
passthroughMediaFormat.setString(MediaFormat.KEY_MIME, format.sampleMimeType);
} else {
codec.configure(format.getFrameworkMediaFormatV16(), null, crypto, 0);
passthroughMediaFormat = null;
}
}
private @NonNull
MediaCodec createVideoEncoder(
final @NonNull MediaCodecInfo codecInfo,
final @NonNull MediaFormat format,
final @NonNull AtomicReference<Surface> surfaceReference) throws IOException {
final MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// Must be called before start()
surfaceReference.set(encoder.createInputSurface());
encoder.start();
return encoder;
}
/**
* Must call in a worker handler thread!
*/
@Override
public void prepare() throws IOException {
if (Looper.myLooper() == null
|| Looper.myLooper() == Looper.getMainLooper()) {
throw new IllegalStateException("should run in a HandlerThread");
}
if (mEncoder != null) {
throw new IllegalStateException("prepared!");
}
MediaFormat format = createMediaFormat();
Log.d("Encoder", "Create media format: " + format);
String mimeType = format.getString(MediaFormat.KEY_MIME);
final MediaCodec encoder = createEncoder(mimeType);
try {
if (this.mCallback != null) {
// NOTE: MediaCodec maybe crash on some devices due to null callback
encoder.setCallback(mCodecCallback);
}
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
onEncoderConfigured(encoder);
encoder.start();
} catch (MediaCodec.CodecException e) {
Log.e("Encoder", "Configure codec failure!\n with format" + format, e);
throw e;
}
mEncoder = encoder;
}
private static @NonNull
MediaCodec createAudioEncoder(final @NonNull MediaCodecInfo codecInfo, final @NonNull MediaFormat format) throws IOException {
final MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
return encoder;
}
/**
* Must call in a worker handler thread!
*/
@Override
public void prepare() throws IOException {
if (Looper.myLooper() == null
|| Looper.myLooper() == Looper.getMainLooper()) {
throw new IllegalStateException("should run in a HandlerThread");
}
if (mEncoder != null) {
throw new IllegalStateException("prepared!");
}
MediaFormat format = createMediaFormat();
LogUtil.i("Encoder", "Create media format: " + format);
String mimeType = format.getString(MediaFormat.KEY_MIME);
final MediaCodec encoder = createEncoder(mimeType);
try {
if (this.mCallback != null) {
// NOTE: MediaCodec maybe crash on some devices due to null callback
encoder.setCallback( mCodecCallback);
}
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
onEncoderConfigured(encoder);
encoder.start();
} catch (MediaCodec.CodecException e) {
LogUtil.e("Encoder", "Configure codec failure!\n with format" + format, e);
throw e;
}
mEncoder = encoder;
}
/**
* Creates a decoder for the given format, which outputs to the given surface.
*
* @param inputFormat the format of the stream to decode
* @param surface into which to decode the frames
*/
private MediaCodec createVideoDecoder(
MediaCodecList mcl, MediaFormat inputFormat, Surface surface){
try {
MediaCodec decoder = MediaCodec.createByCodecName(mcl.findDecoderForFormat(inputFormat));
decoder.configure(inputFormat, surface, null, 0);
decoder.start();
return decoder;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void configureCodec(
MediaCodecInfo codecInfo,
MediaCodec codec,
Format format,
MediaCrypto crypto,
float codecOperatingRate)
throws DecoderQueryException {
codecMaxValues = getCodecMaxValues(codecInfo, format, getStreamFormats());
MediaFormat mediaFormat =
getMediaFormat(
format,
codecMaxValues,
codecOperatingRate,
deviceNeedsAutoFrcWorkaround,
tunnelingAudioSessionId);
if (surface == null) {
Assertions.checkState(shouldUseDummySurface(codecInfo));
if (dummySurface == null) {
dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
}
surface = dummySurface;
}
codec.configure(mediaFormat, surface, crypto, 0);
if (Util.SDK_INT >= 23 && tunneling) {
tunnelingOnFrameRenderedListener = new OnFrameRenderedListenerV23(codec);
}
}
private MediaCodec createACCAudioDecoder() throws IOException {
MediaCodec codec = MediaCodec.createEncoderByType(AUDIO_MIME);
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, AUDIO_MIME);
format.setInteger(MediaFormat.KEY_BIT_RATE, 128000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 2);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
format.setInteger(MediaFormat.KEY_AAC_PROFILE,
MediaCodecInfo.CodecProfileLevel.AACObjectLC);
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
return codec;
}
public boolean configure(SurfaceView surfaceView, int width, int height) {
mSurfaceView = surfaceView;
Log.d(TAG, "configure " + "width" + width + "height" + height + mSurfaceView.toString());
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "video/x-vnd.on2.vp8");
format.setInteger(MediaFormat.KEY_WIDTH, width);
format.setInteger(MediaFormat.KEY_HEIGHT, height);
Surface surface = mSurfaceView.getHolder().getSurface();
Log.d(TAG, "Surface " + surface.isValid());
MediaCodec codec;
try {
codec = MediaCodec.createDecoderByType("video/x-vnd.on2.vp8");
// SW VP8 decoder
// codec = MediaCodec.createByCodecName("OMX.google.vpx.decoder");
// Nexus10 HW VP8 decoder
// codec = MediaCodec.createByCodecName("OMX.Exynos.VP8.Decoder");
} catch (Exception e) {
// TODO(dwkang): replace this instanceof/throw with a narrower catch clause
// once the SDK advances.
if (e instanceof IOException) {
Log.e(TAG, "Failed to create MediaCodec for VP8.", e);
return false;
}
throw new RuntimeException(e);
}
codec.configure(format, surface, null, 0);
mCodecState = new CodecState(this, format, codec);
initMediaCodecView();
return true;
}
/**
* Decodes audio file into a raw file. This method accepts audio file formats with valid
* headers (like .mp3, .mp4, and .wav).
* @param filepath Path of the file to decode.
* @return Decoded raw audio file.
* @throws IOException when file cannot be read.
*/
private File decode(String filepath) throws IOException
{
// Set selected audio file as a source.
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(filepath);
// Get audio format.
MediaFormat format = extractor.getTrackFormat(0);
String mime = format.getString(MediaFormat.KEY_MIME);
// Cache necessary audio attributes.
sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
// Create and configure decoder based on audio format.
MediaCodec decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(format, null, null, 0);
decoder.start();
// Create input/output buffers.
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
extractor.selectTrack(0);
File dst = new File(FileCons.SSJ_EXTERNAL_STORAGE + File.separator + "output.raw");
FileOutputStream f = new FileOutputStream(dst);
boolean endOfStreamReached = false;
while (true)
{
if (!endOfStreamReached)
{
int inputBufferIndex = decoder.dequeueInputBuffer(10 * 1000);
if (inputBufferIndex >= 0)
{
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0)
{
// Pass empty buffer and the end of stream flag to the codec.
decoder.queueInputBuffer(inputBufferIndex, 0, 0,
0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
endOfStreamReached = true;
}
else
{
// Pass data-filled buffer to the decoder.
decoder.queueInputBuffer(inputBufferIndex, 0, sampleSize,
extractor.getSampleTime(), 0);
extractor.advance();
}
}
}
int outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, 10 * 1000);
if (outputBufferIndex >= 0)
{
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] data = new byte[bufferInfo.size];
outputBuffer.get(data);
outputBuffer.clear();
if (data.length > 0)
{
f.write(data, 0, data.length);
}
decoder.releaseOutputBuffer(outputBufferIndex, false);
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
{
endOfStreamReached = true;
}
}
else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{
outputBuffers = decoder.getOutputBuffers();
}
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
{
return dst;
}
}
}
static void extractThumbnails(final @NonNull MediaInput input,
final int thumbnailCount,
final int thumbnailResolution,
final @NonNull Callback callback)
{
MediaExtractor extractor = null;
MediaCodec decoder = null;
OutputSurface outputSurface = null;
try {
extractor = input.createExtractor();
MediaFormat mediaFormat = null;
for (int index = 0; index < extractor.getTrackCount(); ++index) {
if (extractor.getTrackFormat(index).getString(MediaFormat.KEY_MIME).startsWith("video/")) {
extractor.selectTrack(index);
mediaFormat = extractor.getTrackFormat(index);
break;
}
}
if (mediaFormat != null) {
final String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
final int rotation = mediaFormat.containsKey(MediaFormat.KEY_ROTATION) ? mediaFormat.getInteger(MediaFormat.KEY_ROTATION) : 0;
final int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
final int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
final int outputWidth;
final int outputHeight;
if (width < height) {
outputWidth = thumbnailResolution;
outputHeight = height * outputWidth / width;
} else {
outputHeight = thumbnailResolution;
outputWidth = width * outputHeight / height;
}
final int outputWidthRotated;
final int outputHeightRotated;
if ((rotation % 180 == 90)) {
//noinspection SuspiciousNameCombination
outputWidthRotated = outputHeight;
//noinspection SuspiciousNameCombination
outputHeightRotated = outputWidth;
} else {
outputWidthRotated = outputWidth;
outputHeightRotated = outputHeight;
}
Log.i(TAG, "video: " + width + "x" + height + " " + rotation);
Log.i(TAG, "output: " + outputWidthRotated + "x" + outputHeightRotated);
outputSurface = new OutputSurface(outputWidthRotated, outputHeightRotated, true);
decoder = MediaCodec.createDecoderByType(mime);
decoder.configure(mediaFormat, outputSurface.getSurface(), null, 0);
decoder.start();
long duration = 0;
if (mediaFormat.containsKey(MediaFormat.KEY_DURATION)) {
duration = mediaFormat.getLong(MediaFormat.KEY_DURATION);
} else {
Log.w(TAG, "Video is missing duration!");
}
callback.durationKnown(duration);
doExtract(extractor, decoder, outputSurface, outputWidthRotated, outputHeightRotated, duration, thumbnailCount, callback);
}
} catch (IOException | TranscodingException e) {
Log.w(TAG, e);
callback.failed();
} finally {
if (outputSurface != null) {
outputSurface.release();
}
if (decoder != null) {
decoder.stop();
decoder.release();
}
if (extractor != null) {
extractor.release();
}
}
}
private void decodeFrames(final MediaCodec decoder, MediaExtractor extractor, MediaFormat mediaFormat) {
boolean sawInputEOS = false;
sawOutputEOS = false;
decoder.configure(mediaFormat, null, null, 0);
decoder.start();
if(!Helper.isUpperThanAPI21()) {
inputByteBuffers = decoder.getInputBuffers();
outputByteBuffers = decoder.getOutputBuffers();
}
while (!sawOutputEOS && !stopDecode) {
if (!sawInputEOS) {
int inputBufferId = decoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
if (inputBufferId >= 0) {
ByteBuffer inputBuffer = null;
if (Helper.isUpperThanAPI21()) {
inputBuffer = decoder.getInputBuffer(inputBufferId);
} else {
inputBuffer = inputByteBuffers[inputBufferId];
}
int sampleSize = extractor.readSampleData(inputBuffer, 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inputBufferId, 0, 0, 0L, 0);
sawInputEOS = false;
extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
} else {
long presentationTimeUs = extractor.getSampleTime();
decoder.queueInputBuffer(inputBufferId, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
}
if(displayThread==null) {
displayThread = new Thread(new Runnable() {
@Override
public void run() {
while (!sawOutputEOS && !stopDisplay) {
frameDisplay(decoder);
}
}
});
displayThread.start();
}
}
}