From a1c04cd47330bc4104b0b8dea1aa977f35bb9ed9 Mon Sep 17 00:00:00 2001 From: Tolriq Date: Wed, 9 Nov 2022 10:53:52 +0000 Subject: [PATCH] Merge Issue: google/ExoPlayer#10762: Fix ffmpeg jni wrapper returning invalid result codes Imported from GitHub PR Issue: google/ExoPlayer#10762 This ensure that ffmpeg error code are properly translated to values that the ExoPlayer decoder understand. The main gain is that it allows the decoder to properly ignore more cases of invalid data and recover. The second gain is that the other errors are now proper ExoPlayer errors and no more obscure buffer ones. Fixes: Issue: google/ExoPlayer#10760 Merge 82ceeb77d6df71f5ffb0474db66a36fd6eb8e51a into 972e169bd85b14848dcae75e34f9e95fe87e1f4b COPYBARA_INTEGRATE_REVIEW=go/exoghi/10762 from Tolriq:ffmpeg_error_code 82ceeb77d6df71f5ffb0474db66a36fd6eb8e51a PiperOrigin-RevId: 487189910 --- .../decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc b/libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc index c4c650a888..17b4d747c9 100644 --- a/libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc +++ b/libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc @@ -89,6 +89,11 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData, int decodePacket(AVCodecContext *context, AVPacket *packet, uint8_t *outputBuffer, int outputSize); +/** + * Transforms ffmpeg AVERROR into a negative AUDIO_DECODER_ERROR constant value. + */ +int transformError(const char *functionName, int errorNumber); + /** * Outputs a log message describing the avcodec error number. */ @@ -265,8 +270,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, result = avcodec_send_packet(context, packet); if (result) { logError("avcodec_send_packet", result); - return result == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA - : AUDIO_DECODER_ERROR_OTHER; + return transformError(result); } // Dequeue output data until it runs out. @@ -275,7 +279,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, AVFrame *frame = av_frame_alloc(); if (!frame) { LOGE("Failed to allocate output frame."); - return -1; + return AUDIO_DECODER_ERROR_INVALID_DATA; } result = avcodec_receive_frame(context, frame); if (result) { @@ -284,7 +288,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, break; } logError("avcodec_receive_frame", result); - return result; + return transformError(result); } // Resample output. @@ -312,7 +316,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, if (result < 0) { logError("swr_init", result); av_frame_free(&frame); - return -1; + return transformError(result); } context->opaque = resampleContext; } @@ -324,20 +328,20 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, LOGE("Output buffer size (%d) too small for output data (%d).", outputSize, outSize + bufferOutSize); av_frame_free(&frame); - return -1; + return AUDIO_DECODER_ERROR_INVALID_DATA; } result = swr_convert(resampleContext, &outputBuffer, bufferOutSize, (const uint8_t **)frame->data, frame->nb_samples); av_frame_free(&frame); if (result < 0) { logError("swr_convert", result); - return result; + return AUDIO_DECODER_ERROR_INVALID_DATA; } int available = swr_get_out_samples(resampleContext, 0); if (available != 0) { LOGE("Expected no samples remaining after resampling, but found %d.", available); - return -1; + return AUDIO_DECODER_ERROR_INVALID_DATA; } outputBuffer += bufferOutSize; outSize += bufferOutSize; @@ -345,6 +349,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, return outSize; } +int transformError(int result) { + return result == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA + : AUDIO_DECODER_ERROR_OTHER; +} + void logError(const char *functionName, int errorNumber) { char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char)); av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);