下面列出了android.media.MediaCodec# CodecException ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
static NoPlayer.PlayerError map(RuntimeException unexpectedException, String message) {
if (unexpectedException instanceof EGLSurfaceTexture.GlException) {
return new NoPlayerError(PlayerErrorType.UNEXPECTED, DetailErrorType.EGL_OPERATION_ERROR, message);
}
if (unexpectedException instanceof DefaultAudioSink.InvalidAudioTrackTimestampException) {
return new NoPlayerError(PlayerErrorType.UNEXPECTED, DetailErrorType.SPURIOUS_AUDIO_TRACK_TIMESTAMP_ERROR, message);
}
if (unexpectedException instanceof IllegalStateException && message.contains("Multiple renderer media clocks")) {
return new NoPlayerError(PlayerErrorType.UNEXPECTED, DetailErrorType.MULTIPLE_RENDERER_MEDIA_CLOCK_ENABLED_ERROR, message);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && unexpectedException instanceof MediaCodec.CodecException) {
String errorMessage = ErrorFormatter.formatCodecException((MediaCodec.CodecException) unexpectedException);
return new NoPlayerError(PlayerErrorType.UNEXPECTED, DetailErrorType.UNEXPECTED_CODEC_ERROR, errorMessage);
}
return new NoPlayerError(PlayerErrorType.UNKNOWN, DetailErrorType.UNKNOWN, message);
}
/**
* 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;
}
@CalledByNativeUnchecked
private void returnDecodedOutputBuffer(int index)
throws IllegalStateException, MediaCodec.CodecException {
checkOnMediaCodecThread();
if (useSurface()) {
throw new IllegalStateException("returnDecodedOutputBuffer() called for surface decoding.");
}
mediaCodec.releaseOutputBuffer(index, false /* render */);
}
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
private String getExceptionDiagnosticInfo(@Nullable Throwable cause) {
if (!(cause instanceof MediaCodec.CodecException)) {
return null;
}
return ((MediaCodec.CodecException) cause).getDiagnosticInfo();
}
@Override
public byte[] flushAndStop() {
ByteArrayOutputStream outputBytes = new ByteArrayOutputStream();
try {
processAudioBytesInternal(null, 0, 0, true, outputBytes); // Flush!
codec.stop();
} catch (MediaCodec.CodecException e) {
logger.atSevere().log("Something went wrong in the underlying codec!");
}
codec.release();
return outputBytes.toByteArray();
}
/**
* 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;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
HyperionScreenEncoder(final HyperionThread.HyperionThreadListener listener,
final MediaProjection projection, final int width, final int height,
final int density, HyperionGrabberOptions options) {
super(listener, projection, width, height, density, options);
try {
prepare();
} catch (MediaCodec.CodecException e) {
e.printStackTrace();
}
}
@TargetApi(Build.VERSION_CODES.M)
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void prepare() throws MediaCodec.CodecException {
if (DEBUG) Log.d(TAG, "Preparing encoder");
mVirtualDisplay = mMediaProjection.createVirtualDisplay(
TAG,
getGrabberWidth(), getGrabberHeight(), mDensity,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
null, mDisplayCallback, null);
setImageReader();
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void createAsyncCallback() {
callback = new MediaCodec.Callback() {
@Override
public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int inBufferIndex) {
try {
inputAvailable(mediaCodec, inBufferIndex, null);
} catch (IllegalStateException e) {
Log.i(TAG, "Encoding error", e);
}
}
@Override
public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int outBufferIndex,
@NonNull MediaCodec.BufferInfo bufferInfo) {
try {
outputAvailable(mediaCodec, outBufferIndex, bufferInfo);
} catch (IllegalStateException e) {
Log.i(TAG, "Encoding error", e);
}
}
@Override
public void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
Log.e(TAG, "Error", e);
}
@Override
public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
@NonNull MediaFormat mediaFormat) {
formatChanged(mediaCodec, mediaFormat);
}
};
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
static String formatCodecException(MediaCodec.CodecException exception) {
String diagnosticInformation = "diagnosticInformation=" + exception.getDiagnosticInfo();
String isTransient = " : isTransient=" + exception.isTransient();
String isRecoverable = " : isRecoverable=" + exception.isRecoverable();
return diagnosticInformation + isTransient + isRecoverable;
}
@Test
public void givenMediaCodecException_whenFormattingMessage_thenReturnsExpectedMessageFormat() {
MediaCodec.CodecException codecException = mock(MediaCodec.CodecException.class);
given(codecException.getDiagnosticInfo()).willReturn("android.media.MediaCodec.error_+1234");
given(codecException.isTransient()).willReturn(true);
given(codecException.isRecoverable()).willReturn(false);
String expectedFormat = "diagnosticInformation=android.media.MediaCodec.error_+1234 : isTransient=true : isRecoverable=false";
String actualFormat = ErrorFormatter.formatCodecException(codecException);
assertThat(actualFormat).isEqualTo(expectedFormat);
}
protected void onMediaCodecError(@NonNull MediaCodec.CodecException e) {
Log.e(TAG, "MediaCodec.onError: " + e.getLocalizedMessage());
if (listener != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
listener.onDecoderError(e);
} else {
listener.onDecoderError(new Exception("Error decoding audio file"));
}
}
}
@Override
public void onError(MediaCodec codec, MediaCodec.CodecException e) {
mCallback.onError(BaseEncoder.this, e);
}
@Override
public void onError(MediaCodec codec, MediaCodec.CodecException e) {
mCallback.onError(BaseEncoder.this, e);
}
/**
* 对视频先检查,如果不是全关键帧,先处理成所有帧都是关键帧,再逆序
*/
public static void reverseVideo(Context context, MediaSource input, String output, boolean reverseAudio, @Nullable VideoProgressListener listener) throws Exception {
File tempFile = new File(context.getCacheDir(), System.currentTimeMillis() + ".temp");
File temp2File = new File(context.getCacheDir(), System.currentTimeMillis() + ".temp2");
try {
MediaExtractor extractor = new MediaExtractor();
input.setDataSource(extractor);
int trackIndex = VideoUtil.selectTrack(extractor, false);
extractor.selectTrack(trackIndex);
int keyFrameCount = 0;
int frameCount = 0;
List<Long> frameTimeStamps = new ArrayList<>();
while (true) {
int flags = extractor.getSampleFlags();
if (flags > 0 && (flags & MediaExtractor.SAMPLE_FLAG_SYNC) != 0) {
keyFrameCount++;
}
long sampleTime = extractor.getSampleTime();
if (sampleTime < 0) {
break;
}
frameTimeStamps.add(sampleTime);
frameCount++;
extractor.advance();
}
extractor.release();
if (frameCount == keyFrameCount || frameCount == keyFrameCount + 1) {
reverseVideoNoDecode(input, output, reverseAudio, frameTimeStamps, listener);
} else {
VideoMultiStepProgress stepProgress = new VideoMultiStepProgress(new float[]{0.45f, 0.1f, 0.45f}, listener);
stepProgress.setCurrentStep(0);
float bitrateMultiple = (frameCount - keyFrameCount) / (float) keyFrameCount + 1;
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
input.setDataSource(retriever);
int oriBitrate = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE));
int duration = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
try {
processor(context)
.input(input)
.output(tempFile.getAbsolutePath())
.bitrate((int) (oriBitrate * bitrateMultiple))
.iFrameInterval(0)
.progressListener(stepProgress)
.process();
} catch (MediaCodec.CodecException e) {
CL.e(e);
/** Nexus5上-1代表全关键帧*/
processor(context)
.input(input)
.output(tempFile.getAbsolutePath())
.bitrate((int) (oriBitrate * bitrateMultiple))
.iFrameInterval(-1)
.progressListener(stepProgress)
.process();
}
stepProgress.setCurrentStep(1);
reverseVideoNoDecode(new MediaSource(tempFile.getAbsolutePath()), temp2File.getAbsolutePath(), reverseAudio, null, stepProgress);
int oriIFrameInterval = (int) (keyFrameCount / (duration / 1000f));
oriIFrameInterval = oriIFrameInterval == 0 ? 1 : oriIFrameInterval;
stepProgress.setCurrentStep(2);
processor(context)
.input(temp2File.getAbsolutePath())
.output(output)
.bitrate(oriBitrate)
.iFrameInterval(oriIFrameInterval)
.progressListener(stepProgress)
.process();
}
} finally {
tempFile.delete();
temp2File.delete();
}
}
@Override
public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
postOnError(new MediaEncoderException(e));
}