Skip to content

Commit 33484b0

Browse files
copybara-githubmicrokatz
authored andcommitted
Merge pull request #707 from equeim:ffmpeg-6.0
PiperOrigin-RevId: 584893190 (cherry picked from commit 45b51d8)
1 parent 5e86c4c commit 33484b0

File tree

5 files changed

+70
-46
lines changed

5 files changed

+70
-46
lines changed

RELEASENOTES.md

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
* Decoder Extensions (FFmpeg, VP9, AV1, MIDI, etc.):
4747
* MIDI: Fix issue where seeking forward skips the Program Change events
4848
([#704](https://github.com/androidx/media/issues/704).
49+
* Migrate to FFmpeg 6.0
50+
([#707](https://github.com/androidx/media/pull/707)).
4951
* Leanback extension:
5052
* Cast Extension:
5153
* Sanitize creation of a `Timeline` to not crash the app when loading

libraries/decoder_ffmpeg/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@ NDK_PATH="<path to Android NDK>"
4141
HOST_PLATFORM="linux-x86_64"
4242
```
4343

44-
* Fetch FFmpeg and checkout an appropriate branch. We cannot guarantee
45-
compatibility with all versions of FFmpeg. We currently recommend version 4.2:
44+
* Fetch FFmpeg and checkout an appropriate branch. We cannot guarantee
45+
compatibility with all versions of FFmpeg. We currently recommend version
46+
6.0:
4647

4748
```
4849
cd "<preferred location for ffmpeg>" && \
4950
git clone git://source.ffmpeg.org/ffmpeg && \
5051
cd ffmpeg && \
51-
git checkout release/4.2 && \
52+
git checkout release/6.0 && \
5253
FFMPEG_PATH="$(pwd)"
5354
```
5455

libraries/decoder_ffmpeg/src/main/jni/CMakeLists.txt

+6-6
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ set(CMAKE_CXX_STANDARD 11)
2121

2222
project(libffmpegJNI C CXX)
2323

24-
# Additional flags needed for "arm64-v8a" from NDK 23.1.7779620 and above.
25-
# See https://github.com/google/ExoPlayer/issues/9933#issuecomment-1029775358.
26-
if(${ANDROID_ABI} MATCHES "arm64-v8a")
27-
set(CMAKE_CXX_FLAGS "-Wl,-Bsymbolic")
28-
endif()
29-
3024
set(ffmpeg_location "${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg")
3125
set(ffmpeg_binaries "${ffmpeg_location}/android-libs/${ANDROID_ABI}")
3226

@@ -56,3 +50,9 @@ target_link_libraries(ffmpegJNI
5650
PRIVATE avcodec
5751
PRIVATE avutil
5852
PRIVATE ${android_log_lib})
53+
54+
# Additional flags needed for "arm64-v8a" from NDK 23.1.7779620 and above.
55+
# See https://github.com/google/ExoPlayer/issues/9933#issuecomment-1029775358.
56+
if(ANDROID_ABI STREQUAL "arm64-v8a")
57+
target_link_options(ffmpegJNI PRIVATE "-Wl,-Bsymbolic")
58+
endif()

libraries/decoder_ffmpeg/src/main/jni/build_ffmpeg.sh

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ COMMON_OPTIONS="
3535
--disable-postproc
3636
--disable-avfilter
3737
--disable-symver
38-
--disable-avresample
3938
--enable-swresample
4039
--extra-ldexeflags=-pie
40+
--disable-v4l2-m2m
41+
--disable-vulkan
4142
"
4243
TOOLCHAIN_PREFIX="${NDK_PATH}/toolchains/llvm/prebuilt/${HOST_PLATFORM}/bin"
4344
for decoder in "${ENABLED_DECODERS[@]}"

libraries/decoder_ffmpeg/src/main/jni/ffmpeg_jni.cc

+56-36
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,16 @@ static const int AUDIO_DECODER_ERROR_OTHER = -2;
7070
/**
7171
* Returns the AVCodec with the specified name, or NULL if it is not available.
7272
*/
73-
AVCodec *getCodecByName(JNIEnv *env, jstring codecName);
73+
const AVCodec *getCodecByName(JNIEnv *env, jstring codecName);
7474

7575
/**
7676
* Allocates and opens a new AVCodecContext for the specified codec, passing the
7777
* provided extraData as initialization data for the decoder if it is non-NULL.
7878
* Returns the created context.
7979
*/
80-
AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
81-
jboolean outputFloat, jint rawSampleRate,
82-
jint rawChannelCount);
80+
AVCodecContext *createContext(JNIEnv *env, const AVCodec *codec,
81+
jbyteArray extraData, jboolean outputFloat,
82+
jint rawSampleRate, jint rawChannelCount);
8383

8484
/**
8585
* Decodes the packet into the output buffer, returning the number of bytes
@@ -109,7 +109,6 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
109109
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
110110
return -1;
111111
}
112-
avcodec_register_all();
113112
return JNI_VERSION_1_6;
114113
}
115114

@@ -128,7 +127,7 @@ LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
128127
AUDIO_DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName,
129128
jbyteArray extraData, jboolean outputFloat,
130129
jint rawSampleRate, jint rawChannelCount) {
131-
AVCodec *codec = getCodecByName(env, codecName);
130+
const AVCodec *codec = getCodecByName(env, codecName);
132131
if (!codec) {
133132
LOGE("Codec not found.");
134133
return 0L;
@@ -157,20 +156,38 @@ AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
157156
}
158157
uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress(inputData);
159158
uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress(outputData);
160-
AVPacket packet;
161-
av_init_packet(&packet);
162-
packet.data = inputBuffer;
163-
packet.size = inputSize;
164-
return decodePacket((AVCodecContext *)context, &packet, outputBuffer,
165-
outputSize);
159+
AVPacket *packet = av_packet_alloc();
160+
if (!packet) {
161+
LOGE("Failed to allocate packet.");
162+
return -1;
163+
}
164+
packet->data = inputBuffer;
165+
packet->size = inputSize;
166+
const int ret =
167+
decodePacket((AVCodecContext *)context, packet, outputBuffer, outputSize,
168+
GrowOutputBufferCallback{env, thiz, decoderOutputBuffer});
169+
av_packet_free(&packet);
170+
return ret;
171+
}
172+
173+
uint8_t *GrowOutputBufferCallback::operator()(int requiredSize) const {
174+
jobject newOutputData = env->CallObjectMethod(
175+
thiz, growOutputBufferMethod, decoderOutputBuffer, requiredSize);
176+
if (env->ExceptionCheck()) {
177+
LOGE("growOutputBuffer() failed");
178+
env->ExceptionDescribe();
179+
return nullptr;
180+
}
181+
return static_cast<uint8_t *>(env->GetDirectBufferAddress(newOutputData));
182+
>>>>>>> 45b51d8c97 (Merge pull request #707 from equeim:ffmpeg-6.0)
166183
}
167184

168185
AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
169186
if (!context) {
170187
LOGE("Context must be non-NULL.");
171188
return -1;
172189
}
173-
return ((AVCodecContext *)context)->channels;
190+
return ((AVCodecContext *)context)->ch_layout.nb_channels;
174191
}
175192

176193
AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
@@ -193,7 +210,7 @@ AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
193210
// Release and recreate the context if the codec is TrueHD.
194211
// TODO: Figure out why flushing doesn't work for this codec.
195212
releaseContext(context);
196-
AVCodec *codec = avcodec_find_decoder(codecId);
213+
const AVCodec *codec = avcodec_find_decoder(codecId);
197214
if (!codec) {
198215
LOGE("Unexpected error finding codec %d.", codecId);
199216
return 0L;
@@ -215,19 +232,19 @@ AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) {
215232
}
216233
}
217234

218-
AVCodec *getCodecByName(JNIEnv *env, jstring codecName) {
235+
const AVCodec *getCodecByName(JNIEnv *env, jstring codecName) {
219236
if (!codecName) {
220237
return NULL;
221238
}
222239
const char *codecNameChars = env->GetStringUTFChars(codecName, NULL);
223-
AVCodec *codec = avcodec_find_decoder_by_name(codecNameChars);
240+
const AVCodec *codec = avcodec_find_decoder_by_name(codecNameChars);
224241
env->ReleaseStringUTFChars(codecName, codecNameChars);
225242
return codec;
226243
}
227244

228-
AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
229-
jboolean outputFloat, jint rawSampleRate,
230-
jint rawChannelCount) {
245+
AVCodecContext *createContext(JNIEnv *env, const AVCodec *codec,
246+
jbyteArray extraData, jboolean outputFloat,
247+
jint rawSampleRate, jint rawChannelCount) {
231248
AVCodecContext *context = avcodec_alloc_context3(codec);
232249
if (!context) {
233250
LOGE("Failed to allocate context.");
@@ -250,8 +267,7 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
250267
if (context->codec_id == AV_CODEC_ID_PCM_MULAW ||
251268
context->codec_id == AV_CODEC_ID_PCM_ALAW) {
252269
context->sample_rate = rawSampleRate;
253-
context->channels = rawChannelCount;
254-
context->channel_layout = av_get_default_channel_layout(rawChannelCount);
270+
av_channel_layout_default(&context->ch_layout, rawChannelCount);
255271
}
256272
context->err_recognition = AV_EF_IGNORE_ERR;
257273
int result = avcodec_open2(context, codec, NULL);
@@ -293,25 +309,29 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
293309

294310
// Resample output.
295311
AVSampleFormat sampleFormat = context->sample_fmt;
296-
int channelCount = context->channels;
297-
int channelLayout = context->channel_layout;
312+
int channelCount = context->ch_layout.nb_channels;
298313
int sampleRate = context->sample_rate;
299314
int sampleCount = frame->nb_samples;
300315
int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
301316
sampleFormat, 1);
302-
SwrContext *resampleContext;
303-
if (context->opaque) {
304-
resampleContext = (SwrContext *)context->opaque;
305-
} else {
306-
resampleContext = swr_alloc();
307-
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
308-
av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
309-
av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
310-
av_opt_set_int(resampleContext, "out_sample_rate", sampleRate, 0);
311-
av_opt_set_int(resampleContext, "in_sample_fmt", sampleFormat, 0);
312-
// The output format is always the requested format.
313-
av_opt_set_int(resampleContext, "out_sample_fmt",
314-
context->request_sample_fmt, 0);
317+
SwrContext *resampleContext = static_cast<SwrContext *>(context->opaque);
318+
if (!resampleContext) {
319+
result =
320+
swr_alloc_set_opts2(&resampleContext, // ps
321+
&context->ch_layout, // out_ch_layout
322+
context->request_sample_fmt, // out_sample_fmt
323+
sampleRate, // out_sample_rate
324+
&context->ch_layout, // in_ch_layout
325+
sampleFormat, // in_sample_fmt
326+
sampleRate, // in_sample_rate
327+
0, // log_offset
328+
NULL // log_ctx
329+
);
330+
if (result < 0) {
331+
logError("swr_alloc_set_opts2", result);
332+
av_frame_free(&frame);
333+
return transformError(result);
334+
}
315335
result = swr_init(resampleContext);
316336
if (result < 0) {
317337
logError("swr_init", result);

0 commit comments

Comments
 (0)