24 #include "com_tagtraum_ffsampledsp_FFCodecInputStream.h" 29 static jmethodID getEncoding_MID = NULL;
30 static jmethodID getSampleRate_MID = NULL;
31 static jmethodID getFrameSize_MID = NULL;
32 static jmethodID getSampleSizeInBits_MID = NULL;
33 static jmethodID getChannels_MID = NULL;
34 static jmethodID isBigEndian_MID = NULL;
35 static jmethodID toString_MID = NULL;
42 static void init_ids(JNIEnv *env) {
43 if (getSampleRate_MID == NULL) {
44 jclass audioFormat_class = NULL;
45 jclass encoding_class = NULL;
47 audioFormat_class = (*env)->FindClass(env,
"javax/sound/sampled/AudioFormat");
48 encoding_class = (*env)->FindClass(env,
"javax/sound/sampled/AudioFormat$Encoding");
50 getEncoding_MID = (*env)->GetMethodID(env, audioFormat_class,
"getEncoding",
"()Ljavax/sound/sampled/AudioFormat$Encoding;");
51 getSampleRate_MID = (*env)->GetMethodID(env, audioFormat_class,
"getSampleRate",
"()F");
52 getFrameSize_MID = (*env)->GetMethodID(env, audioFormat_class,
"getFrameSize",
"()I");
53 getSampleSizeInBits_MID = (*env)->GetMethodID(env, audioFormat_class,
"getSampleSizeInBits",
"()I");
54 getChannels_MID = (*env)->GetMethodID(env, audioFormat_class,
"getChannels",
"()I");
55 isBigEndian_MID = (*env)->GetMethodID(env, audioFormat_class,
"isBigEndian",
"()Z");
56 toString_MID = (*env)->GetMethodID(env, encoding_class,
"toString",
"()Ljava/lang/String;");
72 enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_NONE;
73 int out_channel_layout = AV_CH_LAYOUT_STEREO;
76 AVCodec *encoder = NULL;
77 int dither_method = SWR_DITHER_NONE;
78 int output_sample_bits = 0;
84 jfloat sample_rate = (*env)->CallFloatMethod(env, target_format, getSampleRate_MID);
85 jint sample_size_in_bits = (*env)->CallIntMethod(env, target_format, getSampleSizeInBits_MID);
86 jint channels = (*env)->CallIntMethod(env, target_format, getChannels_MID);
87 jboolean big_endian = (*env)->CallBooleanMethod(env, target_format, isBigEndian_MID);
88 jobject encoding = (*env)->CallObjectMethod(env, target_format, getEncoding_MID);
89 jstring jencoding_name = (jstring)(*env)->CallObjectMethod(env, encoding, toString_MID);
91 const char *encoding_name = (*env)->GetStringUTFChars(env, jencoding_name, NULL);
92 is_float = strcmp(
"PCM_FLOAT", encoding_name) == 0;
93 is_signed = strcmp(
"PCM_SIGNED", encoding_name) == 0;
94 (*env)->ReleaseStringUTFChars(env, jencoding_name, encoding_name);
97 fprintf(stderr,
"encoding = %s\n", encoding_name);
98 fprintf(stderr,
"signed = %d\n", is_signed);
99 fprintf(stderr,
"float = %d\n", is_float);
100 fprintf(stderr,
"bits = %d\n", (
int)sample_size_in_bits);
103 if (sample_size_in_bits <= 8) {
104 out_sample_fmt = AV_SAMPLE_FMT_U8;
105 }
else if (sample_size_in_bits <=16) {
106 out_sample_fmt = AV_SAMPLE_FMT_S16;
107 }
else if (sample_size_in_bits <= 32 && is_float) {
108 out_sample_fmt = AV_SAMPLE_FMT_FLT;
109 }
else if (sample_size_in_bits <=32) {
110 out_sample_fmt = AV_SAMPLE_FMT_S32;
111 }
else if (sample_size_in_bits <= 64 && is_float) {
112 out_sample_fmt = AV_SAMPLE_FMT_DBL;
114 fprintf(stderr,
"Will use 64 bit PCM_FLOAT even though it might not have been desired.\n");
115 out_sample_fmt = AV_SAMPLE_FMT_DBL;
118 if (aio->
stream->codecpar->channels == channels) {
119 out_channel_layout = aio->
stream->codecpar->channel_layout;
120 }
else if (channels == 1) {
121 out_channel_layout = AV_CH_LAYOUT_MONO;
122 }
else if (channels == 2) {
123 out_channel_layout = AV_CH_LAYOUT_STEREO;
125 fprintf(stderr,
"Undetermined channel layout, will use stereo.\n");
129 if (aio->
stream->codecpar->bits_per_coded_sample > sample_size_in_bits) {
130 dither_method = SWR_DITHER_TRIANGULAR;
131 output_sample_bits = sample_size_in_bits;
135 fprintf(stderr,
"setting out format to: %d\n", out_sample_fmt);
145 res = AVERROR(ENOMEM);
151 av_opt_set_sample_fmt(aio->
swr_context,
"in_sample_fmt", aio->
stream->codecpar->format, 0);
152 av_opt_set_int(aio->
swr_context,
"in_channel_count", aio->
stream->codecpar->channels, 0);
153 av_opt_set_int(aio->
swr_context,
"in_channel_layout", aio->
stream->codecpar->channel_layout, 0);
154 av_opt_set_int(aio->
swr_context,
"in_sample_rate", aio->
stream->codecpar->sample_rate, 0);
156 av_opt_set_int(aio->
swr_context,
"out_channel_layout", out_channel_layout, 0);
157 av_opt_set_int(aio->
swr_context,
"out_channel_count", channels, 0);
158 av_opt_set_int(aio->
swr_context,
"out_sample_rate", (
int)round(sample_rate), 0);
159 av_opt_set_sample_fmt(aio->
swr_context,
"out_sample_fmt", out_sample_fmt, 0);
160 av_opt_set_int(aio->
swr_context,
"dither_method", dither_method, 0);
161 av_opt_set_int(aio->
swr_context,
"output_sample_bits", output_sample_bits, 0);
165 res = AVERROR(ENOMEM);
171 fprintf(stderr,
"open codec: dither method : %d\n", dither_method);
175 encoder =
ff_find_encoder(out_sample_fmt, sample_size_in_bits, big_endian, is_signed);
177 res = AVERROR(EINVAL);
188 return (jlong)(intptr_t)aio;
void throwIOExceptionIfError(JNIEnv *env, int err, const char *message)
Throws an IOException.
AVStream * stream
Audio stream we are interested in.
int ff_init_encoder(JNIEnv *env, FFAudioIO *aio, AVCodec *encoder)
Allocates and initializes the encoder context and frame in FFAudioIO.
SwrContext * swr_context
Resampling context.
AVCodec * ff_find_encoder(enum AVSampleFormat sampleFormat, int bits, int big_endian, int signedSamples)
Finds an AVCodec encoder for the given sample format, bits per sample, byte order and signed/unsigned...
Central context representing the native peer to the Java FFNativePeerInputStream object.