下面列出了android.media.MediaCodec# createDecoderByType ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public MediaCodecDecoder(MediaExtractor extractor, boolean passive, int trackIndex,
OnDecoderEventListener listener)
throws IllegalStateException, IOException
{
// Apply the name of the concrete class that extends this base class to the logging tag
// THis is really not a nice solution but there's no better one: http://stackoverflow.com/a/936724
TAG = getClass().getSimpleName();
if(extractor == null || trackIndex == INDEX_NONE) {
throw new IllegalArgumentException("no track specified");
}
mExtractor = extractor;
mPassive = passive;
mTrackIndex = trackIndex;
mFormat = extractor.getTrackFormat(mTrackIndex);
mOnDecoderEventListener = listener;
mCodec = MediaCodec.createDecoderByType(mFormat.getString(MediaFormat.KEY_MIME));
mDecodingPTS = PTS_NONE;
}
public boolean setDecoder(int sampleRate, int channels, int bitRate) throws Exception
{
decoder = MediaCodec.createDecoderByType("audio/mp4a-latm");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, sampleRate);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate * 1024);//AAC-HE 64kbps
format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectHE);
decoder.configure(format, null, null, 0);
setPlayer(sampleRate);
return true;
}
/**
* Constructs the {@link MediaCodecWrapper} wrapper object around the video codec.
* The codec is created using the encapsulated information in the
* {@link MediaFormat} object.
*
* @param trackFormat The format of the media object to be decoded.
* @param surface Surface to render the decoded frames.
* @return
*/
public static MediaCodecWrapper fromVideoFormat(final MediaFormat trackFormat,
Surface surface) throws IOException {
MediaCodecWrapper result = null;
MediaCodec videoCodec = null;
// BEGIN_INCLUDE(create_codec)
final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
// Check to see if this is actually a video mime type. If it is, then create
// a codec that can decode this mime type.
if (mimeType.contains("video/")) {
videoCodec = MediaCodec.createDecoderByType(mimeType);
videoCodec.configure(trackFormat, surface, null, 0);
}
// If codec creation was successful, then create a wrapper object around the
// newly created codec.
if (videoCodec != null) {
result = new MediaCodecWrapper(videoCodec);
}
// END_INCLUDE(create_codec)
return result;
}
/**
* Constructs the {@link MediaCodecWrapper} wrapper object around the video codec.
* The codec is created using the encapsulated information in the
* {@link MediaFormat} object.
*
* @param trackFormat The format of the media object to be decoded.
* @param surface Surface to render the decoded frames.
* @return
*/
public static MediaCodecWrapper fromVideoFormat(final MediaFormat trackFormat,
Surface surface) throws IOException {
MediaCodecWrapper result = null;
MediaCodec videoCodec = null;
// BEGIN_INCLUDE(create_codec)
final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
// Check to see if this is actually a video mime type. If it is, then create
// a codec that can decode this mime type.
if (mimeType.contains("video/")) {
videoCodec = MediaCodec.createDecoderByType(mimeType);
videoCodec.configure(trackFormat, surface, null, 0);
}
// If codec creation was successful, then create a wrapper object around the
// newly created codec.
if (videoCodec != null) {
result = new MediaCodecWrapper(videoCodec);
}
// END_INCLUDE(create_codec)
return result;
}
@CalledByNative
private static MediaCodecBridge create(String mime, boolean isSecure) {
MediaCodec mediaCodec = null;
try {
// |isSecure| only applies to video decoders.
if (mime.startsWith("video") && isSecure) {
mediaCodec = MediaCodec.createByCodecName(getSecureDecoderNameForMime(mime));
} else {
mediaCodec = MediaCodec.createDecoderByType(mime);
}
} catch (Exception e) {
Log.e(TAG, "Failed to create MediaCodec: " + mime + ", isSecure: "
+ isSecure + ", " + e.toString());
}
if (mediaCodec == null) {
return null;
}
return new MediaCodecBridge(mediaCodec);
}
public AudioRecoder(MediaFormat inputAudioFormat, MediaExtractor extractor, int trackIndex) throws IOException {
this.extractor = extractor;
this.trackIndex = trackIndex;
decoder = MediaCodec.createDecoderByType(inputAudioFormat.getString(MediaFormat.KEY_MIME));
decoder.configure(inputAudioFormat, null, null, 0);
decoder.start();
encoder = MediaCodec.createEncoderByType(MediaController.AUIDO_MIME_TYPE);
format = MediaFormat.createAudioFormat(MediaController.AUIDO_MIME_TYPE,
inputAudioFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE),
inputAudioFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT)
);
format.setInteger(MediaFormat.KEY_BIT_RATE, 64 * 1024);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
decoderInputBuffers = decoder.getInputBuffers();
decoderOutputBuffers = decoder.getOutputBuffers();
encoderInputBuffers = encoder.getInputBuffers();
encoderOutputBuffers = encoder.getOutputBuffers();
}
@Override
public void setup() throws IOException {
mExtractor.selectTrack(mTrackIndex);
mEncoder = MediaCodec.createEncoderByType(mOutputFormat.getString(MediaFormat.KEY_MIME));
mEncoder.configure(mOutputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
mEncoderStarted = true;
final MediaFormat inputFormat = mExtractor.getTrackFormat(mTrackIndex);
mDecoder = MediaCodec.createDecoderByType(inputFormat.getString(MediaFormat.KEY_MIME));
mDecoder.configure(inputFormat, null, null, 0);
mDecoder.start();
mDecoderStarted = true;
mAudioChannel = new AudioChannel(mDecoder, mEncoder, mOutputFormat);
}
/**
* @param media_extractor
* @param trackIndex
* @return
*/
protected MediaCodec internal_start_video(final MediaExtractor media_extractor, final int trackIndex) {
if (DEBUG) Log.v(TAG, "internal_start_video:");
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();
if (DEBUG) Log.v(TAG, "internal_start_video:codec started");
} catch (final IOException e) {
Log.w(TAG, e);
}
}
return codec;
}
private @NonNull
MediaCodec createVideoDecoder(
final @NonNull MediaFormat inputFormat,
final @NonNull Surface surface) throws IOException {
final MediaCodec decoder = MediaCodec.createDecoderByType(MediaConverter.getMimeTypeFor(inputFormat));
decoder.configure(inputFormat, surface, null, 0);
decoder.start();
return decoder;
}
public int Init()
{
Log.i("AvcDecoder", "Init");
mMC = MediaCodec.createDecoderByType(MIME_TYPE);
mStatus = STATUS_LOADED;
mBI = new BufferInfo();
Log.i("AvcDecoder", "Init, createDecoderByType");
return 0;
}
public void initDecoder() {
try {
mCodec = MediaCodec.createDecoderByType(MIME_TYPE);
} catch (IOException e) {
e.printStackTrace();
}
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,
VIDEO_WIDTH, VIDEO_HEIGHT);
mCodec.configure(mediaFormat, mSurface,
null, 0);
mCodec.start();
}
@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);
}
ByteBuffer csd0 = ByteBuffer.allocateDirect(mVPS.length + mSPS.length + mPPS.length);
csd0.put(mVPS);
csd0.position(mVPS.length);
csd0.put(mSPS);
csd0.position(mVPS.length + mSPS.length);
csd0.put(mPPS);
format.setByteBuffer("csd-0", csd0);
if (DEBUG) {
Log.d(TAG, "H265Decoder::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;
}
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;
}
private void setupExtractor() {
mExtractor = new MediaExtractor();
try {
mExtractor.setDataSource( mUri.toString() );
} catch ( IOException e ) {
e.printStackTrace();
}
int videoIndex = 0;
for ( int trackIndex = 0; trackIndex < mExtractor.getTrackCount(); trackIndex++ ) {
MediaFormat format = mExtractor.getTrackFormat( trackIndex );
String mime = format.getString( MediaFormat.KEY_MIME );
if ( mime != null ) {
if ( mime.equals( "video/avc" ) ) {
mExtractor.selectTrack( trackIndex );
videoIndex = trackIndex;
break;
}
}
}
mDecoder = MediaCodec.createDecoderByType( "video/avc" );
mDecoder.configure( mExtractor.getTrackFormat( videoIndex ), mSurface, null, 0 );
mDecoder.start();
mInfo = new BufferInfo();
mInputBuffers = mDecoder.getInputBuffers();
mOutputBuffers = mDecoder.getOutputBuffers();
}
public boolean prepareVideo(Surface surface) {
try {
videoDecoder = MediaCodec.createDecoderByType(mime);
videoDecoder.configure(videoFormat, surface, null, 0);
return true;
} catch (IOException e) {
Log.e(TAG, "Prepare decoder error:", e);
return false;
}
}
@Override
public void recreate() {
try {
release();
this.mediaCodec = MediaCodec.createDecoderByType("audio/mp4a-latm");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Checks the video file to see if the contents match our expectations. We decode the
* video to a Surface and check the pixels with GL.
*/
private void checkVideoFile(VideoChunks inputData) {
OutputSurface surface = null;
MediaCodec decoder = null;
mLargestColorDelta = -1;
if (VERBOSE) Log.d(TAG, "checkVideoFile");
try {
surface = new OutputSurface(mWidth, mHeight);
MediaFormat format = inputData.getMediaFormat();
decoder = MediaCodec.createDecoderByType(MIME_TYPE);
decoder.configure(format, surface.getSurface(), null, 0);
decoder.start();
int badFrames = checkVideoData(inputData, decoder, surface);
if (badFrames != 0) {
fail("Found " + badFrames + " bad frames");
}
} finally {
if (surface != null) {
surface.release();
}
if (decoder != null) {
decoder.stop();
decoder.release();
}
Log.i(TAG, "Largest color delta: " + mLargestColorDelta);
}
}
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();
}
}
}
/**
* 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;
}
}
}
/**
* Edits a video file, saving the contents to a new file. This involves decoding and
* re-encoding, not to mention conversions between YUV and RGB, and so may be lossy.
* <p>
* If we recognize the decoded format we can do this in Java code using the ByteBuffer[]
* output, but it's not practical to support all OEM formats. By using a SurfaceTexture
* for output and a Surface for input, we can avoid issues with obscure formats and can
* use a fragment shader to do transformations.
*/
private VideoChunks editVideoFile(VideoChunks inputData) {
if (VERBOSE) Log.d(TAG, "editVideoFile " + mWidth + "x" + mHeight);
VideoChunks outputData = new VideoChunks();
MediaCodec decoder = null;
MediaCodec encoder = null;
InputSurface inputSurface = null;
OutputSurface outputSurface = null;
try {
MediaFormat inputFormat = inputData.getMediaFormat();
// Create an encoder format that matches the input format. (Might be able to just
// re-use the format used to generate the video, since we want it to be the same.)
MediaFormat outputFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE,
inputFormat.getInteger(MediaFormat.KEY_BIT_RATE));
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
inputFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
inputFormat.getInteger(MediaFormat.KEY_I_FRAME_INTERVAL));
outputData.setMediaFormat(outputFormat);
encoder = MediaCodec.createEncoderByType(MIME_TYPE);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
encoder.start();
// OutputSurface uses the EGL context created by InputSurface.
decoder = MediaCodec.createDecoderByType(MIME_TYPE);
outputSurface = new OutputSurface();
outputSurface.changeFragmentShader(FRAGMENT_SHADER);
decoder.configure(inputFormat, outputSurface.getSurface(), null, 0);
decoder.start();
editVideoData(inputData, decoder, outputSurface, inputSurface, encoder, outputData);
} finally {
if (VERBOSE) Log.d(TAG, "shutting down encoder, decoder");
if (outputSurface != null) {
outputSurface.release();
}
if (inputSurface != null) {
inputSurface.release();
}
if (encoder != null) {
encoder.stop();
encoder.release();
}
if (decoder != null) {
decoder.stop();
decoder.release();
}
}
return outputData;
}