Skip to content

Commit

Permalink
Merge Issue: google/ExoPlayer#10762: Fix ffmpeg jni wrapper returning…
Browse files Browse the repository at this point in the history
… 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 972e169
COPYBARA_INTEGRATE_REVIEW=go/exoghi/10762 from Tolriq:ffmpeg_error_code 82ceeb77d6df71f5ffb0474db66a36fd6eb8e51a
PiperOrigin-RevId: 487189910

(cherry picked from commit a1c04cd)
  • Loading branch information
Tolriq authored and microkatz committed Nov 9, 2022
1 parent 5976955 commit d262f76
Showing 1 changed file with 17 additions and 8 deletions.
25 changes: 17 additions & 8 deletions libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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.
Expand All @@ -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) {
Expand All @@ -284,7 +288,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
break;
}
logError("avcodec_receive_frame", result);
return result;
return transformError(result);
}

// Resample output.
Expand Down Expand Up @@ -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;
}
Expand All @@ -324,27 +328,32 @@ 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;
}
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);
Expand Down

0 comments on commit d262f76

Please sign in to comment.