Commit 95d9e492 by Tolriq Committed by microkatz

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 972e169b
COPYBARA_INTEGRATE_REVIEW=go/exoghi/10762 from Tolriq:ffmpeg_error_code 82ceeb77d6df71f5ffb0474db66a36fd6eb8e51a
PiperOrigin-RevId: 487189910

(cherry picked from commit 6d2e7a1b)
parent 881838ba
Showing with 17 additions and 8 deletions
...@@ -89,6 +89,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -89,6 +89,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
uint8_t *outputBuffer, int outputSize); 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. * Outputs a log message describing the avcodec error number.
*/ */
void logError(const char *functionName, int errorNumber); void logError(const char *functionName, int errorNumber);
...@@ -264,8 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -264,8 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
result = avcodec_send_packet(context, packet); result = avcodec_send_packet(context, packet);
if (result) { if (result) {
logError("avcodec_send_packet", result); logError("avcodec_send_packet", result);
return result == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA return transformError(result);
: AUDIO_DECODER_ERROR_OTHER;
} }
// Dequeue output data until it runs out. // Dequeue output data until it runs out.
...@@ -274,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -274,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
AVFrame *frame = av_frame_alloc(); AVFrame *frame = av_frame_alloc();
if (!frame) { if (!frame) {
LOGE("Failed to allocate output frame."); LOGE("Failed to allocate output frame.");
return -1; return AUDIO_DECODER_ERROR_INVALID_DATA;
} }
result = avcodec_receive_frame(context, frame); result = avcodec_receive_frame(context, frame);
if (result) { if (result) {
...@@ -283,7 +287,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -283,7 +287,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
break; break;
} }
logError("avcodec_receive_frame", result); logError("avcodec_receive_frame", result);
return result; return transformError(result);
} }
// Resample output. // Resample output.
...@@ -311,7 +315,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -311,7 +315,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
if (result < 0) { if (result < 0) {
logError("swr_init", result); logError("swr_init", result);
av_frame_free(&frame); av_frame_free(&frame);
return -1; return transformError(result);
} }
context->opaque = resampleContext; context->opaque = resampleContext;
} }
...@@ -323,20 +327,20 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -323,20 +327,20 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
LOGE("Output buffer size (%d) too small for output data (%d).", LOGE("Output buffer size (%d) too small for output data (%d).",
outputSize, outSize + bufferOutSize); outputSize, outSize + bufferOutSize);
av_frame_free(&frame); av_frame_free(&frame);
return -1; return AUDIO_DECODER_ERROR_INVALID_DATA;
} }
result = swr_convert(resampleContext, &outputBuffer, bufferOutSize, result = swr_convert(resampleContext, &outputBuffer, bufferOutSize,
(const uint8_t **)frame->data, frame->nb_samples); (const uint8_t **)frame->data, frame->nb_samples);
av_frame_free(&frame); av_frame_free(&frame);
if (result < 0) { if (result < 0) {
logError("swr_convert", result); logError("swr_convert", result);
return result; return AUDIO_DECODER_ERROR_INVALID_DATA;
} }
int available = swr_get_out_samples(resampleContext, 0); int available = swr_get_out_samples(resampleContext, 0);
if (available != 0) { if (available != 0) {
LOGE("Expected no samples remaining after resampling, but found %d.", LOGE("Expected no samples remaining after resampling, but found %d.",
available); available);
return -1; return AUDIO_DECODER_ERROR_INVALID_DATA;
} }
outputBuffer += bufferOutSize; outputBuffer += bufferOutSize;
outSize += bufferOutSize; outSize += bufferOutSize;
...@@ -344,6 +348,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet, ...@@ -344,6 +348,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
return outSize; 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) { void logError(const char *functionName, int errorNumber) {
char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char)); char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH); av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment