• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <android/log.h>
17 #include <jni.h>
18 #include <stdlib.h>
19 
20 extern "C" {
21 #ifdef __cplusplus
22 #define __STDC_CONSTANT_MACROS
23 #ifdef _STDINT_H
24 #undef _STDINT_H
25 #endif
26 #include <stdint.h>
27 #endif
28 #include <libavcodec/avcodec.h>
29 #include <libavutil/channel_layout.h>
30 #include <libavutil/error.h>
31 #include <libavutil/opt.h>
32 #include <libswresample/swresample.h>
33 }
34 
35 #define LOG_TAG "ffmpeg_jni"
36 #define LOGE(...) \
37   ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
38 
39 #define LIBRARY_FUNC(RETURN_TYPE, NAME, ...)                              \
40   extern "C" {                                                            \
41   JNIEXPORT RETURN_TYPE                                                   \
42       Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
43           JNIEnv *env, jobject thiz, ##__VA_ARGS__);                      \
44   }                                                                       \
45   JNIEXPORT RETURN_TYPE                                                   \
46       Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
47           JNIEnv *env, jobject thiz, ##__VA_ARGS__)
48 
49 #define AUDIO_DECODER_FUNC(RETURN_TYPE, NAME, ...)                             \
50   extern "C" {                                                                 \
51   JNIEXPORT RETURN_TYPE                                                        \
52       Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
53           JNIEnv *env, jobject thiz, ##__VA_ARGS__);                           \
54   }                                                                            \
55   JNIEXPORT RETURN_TYPE                                                        \
56       Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
57           JNIEnv *env, jobject thiz, ##__VA_ARGS__)
58 
59 #define ERROR_STRING_BUFFER_LENGTH 256
60 
61 // Output format corresponding to AudioFormat.ENCODING_PCM_16BIT.
62 static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16;
63 // Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
64 static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;
65 
66 static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1;
67 static const int AUDIO_DECODER_ERROR_OTHER = -2;
68 
69 /**
70  * Returns the AVCodec with the specified name, or NULL if it is not available.
71  */
72 AVCodec *getCodecByName(JNIEnv *env, jstring codecName);
73 
74 /**
75  * Allocates and opens a new AVCodecContext for the specified codec, passing the
76  * provided extraData as initialization data for the decoder if it is non-NULL.
77  * Returns the created context.
78  */
79 AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
80                               jboolean outputFloat, jint rawSampleRate,
81                               jint rawChannelCount);
82 
83 /**
84  * Decodes the packet into the output buffer, returning the number of bytes
85  * written, or a negative AUDIO_DECODER_ERROR constant value in the case of an
86  * error.
87  */
88 int decodePacket(AVCodecContext *context, AVPacket *packet,
89                  uint8_t *outputBuffer, int outputSize);
90 
91 /**
92  * Outputs a log message describing the avcodec error number.
93  */
94 void logError(const char *functionName, int errorNumber);
95 
96 /**
97  * Releases the specified context.
98  */
99 void releaseContext(AVCodecContext *context);
100 
JNI_OnLoad(JavaVM * vm,void * reserved)101 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
102   JNIEnv *env;
103   if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
104     return -1;
105   }
106   avcodec_register_all();
107   return JNI_VERSION_1_6;
108 }
109 
LIBRARY_FUNC(jstring,ffmpegGetVersion)110 LIBRARY_FUNC(jstring, ffmpegGetVersion) {
111   return env->NewStringUTF(LIBAVCODEC_IDENT);
112 }
113 
LIBRARY_FUNC(jint,ffmpegGetInputBufferPaddingSize)114 LIBRARY_FUNC(jint, ffmpegGetInputBufferPaddingSize) {
115   return (jint)AV_INPUT_BUFFER_PADDING_SIZE;
116 }
117 
LIBRARY_FUNC(jboolean,ffmpegHasDecoder,jstring codecName)118 LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
119   return getCodecByName(env, codecName) != NULL;
120 }
121 
AUDIO_DECODER_FUNC(jlong,ffmpegInitialize,jstring codecName,jbyteArray extraData,jboolean outputFloat,jint rawSampleRate,jint rawChannelCount)122 AUDIO_DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName,
123                    jbyteArray extraData, jboolean outputFloat,
124                    jint rawSampleRate, jint rawChannelCount) {
125   AVCodec *codec = getCodecByName(env, codecName);
126   if (!codec) {
127     LOGE("Codec not found.");
128     return 0L;
129   }
130   return (jlong)createContext(env, codec, extraData, outputFloat, rawSampleRate,
131                               rawChannelCount);
132 }
133 
AUDIO_DECODER_FUNC(jint,ffmpegDecode,jlong context,jobject inputData,jint inputSize,jobject outputData,jint outputSize)134 AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
135                    jint inputSize, jobject outputData, jint outputSize) {
136   if (!context) {
137     LOGE("Context must be non-NULL.");
138     return -1;
139   }
140   if (!inputData || !outputData) {
141     LOGE("Input and output buffers must be non-NULL.");
142     return -1;
143   }
144   if (inputSize < 0) {
145     LOGE("Invalid input buffer size: %d.", inputSize);
146     return -1;
147   }
148   if (outputSize < 0) {
149     LOGE("Invalid output buffer length: %d", outputSize);
150     return -1;
151   }
152   uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress(inputData);
153   uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress(outputData);
154   AVPacket packet;
155   av_init_packet(&packet);
156   packet.data = inputBuffer;
157   packet.size = inputSize;
158   return decodePacket((AVCodecContext *)context, &packet, outputBuffer,
159                       outputSize);
160 }
161 
AUDIO_DECODER_FUNC(jint,ffmpegGetChannelCount,jlong context)162 AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
163   if (!context) {
164     LOGE("Context must be non-NULL.");
165     return -1;
166   }
167   return ((AVCodecContext *)context)->channels;
168 }
169 
AUDIO_DECODER_FUNC(jint,ffmpegGetSampleRate,jlong context)170 AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
171   if (!context) {
172     LOGE("Context must be non-NULL.");
173     return -1;
174   }
175   return ((AVCodecContext *)context)->sample_rate;
176 }
177 
AUDIO_DECODER_FUNC(jlong,ffmpegReset,jlong jContext,jbyteArray extraData)178 AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
179   AVCodecContext *context = (AVCodecContext *)jContext;
180   if (!context) {
181     LOGE("Tried to reset without a context.");
182     return 0L;
183   }
184 
185   AVCodecID codecId = context->codec_id;
186   if (codecId == AV_CODEC_ID_TRUEHD) {
187     // Release and recreate the context if the codec is TrueHD.
188     // TODO: Figure out why flushing doesn't work for this codec.
189     releaseContext(context);
190     AVCodec *codec = avcodec_find_decoder(codecId);
191     if (!codec) {
192       LOGE("Unexpected error finding codec %d.", codecId);
193       return 0L;
194     }
195     jboolean outputFloat =
196         (jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
197     return (jlong)createContext(env, codec, extraData, outputFloat,
198                                 /* rawSampleRate= */ -1,
199                                 /* rawChannelCount= */ -1);
200   }
201 
202   avcodec_flush_buffers(context);
203   return (jlong)context;
204 }
205 
AUDIO_DECODER_FUNC(void,ffmpegRelease,jlong context)206 AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) {
207   if (context) {
208     releaseContext((AVCodecContext *)context);
209   }
210 }
211 
getCodecByName(JNIEnv * env,jstring codecName)212 AVCodec *getCodecByName(JNIEnv *env, jstring codecName) {
213   if (!codecName) {
214     return NULL;
215   }
216   const char *codecNameChars = env->GetStringUTFChars(codecName, NULL);
217   AVCodec *codec = avcodec_find_decoder_by_name(codecNameChars);
218   env->ReleaseStringUTFChars(codecName, codecNameChars);
219   return codec;
220 }
221 
createContext(JNIEnv * env,AVCodec * codec,jbyteArray extraData,jboolean outputFloat,jint rawSampleRate,jint rawChannelCount)222 AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
223                               jboolean outputFloat, jint rawSampleRate,
224                               jint rawChannelCount) {
225   AVCodecContext *context = avcodec_alloc_context3(codec);
226   if (!context) {
227     LOGE("Failed to allocate context.");
228     return NULL;
229   }
230   context->request_sample_fmt =
231       outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
232   if (extraData) {
233     jsize size = env->GetArrayLength(extraData);
234     context->extradata_size = size;
235     context->extradata =
236         (uint8_t *)av_malloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
237     if (!context->extradata) {
238       LOGE("Failed to allocate extradata.");
239       releaseContext(context);
240       return NULL;
241     }
242     env->GetByteArrayRegion(extraData, 0, size, (jbyte *)context->extradata);
243   }
244   if (context->codec_id == AV_CODEC_ID_PCM_MULAW ||
245       context->codec_id == AV_CODEC_ID_PCM_ALAW) {
246     context->sample_rate = rawSampleRate;
247     context->channels = rawChannelCount;
248     context->channel_layout = av_get_default_channel_layout(rawChannelCount);
249   }
250   context->err_recognition = AV_EF_IGNORE_ERR;
251   int result = avcodec_open2(context, codec, NULL);
252   if (result < 0) {
253     logError("avcodec_open2", result);
254     releaseContext(context);
255     return NULL;
256   }
257   return context;
258 }
259 
decodePacket(AVCodecContext * context,AVPacket * packet,uint8_t * outputBuffer,int outputSize)260 int decodePacket(AVCodecContext *context, AVPacket *packet,
261                  uint8_t *outputBuffer, int outputSize) {
262   int result = 0;
263   // Queue input data.
264   result = avcodec_send_packet(context, packet);
265   if (result) {
266     logError("avcodec_send_packet", result);
267     return result == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA
268                                          : AUDIO_DECODER_ERROR_OTHER;
269   }
270 
271   // Dequeue output data until it runs out.
272   int outSize = 0;
273   while (true) {
274     AVFrame *frame = av_frame_alloc();
275     if (!frame) {
276       LOGE("Failed to allocate output frame.");
277       return -1;
278     }
279     result = avcodec_receive_frame(context, frame);
280     if (result) {
281       av_frame_free(&frame);
282       if (result == AVERROR(EAGAIN)) {
283         break;
284       }
285       logError("avcodec_receive_frame", result);
286       return result;
287     }
288 
289     // Resample output.
290     AVSampleFormat sampleFormat = context->sample_fmt;
291     int channelCount = context->channels;
292     int channelLayout = context->channel_layout;
293     int sampleRate = context->sample_rate;
294     int sampleCount = frame->nb_samples;
295     int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
296                                               sampleFormat, 1);
297     SwrContext *resampleContext;
298     if (context->opaque) {
299       resampleContext = (SwrContext *)context->opaque;
300     } else {
301       resampleContext = swr_alloc();
302       av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
303       av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
304       av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
305       av_opt_set_int(resampleContext, "out_sample_rate", sampleRate, 0);
306       av_opt_set_int(resampleContext, "in_sample_fmt", sampleFormat, 0);
307       // The output format is always the requested format.
308       av_opt_set_int(resampleContext, "out_sample_fmt",
309                      context->request_sample_fmt, 0);
310       result = swr_init(resampleContext);
311       if (result < 0) {
312         logError("swr_init", result);
313         av_frame_free(&frame);
314         return -1;
315       }
316       context->opaque = resampleContext;
317     }
318     int inSampleSize = av_get_bytes_per_sample(sampleFormat);
319     int outSampleSize = av_get_bytes_per_sample(context->request_sample_fmt);
320     int outSamples = swr_get_out_samples(resampleContext, sampleCount);
321     int bufferOutSize = outSampleSize * channelCount * outSamples;
322     if (outSize + bufferOutSize > outputSize) {
323       LOGE("Output buffer size (%d) too small for output data (%d).",
324            outputSize, outSize + bufferOutSize);
325       av_frame_free(&frame);
326       return -1;
327     }
328     result = swr_convert(resampleContext, &outputBuffer, bufferOutSize,
329                          (const uint8_t **)frame->data, frame->nb_samples);
330     av_frame_free(&frame);
331     if (result < 0) {
332       logError("swr_convert", result);
333       return result;
334     }
335     int available = swr_get_out_samples(resampleContext, 0);
336     if (available != 0) {
337       LOGE("Expected no samples remaining after resampling, but found %d.",
338            available);
339       return -1;
340     }
341     outputBuffer += bufferOutSize;
342     outSize += bufferOutSize;
343   }
344   return outSize;
345 }
346 
logError(const char * functionName,int errorNumber)347 void logError(const char *functionName, int errorNumber) {
348   char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
349   av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
350   LOGE("Error in %s: %s", functionName, buffer);
351   free(buffer);
352 }
353 
releaseContext(AVCodecContext * context)354 void releaseContext(AVCodecContext *context) {
355   if (!context) {
356     return;
357   }
358   SwrContext *swrContext;
359   if ((swrContext = (SwrContext *)context->opaque)) {
360     swr_free(&swrContext);
361     context->opaque = NULL;
362   }
363   avcodec_free_context(&context);
364 }
365