13
13
* See the License for the specific language governing permissions and
14
14
* limitations under the License.
15
15
*/
16
+ #include < android/log.h>
16
17
#include < jni.h>
17
18
#include < stdlib.h>
18
- #include < android/log.h>
19
19
20
20
extern " C" {
21
21
#ifdef __cplusplus
22
+ #define __STDC_CONSTANT_MACROS
22
23
#ifdef _STDINT_H
23
24
#undef _STDINT_H
24
25
#endif
25
26
#include < stdint.h>
26
27
#endif
27
28
#include < libavcodec/avcodec.h>
28
- #include < libavresample/avresample.h>
29
29
#include < libavutil/channel_layout.h>
30
30
#include < libavutil/error.h>
31
31
#include < libavutil/opt.h>
32
+ #include < libswresample/swresample.h>
32
33
}
33
34
34
35
#define LOG_TAG " ffmpeg_jni"
35
- #define LOGE (...) (( void )__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
36
- __VA_ARGS__))
37
-
38
- #define DECODER_FUNC (RETURN_TYPE, NAME, ...) \
39
- extern " C" { \
40
- JNIEXPORT RETURN_TYPE \
41
- Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
42
- ( JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
43
- } \
44
- JNIEXPORT RETURN_TYPE \
45
- Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
46
- ( JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
47
-
48
- #define LIBRARY_FUNC (RETURN_TYPE, NAME, ...) \
49
- extern " C" { \
50
- JNIEXPORT RETURN_TYPE \
51
- Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
52
- ( JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
53
- } \
54
- JNIEXPORT RETURN_TYPE \
55
- Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
56
- ( JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
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__)
57
58
58
59
#define ERROR_STRING_BUFFER_LENGTH 256
59
60
@@ -62,14 +63,13 @@ static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16;
62
63
// Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
63
64
static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;
64
65
65
- // Error codes matching FfmpegDecoder.java.
66
- static const int DECODER_ERROR_INVALID_DATA = -1 ;
67
- static const int DECODER_ERROR_OTHER = -2 ;
66
+ static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1 ;
67
+ static const int AUDIO_DECODER_ERROR_OTHER = -2 ;
68
68
69
69
/* *
70
70
* Returns the AVCodec with the specified name, or NULL if it is not available.
71
71
*/
72
- AVCodec *getCodecByName (JNIEnv* env, jstring codecName);
72
+ AVCodec *getCodecByName (JNIEnv * env, jstring codecName);
73
73
74
74
/* *
75
75
* Allocates and opens a new AVCodecContext for the specified codec, passing the
@@ -82,11 +82,17 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
82
82
83
83
/* *
84
84
* Decodes the packet into the output buffer, returning the number of bytes
85
- * written, or a negative DECODER_ERROR constant value in the case of an error.
85
+ * written, or a negative AUDIO_DECODER_ERROR constant value in the case of an
86
+ * error.
86
87
*/
87
88
int decodePacket (AVCodecContext *context, AVPacket *packet,
88
89
uint8_t *outputBuffer, int outputSize);
89
90
91
+ /* *
92
+ * Transforms ffmpeg AVERROR into a negative AUDIO_DECODER_ERROR constant value.
93
+ */
94
+ int transformError (int errorNumber);
95
+
90
96
/* *
91
97
* Outputs a log message describing the avcodec error number.
92
98
*/
@@ -101,12 +107,17 @@ LIBRARY_FUNC(jstring, ffmpegGetVersion) {
101
107
return env->NewStringUTF (LIBAVCODEC_IDENT);
102
108
}
103
109
110
+ LIBRARY_FUNC (jint, ffmpegGetInputBufferPaddingSize) {
111
+ return (jint)AV_INPUT_BUFFER_PADDING_SIZE;
112
+ }
113
+
104
114
LIBRARY_FUNC (jboolean, ffmpegHasDecoder, jstring codecName) {
105
115
return getCodecByName (env, codecName) != NULL ;
106
116
}
107
117
108
- DECODER_FUNC (jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
109
- jboolean outputFloat, jint rawSampleRate, jint rawChannelCount) {
118
+ AUDIO_DECODER_FUNC (jlong, ffmpegInitialize, jstring codecName,
119
+ jbyteArray extraData, jboolean outputFloat,
120
+ jint rawSampleRate, jint rawChannelCount) {
110
121
AVCodec *codec = getCodecByName (env, codecName);
111
122
if (!codec) {
112
123
LOGE (" Codec not found." );
@@ -116,8 +127,8 @@ DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
116
127
rawChannelCount);
117
128
}
118
129
119
- DECODER_FUNC (jint, ffmpegDecode, jlong context, jobject inputData,
120
- jint inputSize, jobject outputData, jint outputSize) {
130
+ AUDIO_DECODER_FUNC (jint, ffmpegDecode, jlong context, jobject inputData,
131
+ jint inputSize, jobject outputData, jint outputSize) {
121
132
if (!context) {
122
133
LOGE (" Context must be non-NULL." );
123
134
return -1 ;
@@ -134,34 +145,34 @@ DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
134
145
LOGE (" Invalid output buffer length: %d" , outputSize);
135
146
return -1 ;
136
147
}
137
- uint8_t *inputBuffer = (uint8_t *) env->GetDirectBufferAddress (inputData);
138
- uint8_t *outputBuffer = (uint8_t *) env->GetDirectBufferAddress (outputData);
148
+ uint8_t *inputBuffer = (uint8_t *)env->GetDirectBufferAddress (inputData);
149
+ uint8_t *outputBuffer = (uint8_t *)env->GetDirectBufferAddress (outputData);
139
150
AVPacket packet;
140
151
av_init_packet (&packet);
141
152
packet.data = inputBuffer;
142
153
packet.size = inputSize;
143
- return decodePacket ((AVCodecContext *) context, &packet, outputBuffer,
154
+ return decodePacket ((AVCodecContext *)context, &packet, outputBuffer,
144
155
outputSize);
145
156
}
146
157
147
- DECODER_FUNC (jint, ffmpegGetChannelCount, jlong context) {
158
+ AUDIO_DECODER_FUNC (jint, ffmpegGetChannelCount, jlong context) {
148
159
if (!context) {
149
160
LOGE (" Context must be non-NULL." );
150
161
return -1 ;
151
162
}
152
- return ((AVCodecContext *) context)->channels ;
163
+ return ((AVCodecContext *)context)->channels ;
153
164
}
154
165
155
- DECODER_FUNC (jint, ffmpegGetSampleRate, jlong context) {
166
+ AUDIO_DECODER_FUNC (jint, ffmpegGetSampleRate, jlong context) {
156
167
if (!context) {
157
168
LOGE (" Context must be non-NULL." );
158
169
return -1 ;
159
170
}
160
- return ((AVCodecContext *) context)->sample_rate ;
171
+ return ((AVCodecContext *)context)->sample_rate ;
161
172
}
162
173
163
- DECODER_FUNC (jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
164
- AVCodecContext *context = (AVCodecContext *) jContext;
174
+ AUDIO_DECODER_FUNC (jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
175
+ AVCodecContext *context = (AVCodecContext *)jContext;
165
176
if (!context) {
166
177
LOGE (" Tried to reset without a context." );
167
178
return 0L ;
@@ -178,23 +189,23 @@ DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
178
189
return 0L ;
179
190
}
180
191
jboolean outputFloat =
181
- (jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
192
+ (jboolean)(context->request_sample_fmt == OUTPUT_FORMAT_PCM_FLOAT);
182
193
return (jlong)createContext (env, codec, extraData, outputFloat,
183
- /* rawSampleRate= */ -1 ,
184
- /* rawChannelCount= */ -1 );
194
+ /* rawSampleRate= */ -1 ,
195
+ /* rawChannelCount= */ -1 );
185
196
}
186
197
187
198
avcodec_flush_buffers (context);
188
- return (jlong) context;
199
+ return (jlong)context;
189
200
}
190
201
191
- DECODER_FUNC (void , ffmpegRelease, jlong context) {
202
+ AUDIO_DECODER_FUNC (void , ffmpegRelease, jlong context) {
192
203
if (context) {
193
- releaseContext ((AVCodecContext *) context);
204
+ releaseContext ((AVCodecContext *)context);
194
205
}
195
206
}
196
207
197
- AVCodec *getCodecByName (JNIEnv* env, jstring codecName) {
208
+ AVCodec *getCodecByName (JNIEnv * env, jstring codecName) {
198
209
if (!codecName) {
199
210
return NULL ;
200
211
}
@@ -213,18 +224,18 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
213
224
return NULL ;
214
225
}
215
226
context->request_sample_fmt =
216
- outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
227
+ outputFloat ? OUTPUT_FORMAT_PCM_FLOAT : OUTPUT_FORMAT_PCM_16BIT;
217
228
if (extraData) {
218
229
jsize size = env->GetArrayLength (extraData);
219
230
context->extradata_size = size;
220
231
context->extradata =
221
- (uint8_t *) av_malloc (size + AV_INPUT_BUFFER_PADDING_SIZE);
232
+ (uint8_t *)av_malloc (size + AV_INPUT_BUFFER_PADDING_SIZE);
222
233
if (!context->extradata ) {
223
234
LOGE (" Failed to allocate extradata." );
224
235
releaseContext (context);
225
236
return NULL ;
226
237
}
227
- env->GetByteArrayRegion (extraData, 0 , size, (jbyte *) context->extradata );
238
+ env->GetByteArrayRegion (extraData, 0 , size, (jbyte *)context->extradata );
228
239
}
229
240
if (context->codec_id == AV_CODEC_ID_PCM_MULAW ||
230
241
context->codec_id == AV_CODEC_ID_PCM_ALAW) {
@@ -249,8 +260,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
249
260
result = avcodec_send_packet (context, packet);
250
261
if (result) {
251
262
logError (" avcodec_send_packet" , result);
252
- return result == AVERROR_INVALIDDATA ? DECODER_ERROR_INVALID_DATA
253
- : DECODER_ERROR_OTHER;
263
+ return transformError (result);
254
264
}
255
265
256
266
// Dequeue output data until it runs out.
@@ -259,7 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
259
269
AVFrame *frame = av_frame_alloc ();
260
270
if (!frame) {
261
271
LOGE (" Failed to allocate output frame." );
262
- return - 1 ;
272
+ return AUDIO_DECODER_ERROR_INVALID_DATA ;
263
273
}
264
274
result = avcodec_receive_frame (context, frame);
265
275
if (result) {
@@ -268,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
268
278
break ;
269
279
}
270
280
logError (" avcodec_receive_frame" , result);
271
- return result;
281
+ return transformError ( result) ;
272
282
}
273
283
274
284
// Resample output.
@@ -279,59 +289,63 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
279
289
int sampleCount = frame->nb_samples ;
280
290
int dataSize = av_samples_get_buffer_size (NULL , channelCount, sampleCount,
281
291
sampleFormat, 1 );
282
- AVAudioResampleContext *resampleContext;
292
+ SwrContext *resampleContext;
283
293
if (context->opaque ) {
284
- resampleContext = (AVAudioResampleContext *) context->opaque ;
294
+ resampleContext = (SwrContext *)context->opaque ;
285
295
} else {
286
- resampleContext = avresample_alloc_context ();
287
- av_opt_set_int (resampleContext, " in_channel_layout" , channelLayout, 0 );
296
+ resampleContext = swr_alloc ();
297
+ av_opt_set_int (resampleContext, " in_channel_layout" , channelLayout, 0 );
288
298
av_opt_set_int (resampleContext, " out_channel_layout" , channelLayout, 0 );
289
299
av_opt_set_int (resampleContext, " in_sample_rate" , sampleRate, 0 );
290
300
av_opt_set_int (resampleContext, " out_sample_rate" , sampleRate, 0 );
291
301
av_opt_set_int (resampleContext, " in_sample_fmt" , sampleFormat, 0 );
292
302
// The output format is always the requested format.
293
303
av_opt_set_int (resampleContext, " out_sample_fmt" ,
294
- context->request_sample_fmt , 0 );
295
- result = avresample_open (resampleContext);
304
+ context->request_sample_fmt , 0 );
305
+ result = swr_init (resampleContext);
296
306
if (result < 0 ) {
297
- logError (" avresample_open " , result);
307
+ logError (" swr_init " , result);
298
308
av_frame_free (&frame);
299
- return - 1 ;
309
+ return transformError (result) ;
300
310
}
301
311
context->opaque = resampleContext;
302
312
}
303
313
int inSampleSize = av_get_bytes_per_sample (sampleFormat);
304
314
int outSampleSize = av_get_bytes_per_sample (context->request_sample_fmt );
305
- int outSamples = avresample_get_out_samples (resampleContext, sampleCount);
315
+ int outSamples = swr_get_out_samples (resampleContext, sampleCount);
306
316
int bufferOutSize = outSampleSize * channelCount * outSamples;
307
317
if (outSize + bufferOutSize > outputSize) {
308
318
LOGE (" Output buffer size (%d) too small for output data (%d)." ,
309
319
outputSize, outSize + bufferOutSize);
310
320
av_frame_free (&frame);
311
- return - 1 ;
321
+ return AUDIO_DECODER_ERROR_INVALID_DATA ;
312
322
}
313
- result = avresample_convert (resampleContext, &outputBuffer, bufferOutSize,
314
- outSamples, frame->data , frame->linesize [0 ],
315
- sampleCount);
323
+ result = swr_convert (resampleContext, &outputBuffer, bufferOutSize,
324
+ (const uint8_t **)frame->data , frame->nb_samples );
316
325
av_frame_free (&frame);
317
326
if (result < 0 ) {
318
- logError (" avresample_convert " , result);
319
- return result ;
327
+ logError (" swr_convert " , result);
328
+ return AUDIO_DECODER_ERROR_INVALID_DATA ;
320
329
}
321
- int available = avresample_available (resampleContext);
330
+ int available = swr_get_out_samples (resampleContext, 0 );
322
331
if (available != 0 ) {
323
332
LOGE (" Expected no samples remaining after resampling, but found %d." ,
324
333
available);
325
- return - 1 ;
334
+ return AUDIO_DECODER_ERROR_INVALID_DATA ;
326
335
}
327
336
outputBuffer += bufferOutSize;
328
337
outSize += bufferOutSize;
329
338
}
330
339
return outSize;
331
340
}
332
341
342
+ int transformError (int errorNumber) {
343
+ return errorNumber == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA
344
+ : AUDIO_DECODER_ERROR_OTHER;
345
+ }
346
+
333
347
void logError (const char *functionName, int errorNumber) {
334
- char *buffer = (char *) malloc (ERROR_STRING_BUFFER_LENGTH * sizeof (char ));
348
+ char *buffer = (char *)malloc (ERROR_STRING_BUFFER_LENGTH * sizeof (char ));
335
349
av_strerror (errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
336
350
LOGE (" Error in %s: %s" , functionName, buffer);
337
351
free (buffer);
@@ -341,11 +355,10 @@ void releaseContext(AVCodecContext *context) {
341
355
if (!context) {
342
356
return ;
343
357
}
344
- AVAudioResampleContext *resampleContext ;
345
- if ((resampleContext = (AVAudioResampleContext *) context->opaque )) {
346
- avresample_free (&resampleContext );
358
+ SwrContext *swrContext ;
359
+ if ((swrContext = (SwrContext *)context->opaque )) {
360
+ swr_free (&swrContext );
347
361
context->opaque = NULL ;
348
362
}
349
363
avcodec_free_context (&context);
350
364
}
351
-
0 commit comments