### ff_init_audioio Function Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Initializes audio IO, including SWR, encoder setup for 24-bit samples, and buffer allocation. ```c int ff_init_audioio(JNIEnv *env, FFAudioIO *aio) { int res = 0; int nb_planes; AVCodec *codec = NULL; aio->timestamp = 0; // allocate pointer to the audio buffers, i.e. the multiple planes/channels. nb_planes = av_sample_fmt_is_planar(aio->stream->codecpar->format) ? aio->stream->codecpar->channels : 1; // always init SWR to keep code simpler res = init_swr(env, aio); if (res < 0) { // exception is already thrown goto bail; } // if for some reason the codec delivers 24bit, we need to encode its output to little endian if (aio->stream->codecpar->bits_per_coded_sample == 24) { codec = ff_find_encoder(aio->stream->codecpar->format, aio->stream->codecpar->bits_per_coded_sample, ff_big_endian(aio->stream->codecpar->codec_id), 1); if (!codec) { res = AVERROR(EINVAL); throwIOExceptionIfError(env, res, "Could not find suitable encoder codec."); goto bail; } res = ff_init_encoder(env, aio, codec); if (res<0) { throwIOExceptionIfError(env, res, "Could not initialize encoder codec."); goto bail; } } // allocate the buffer the codec decodes to aio->audio_data = av_mallocz(sizeof(uint8_t *) * nb_planes); if (!aio->audio_data) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate audio data buffers."); goto bail; } aio->decode_frame = av_frame_alloc(); if (!aio->decode_frame) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate frame."); goto bail; } // initialize packet av_init_packet(&(aio->decode_packet)); aio->decode_packet.data = NULL; aio->decode_packet.size = 0; bail: return res; } ``` -------------------------------- ### ff_init_audioio Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Initializes the main context FFAudioIO, so that SwrContext, decode buffers and the encoder are set to reasonable values. ```APIDOC ## ff_init_audioio ### Description Initializes the main context FFAudioIO, so that SwrContext, decode buffers and the encoder are set to reasonable values. ### Signature int ff_init_audioio(JNIEnv *, FFAudioIO *) ### Parameters - **JNIEnv*** - JNI environment pointer. - **FFAudioIO*** - Pointer to the FFAudioIO context to initialize. ### Returns int - 0 on success, negative error code on failure. ``` -------------------------------- ### read(byte[] b, int off, int len) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFNativePeerInputStream.html Reads up to len bytes of audio data into a byte array starting at offset off. This method overrides InputStream.read and throws IOException on error. ```APIDOC ## read(byte[] b, int off, int len) ### Description Reads up to len bytes of audio data into the given byte array starting at the specified offset. ### Method read ### Signature `public int read(byte[] b, int off, int len) throws IOException` ### Parameters - **b** (byte[]) - The buffer into which the data is read. - **off** (int) - The start offset in the array b at which the data is written. - **len** (int) - The maximum number of bytes to read. ### Returns - **int** - The total number of bytes read, or -1 if the end of the stream is reached. ### Throws - **IOException** - If an I/O error occurs. ``` -------------------------------- ### ff_init_audioio Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Initializes the main FFAudioIO context, setting up SwrContext, decode buffers, and encoder to reasonable values. Returns a negative value if something goes wrong. ```APIDOC ## ff_init_audioio ### Description Initializes the main FFAudioIO context, setting up SwrContext, decode buffers, and encoder to reasonable values. ### Function Signature int ff_init_audioio(JNIEnv *env, FFAudioIO *aio) ### Parameters - **env** (JNIEnv*) - Required - JNI environment - **aio** (FFAudioIO*) - Required - Our context, FFAudioIO ### Returns - A negative value if something went wrong. ``` -------------------------------- ### FFAudioFileFormat(String url, int codecId, float sampleRate, int sampleSize, int channels, int frameSize, float frameRate, int frameLength, boolean bigEndian, long durationInMicroSeconds, int bitRate, Boolean vbr, boolean encrypted) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFAudioFileFormat.html Creates a new FFAudioFileFormat instance. This constructor is called from native code in FFAudioFileReader.c and throws UnsupportedAudioFileException if the URL extension is not recognized. ```APIDOC ## Constructor: FFAudioFileFormat ### Description Creates a new FFAudioFileFormat instance. This constructor is called from native code in FFAudioFileReader.c. ### Signature public FFAudioFileFormat(String url, int codecId, float sampleRate, int sampleSize, int channels, int frameSize, float frameRate, int frameLength, boolean bigEndian, long durationInMicroSeconds, int bitRate, Boolean vbr, boolean encrypted) throws UnsupportedAudioFileException ### Parameters - **url** (String) - Required - URL string of the audio source, or null - **codecId** (int) - Required - FFmpeg AVCodecID value - **sampleRate** (float) - Required - Sample rate in Hz - **sampleSize** (int) - Required - Bits per sample, or AudioSystem.NOT_SPECIFIED - **channels** (int) - Required - Channel count, or AudioSystem.NOT_SPECIFIED - **frameSize** (int) - Required - Frame size in bytes, or AudioSystem.NOT_SPECIFIED - **frameRate** (float) - Required - Frame rate in frames per second, or AudioSystem.NOT_SPECIFIED - **frameLength** (int) - Required - Total frame count, or AudioSystem.NOT_SPECIFIED - **bigEndian** (boolean) - Required - true if samples are big-endian - **durationInMicroSeconds** (long) - Required - Duration in microseconds, or 0 if unknown - **bitRate** (int) - Required - Bit rate in bits per second, or 0 if unknown - **vbr** (Boolean) - Required - true if variable bit rate, false if CBR, or null if unknown - **encrypted** (boolean) - Required - true if the stream is DRM-protected ### Throws - **UnsupportedAudioFileException** - if the URL extension is not recognised ``` -------------------------------- ### Initialize AVIOContext and Open Stream Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_stream_input_stream_8c_source.html Allocates a callback buffer and custom AVIOContext for reading audio data, then initializes the audio IO context and opens the stream. ```c callback_buffer = (unsigned char*)av_malloc(CALLBACK_BUFFERSIZE * sizeof(uint8_t)); if (!callback_buffer) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate callback buffer."); goto bail; } io_context = avio_alloc_context( callback_buffer, // IOBuffer CALLBACK_BUFFERSIZE, // Buffer Size (32kb corresponds to Java code) 0, // Write flag, only reading, so 0 aio, // FFAudioIO pointer (opaque) read_callback, // Read callback NULL, // Write callback NULL // Seek callback ); if (!io_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate custom IO context."); goto bail; } // we didn't supply a seek function in avio_alloc_context, // so we need to make sure we don't seek... io_context->seekable = 0; aio->format_context->pb = io_context; aio->stream_index = (int)streamIndex; res = ff_open_file(env, &aio->format_context, &aio->stream, &aio->decode_context, &aio->stream_index, "MemoryAVIOContext"); if (res) { // exception is already thrown goto bail; } res = ff_init_audioio(env, aio); if (res) { // exception is already thrown goto bail; } #ifdef DEBUG fprintf(stderr, "stream->codecpar->bits_per_coded_sample: %i\n", aio->stream->codecpar->bits_per_coded_sample); fprintf(stderr, "stream->codecpar->bits_per_raw_sample : %i\n", aio->stream->codecpar->bits_per_raw_sample); fprintf(stderr, "stream->codecpar->bit_rate : %lli\n", aio->stream->codecpar->bit_rate); fprintf(stderr, "frames : %\" PRId64 \"\n", aio->stream->nb_frames); fprintf(stderr, "sample_rate: %i\n", aio->stream->codecpar->sample_rate); fprintf(stderr, "channels : %i\n", aio->stream->codecpar->channels); fprintf(stderr, "frame_size : %i\n", aio->stream->codecpar->frame_size); fprintf(stderr, "codec_id : %i\n", aio->stream->codecpar->codec_id); #endif bail: if (res) ff_audioio_free(aio); return (jlong)(intptr_t)aio; } ``` -------------------------------- ### Java_com_tagtraum_ffsampledsp_FFCodecInputStream_open implementation Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_codec_input_stream_8c_source.html Re-configures SwrContext and Encoder to match the provided target_format. Determines output sample format and channel layout based on sample size, float flag, and channel count. Sets up swr options, initializes the context, and re-adjusts the encoder. Includes error handling with throwIOExceptionIfError. ```c 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; 113 } else { 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; 116 } 117 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; 124 } else { 125 fprintf(stderr, "Undetermined channel layout, will use stereo.\n"); 126 channels = 2; 127 } 128 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; 132 } 133 134 #ifdef DEBUG 135 fprintf(stderr, "setting out format to: %d\n", out_sample_fmt); 136 #endif 137 138 // remove default setup 139 if (aio->swr_context) { 140 swr_free(&aio->swr_context); 141 } 142 // allocate new 143 aio->swr_context = swr_alloc(); 144 if (!aio->swr_context) { 145 res = AVERROR(ENOMEM); 146 throwIOExceptionIfError(env, res, "Could not allocate swr context."); 147 goto bail; 148 } 149 150 // standard stuff from input 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); 155 // custom stuff 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); 162 163 res = swr_init(aio->swr_context); 164 if (res < 0) { 165 res = AVERROR(ENOMEM); 166 throwIOExceptionIfError(env, res, "Could not re-initialize swr context."); 167 goto bail; 168 } 169 170 #ifdef DEBUG 171 fprintf(stderr, "open codec: dither method : %d\n", dither_method); 172 #endif 173 174 // re-adjust encoder 175 encoder = ff_find_encoder(out_sample_fmt, sample_size_in_bits, big_endian, is_signed); 176 if (!encoder) { 177 res = AVERROR(EINVAL); 178 throwIOExceptionIfError(env, res, "Could not find suitable encoder."); 179 goto bail; 180 } 181 res = ff_init_encoder(env, aio, encoder); 182 if (res < 0) { 183 goto bail; 184 } 185 186 bail: 187 188 return (jlong)(intptr_t)aio; 189 } ``` -------------------------------- ### Java_com_tagtraum_ffsampledsp_FFAudioFileReader_getAudioFileFormatsFromURL Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_audio_file_reader_8c_source.html Opens an audio file from a URL and retrieves its audio file formats. It initializes the environment, opens the format context, and cleans up resources upon completion. ```c JNIEXPORT jobjectArray JNICALL Java_com_tagtraum_ffsampledsp_FFAudioFileReader_getAudioFileFormatsFromURL(JNIEnv *env, jobject instance, jstring url) { #ifdef DEBUG fprintf(stderr, "openFromUrl_1\n"); #endif int res = 0; AVFormatContext *format_context = NULL; jobjectArray array = NULL; //AVStream *stream = NULL; //int stream_index = 0; init_ids(env); const char *input_url = (*env)->GetStringUTFChars(env, url, NULL); res = ff_open_format_context(env, &format_context, input_url); if (res) { goto bail; } res = create_ffaudiofileformats(env, format_context, &array, url); if (res) { goto bail; } bail: if (format_context) { avformat_close_input(&format_context); } (*env)->ReleaseStringUTFChars(env, url, input_url); return array; } ``` -------------------------------- ### ff_init_encoder Function Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Initializes the audio encoder context, allocates frames, and configures codec parameters based on the SwrContext. ```c int ff_init_encoder(JNIEnv *env, FFAudioIO *aio, AVCodec *encoder) { int res = 0; int64_t out_sample_rate; int64_t out_channel_count; int64_t out_channel_layout; enum AVSampleFormat out_sample_fmt; // make sure we clean up before resetting this // in case this is called twice if (aio->encode_frame) { av_frame_free(&aio->encode_frame); } if (aio->encode_context) { avcodec_close(aio->encode_context); av_free(aio->encode_context); } aio->encode_context = avcodec_alloc_context3(encoder); if (!aio->encode_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate codec context."); goto bail; } // init to whatever we have in SwrContext av_opt_get_int(aio->swr_context, "out_channel_count", 0, &out_channel_count); av_opt_get_int(aio->swr_context, "out_channel_layout", 0, &out_channel_layout); av_opt_get_int(aio->swr_context, "out_sample_rate", 0, &out_sample_rate); av_opt_get_sample_fmt(aio->swr_context, "out_sample_fmt", 0, &out_sample_fmt); aio->encode_context->sample_fmt = out_sample_fmt; aio->encode_context->sample_rate = out_sample_rate; aio->encode_context->channel_layout = out_channel_layout; aio->encode_context->channels = out_channel_count; res = avcodec_open2(aio->encode_context, encoder, NULL); if (res < 0) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not open encoder."); goto bail; } aio->encode_frame = av_frame_alloc(); if (!aio->encode_frame) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate encoder frame."); goto bail; } aio->encode_frame->nb_samples = aio->encode_context->frame_size; // this will be changed later!! aio->encode_frame->format = aio->encode_context->sample_fmt; aio->encode_frame->channel_layout = aio->encode_context->channel_layout; bail: return res; } ``` -------------------------------- ### loadLibrary(String, Class) Source: https://www.tagtraum.com/ffsampledsp/apidocs/index-all.html Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader. Loads a library. ```APIDOC ## loadLibrary(String, Class) ### Description Loads a library. ### Method Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader ### Parameters - **String** - The name of the library to load. - **Class** - The class to use for loading the library. ### Returns Void. ``` -------------------------------- ### ff_open_file Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Opens the input file/url, allocates an AVFormatContext for it and opens the audio stream with an appropriate decoder. ```APIDOC ## ff_open_file ### Description Opens the input file/url, allocates an AVFormatContext for it and opens the audio stream with an appropriate decoder. ### Signature int ff_open_file(JNIEnv *, AVFormatContext **, AVStream **, AVCodecContext **, int *, const char *) ### Parameters - **JNIEnv*** - JNI environment pointer. - **AVFormatContext*** - Output pointer to the allocated AVFormatContext. - **AVStream*** - Output pointer to the selected audio stream. - **AVCodecContext*** - Output pointer to the allocated AVCodecContext. - **int*** - Output pointer to the stream index. - **const char*** - Input file/url path. ### Returns int - 0 on success, negative error code on failure. ``` -------------------------------- ### JNI_OnLoad() Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c.html Make sure FFmpeg is initialized all the way. ```APIDOC ## JNI_OnLoad() ### Description Make sure FFmpeg is initialized all the way. ### Function Signature JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) ### Parameters - **vm** (JavaVM*) - Required - JavaVM pointer. - **reserved** (void*) - Required - Reserved parameter. ### Returns - JNI version constant. ``` -------------------------------- ### FFCodecInputStream_open: JNI open with sample format selection Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_codec_input_stream_8c_source.html JNI entry point for FFCodecInputStream.open(). Reads target AudioFormat properties, determines signed/float encoding, and selects an AVSampleFormat based on sample size. The snippet is truncated at the source boundary. ```c JNIEXPORT jlong JNICALL Java_com_tagtraum_ffsampledsp_FFCodecInputStream_open(JNIEnv *env, jobject object, jobject target_format, jlong aio_pointer) { int res = 0; enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_NONE; int out_channel_layout = AV_CH_LAYOUT_STEREO; int is_float = 0; int is_signed = 0; AVCodec *encoder = NULL; int dither_method = SWR_DITHER_NONE; int output_sample_bits = 0; init_ids(env); FFAudioIO *aio = (FFAudioIO*)(intptr_t)aio_pointer; jfloat sample_rate = (*env)->CallFloatMethod(env, target_format, getSampleRate_MID); jint sample_size_in_bits = (*env)->CallIntMethod(env, target_format, getSampleSizeInBits_MID); jint channels = (*env)->CallIntMethod(env, target_format, getChannels_MID); jboolean big_endian = (*env)->CallBooleanMethod(env, target_format, isBigEndian_MID); jobject encoding = (*env)->CallObjectMethod(env, target_format, getEncoding_MID); jstring jencoding_name = (jstring)(*env)->CallObjectMethod(env, encoding, toString_MID); const char *encoding_name = (*env)->GetStringUTFChars(env, jencoding_name, NULL); is_float = strcmp("PCM_FLOAT", encoding_name) == 0; is_signed = strcmp("PCM_SIGNED", encoding_name) == 0; (*env)->ReleaseStringUTFChars(env, jencoding_name, encoding_name); #ifdef DEBUG fprintf(stderr, "encoding = %s\n", encoding_name); fprintf(stderr, "signed = %d\n", is_signed); fprintf(stderr, "float = %d\n", is_float); fprintf(stderr, "bits = %d\n", (int)sample_size_in_bits); #endif if (sample_size_in_bits <= 8) { out_sample_fmt = AV_SAMPLE_FMT_U8; } else if (sample_size_in_bits <=16) { out_sample_fmt = AV_SAMPLE_FMT_S16; } else if (sample_size_in_bits <= 32 && is_float) { out_sample_fmt = AV_SAMPLE_FMT_FLT; } else if (sample_size_in_bits <=32) { ``` -------------------------------- ### loadLibrary() Source: https://www.tagtraum.com/ffsampledsp/apidocs/index-all.html Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader. Loads the FFSampledSP library. ```APIDOC ## loadLibrary() ### Description Loads the FFSampledSP library. ### Method Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader ### Parameters None. ### Returns Void. ``` -------------------------------- ### FFAudioFileReader() Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFAudioFileReader.html Creates a new FFAudioFileReader instance. ```APIDOC ## Constructor: FFAudioFileReader() ### Description Creates a new `FFAudioFileReader`. ### Method Constructor ### Signature `public FFAudioFileReader()` ``` -------------------------------- ### loadLibrary() Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFNativeLibraryLoader.html Loads the FFSampledSP library and returns a boolean indicating success. ```APIDOC ## loadLibrary() ### Description Loads the FFSampledSP library. ### Method loadLibrary ### Signature `public static boolean loadLibrary()` ### Returns - `boolean` - true, if loading was successful ``` -------------------------------- ### ff_open_format_context Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Opens the input file/url and allocates an AVFormatContext for it, but does not open the audio stream with an appropriate decoder. ```APIDOC ## ff_open_format_context ### Description Opens the input file/url and allocates an AVFormatContext for it, but does not open the audio stream with an appropriate decoder. ### Signature int ff_open_format_context(JNIEnv *, AVFormatContext **, const char *) ### Parameters - **JNIEnv*** - JNI environment pointer. - **AVFormatContext*** - Output pointer to the allocated AVFormatContext. - **const char*** - Input file/url path. ### Returns int - 0 on success, negative error code on failure. ``` -------------------------------- ### ff_open_file Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Opens the input file/url, allocates an AVFormatContext, and opens the audio stream with an appropriate decoder. Returns a negative value if something goes wrong. ```APIDOC ## ff_open_file ### Description Opens the input file/url, allocates an AVFormatContext, and opens the audio stream with an appropriate decoder. ### Function Signature int ff_open_file(JNIEnv *env, AVFormatContext **format_context, AVStream **openedStream, AVCodecContext **context, int *stream_index, const char *url) ### Parameters - **env** (JNIEnv*) - Required - JNI environment - **format_context** (AVFormatContext**) - Required - AVFormatContext - **openedStream** (AVStream**) - Required - Opened audio AVStream - **stream_index** (int*) - Required - Index of the desired audio stream (in) and index of the selected stream (out) - **url** (const char*) - Required - URL to open ### Returns - A negative value if something went wrong. ``` -------------------------------- ### PROVIDER (static final String) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFAudioFormat.html Property key to mark where this AudioFormat came from. ```APIDOC ## PROVIDER (static final String) ### Description Property key to mark where this `AudioFormat` came from. ### Field `public static final String PROVIDER` ### See Also - `FFSAMPLEDSP` ``` -------------------------------- ### loadLibrary(String) Source: https://www.tagtraum.com/ffsampledsp/apidocs/index-all.html Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader. Loads a library. ```APIDOC ## loadLibrary(String) ### Description Loads a library. ### Method Static method in class com.tagtraum.ffsampledsp.FFNativeLibraryLoader ### Parameters - **String** - The name of the library to load. ### Returns Void. ``` -------------------------------- ### Initialize Stream Decoder Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Finds the best stream and initializes the codec context for decoding. ```c enum AVMediaType type) { int res = 0; AVStream *stream; AVCodec *decoder = NULL; res = av_find_best_stream(format_context, type, -1, -1, NULL, 0); if (res < 0) { goto bail; } *stream_index = res; stream = format_context->streams[*stream_index]; // find decoder for the stream decoder = avcodec_find_decoder(stream->codecpar->codec_id); if (!decoder) { goto bail; } context = avcodec_alloc_context3(decoder); if (!context) { goto bail; } res = avcodec_open2(context, decoder, NULL); if (res < 0) { goto bail; } return res; bail: return res; } ``` -------------------------------- ### FFURLInputStream(URL url) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFURLInputStream.html Opens the first audio stream from the given URL using the default I/O buffer size. ```APIDOC ## Constructor: FFURLInputStream(URL url) ### Description Opens the first audio stream from the given URL using the default I/O buffer size. ### Parameters - **url** (URL) - Required - The URL of the audio resource. ``` -------------------------------- ### Java_com_tagtraum_ffsampledsp_FFURLInputStream_open Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_u_r_l_input_stream_8c.html Opens a file or URL and creates a corresponding FFAudioIO object. Returns a pointer to the new FFAudioIO. ```APIDOC ## Java_com_tagtraum_ffsampledsp_FFURLInputStream_open ### Description Opens a file or URL and creates a corresponding FFAudioIO object. ### Method JNI function ### Signature JNIEXPORT jlong JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_open(JNIEnv *env, jobject stream, jstring url, jint streamIndex) ### Parameters - **env** (JNIEnv*) - Required - JNI environment - **stream** (jobject) - Required - Calling FFURLInputStream instance - **url** (jstring) - Required - URL of the file/stream to open - **streamIndex** (jint) - Required - Index of the stream to open ### Returns - **jlong** - Pointer to new FFAudioIO ``` -------------------------------- ### JNI initialization and read callback in FFAudioFileReader.c Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_audio_file_reader_8c_source.html Initializes JNI method IDs for java.nio.Buffer.limit() and the FFAudioFileFormat constructor, then defines a read callback that copies data from a direct byte buffer to a C buffer. The callback is limited to a single call per invocation. ```c static void init_ids(JNIEnv *env) { #ifdef DEBUG fprintf(stderr, "FFAudioFileReader.c init_ids(env)\n"); #endif if (!limit_MID) { jclass bufferClass = NULL; jclass ffAudioFileFormat_class = NULL; bufferClass = (*env)->FindClass(env, "java/nio/Buffer"); ffAudioFileFormat_class = (*env)->FindClass(env, "com/tagtraum/ffsampledsp/FFAudioFileFormat"); #ifdef DEBUG if (!bufferClass) fprintf(stderr, "Failed to find java/nio/Buffer\n"); if (!ffAudioFileFormat_class) fprintf(stderr, "Failed to find com/tagtraum/ffsampledsp/FFAudioFileFormat\n"); #endif limit_MID = (*env)->GetMethodID(env, bufferClass, "limit", "()I"); ffAudioFileFormat_MID = (*env)->GetMethodID(env, ffAudioFileFormat_class, "", "(Ljava/lang/String;IFIIIFZJILjava/lang/Boolean;)V"); #ifdef DEBUG if (!limit_MID) fprintf(stderr, "Failed to find limit method\n"); if (!ffAudioFileFormat_MID) fprintf(stderr, "Failed to find constructor of AudioFileFormat\n"); #endif } } ``` ```c static int read_callback(void *opaque, uint8_t *buf, int size) { int res = 0; int availableData; uint8_t *java_buffer = NULL; FFCallback *callback = (FFCallback *)opaque; if (callback->call_count > 0) goto bail; callback->call_count = 1; java_buffer = (uint8_t *)(*callback->env)->GetDirectBufferAddress(callback->env, callback->byte_buffer); if (!java_buffer) { res = -1; throwIOExceptionIfError(callback->env, 1, "Failed to get address for byte buffer"); goto bail; } // get available data, i.e. the limit of the java buffer availableData = (*callback->env)->CallIntMethod(callback->env, callback->byte_buffer, limit_MID); // copy to c buf memcpy(buf, (const uint8_t *)java_buffer, availableData); res = availableData; bail: return res; } ``` -------------------------------- ### Browse Source Repository Source: https://www.tagtraum.com/ffsampledsp/ffsampledsp-java/scm.html A link to the browsable version of the source repository on GitHub. ```text https://github.com/hendriks73/ffsampledsp/tree/main ``` -------------------------------- ### Open Audio Stream with FFmpeg (ff_open_stream) Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Opens an audio stream using FFmpeg's decoding API. Finds the decoder, allocates context, copies codec parameters, and opens the codec. On error, throws an UnsupportedAudioFileException via JNI and returns an error code. ```c int ff_open_stream(JNIEnv *env, AVStream *stream, AVCodecContext **context) { #ifdef DEBUG fprintf(stderr, "Opening stream...\n"); #endif int res = 0; AVCodec *decoder = NULL; AVDictionary *opts = NULL; int refcount = 0; // is this correct? decoder = avcodec_find_decoder(stream->codecpar->codec_id); if (!decoder) { fprintf(stderr, "Failed to find %s codec\n", av_get_media_type_string(AVMEDIA_TYPE_AUDIO)); res = AVERROR(EINVAL); throwUnsupportedAudioFileExceptionIfError(env, res, "Failed to find codec."); goto bail; } *context = avcodec_alloc_context3(decoder); if (!context) { fprintf(stderr, "Failed to allocate context\n"); res = AVERROR(EINVAL); throwUnsupportedAudioFileExceptionIfError(env, res, "Failed to allocate codec context."); goto bail; } /* Copy codec parameters from input stream to output codec context */ if ((res = avcodec_parameters_to_context(*context, stream->codecpar)) < 0) { fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n", av_get_media_type_string(AVMEDIA_TYPE_AUDIO)); throwUnsupportedAudioFileExceptionIfError(env, res, "Failed to copy codec parameters."); goto bail; } /* Init the decoders, with or without reference counting */ av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0); if ((res = avcodec_open2(*context, decoder, &opts)) < 0) { fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(AVMEDIA_TYPE_AUDIO)); throwUnsupportedAudioFileExceptionIfError(env, res, "Failed to open codec."); goto bail; } #ifdef DEBUG fprintf(stderr, "Stream was opened.\n"); #endif return res; bail: return res; } ``` -------------------------------- ### Initialize JNI Environment Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html The JNI_OnLoad function initializes the FFmpeg network components when the library is loaded by the JVM. ```c JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { //av_register_all(); avformat_network_init(); //avcodec_register_all(); return JNI_VERSION_1_6; } ``` -------------------------------- ### Java_com_tagtraum_ffsampledsp_FFStreamInputStream_open Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_stream_input_stream_8c.html Creates the FFAudioIO, custom AVIOContext etc for reading data from the stream. ```APIDOC ## Java_com_tagtraum_ffsampledsp_FFStreamInputStream_open ### Description Creates the FFAudioIO, custom AVIOContext etc for reading data from the stream. ### Method JNIEXPORT jlong JNICALL ### Signature Java_com_tagtraum_ffsampledsp_FFStreamInputStream_open(JNIEnv *env, jobject stream, jint streamIndex) ### Parameters - **env** (JNIEnv*) - Required - JNIEnv - **stream** (jobject) - Required - calling FFStreamInputStream instance - **streamIndex** (jint) - Required - stream index ### Returns pointer to the created FFAudioIO ``` -------------------------------- ### FFAudioFormat(int codecId, float sampleRate, int sampleSize, int channels, int frameSize, float frameRate, boolean bigEndian, int bitRate, Boolean vbr, boolean encrypted) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFAudioFormat.html Creates a new FFAudioFormat from the given codec and format parameters. This constructor is intended to be called from FFAudioFileFormat. ```APIDOC ## FFAudioFormat(int codecId, float sampleRate, int sampleSize, int channels, int frameSize, float frameRate, boolean bigEndian, int bitRate, Boolean vbr, boolean encrypted) ### Description Creates a new `FFAudioFormat` from the given codec and format parameters. ### Constructor `public FFAudioFormat(int codecId, float sampleRate, int sampleSize, int channels, int frameSize, float frameRate, boolean bigEndian, int bitRate, Boolean vbr, boolean encrypted)` ### Parameters - **codecId** (int) - Required - FFmpeg `AVCodecID` value - **sampleRate** (float) - Required - Sample rate in Hz - **sampleSize** (int) - Required - Bits per sample, or `AudioSystem.NOT_SPECIFIED` - **channels** (int) - Required - Channel count, or `AudioSystem.NOT_SPECIFIED` - **frameSize** (int) - Required - Frame size in bytes, or `AudioSystem.NOT_SPECIFIED` - **frameRate** (float) - Required - Frame rate in frames per second, or `AudioSystem.NOT_SPECIFIED` - **bigEndian** (boolean) - Required - `true` if samples are big-endian - **bitRate** (int) - Required - Bit rate in bits per second, or 0 if unknown - **vbr** (Boolean) - Required - `true` if variable bit rate, `false` if CBR, or `null` if unknown - **encrypted** (boolean) - Required - `true` if the stream is DRM-protected ``` -------------------------------- ### open: JNI function to open stream and allocate context Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_stream_input_stream_8c_source.html JNI function to open the stream. Initializes JNI IDs, allocates FFAudioIO and format context, and sets probe size and max analyze duration. Throws IOException on allocation failures. ```c JNIEXPORT jlong JNICALL Java_com_tagtraum_ffsampledsp_FFStreamInputStream_open(JNIEnv *env, jobject stream, jint streamIndex) { int res = 0; FFAudioIO *aio; AVIOContext *io_context; unsigned char* callback_buffer = NULL; init_ids(env, stream); aio = calloc(1, sizeof(FFAudioIO)); if (!aio) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate audio IO."); goto bail; } aio->env = env; aio->java_instance = stream; aio->format_context = avformat_alloc_context(); if (!aio->format_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate format context."); goto bail; } // limit probe to less than what we read in one chunk... aio->format_context->probesize = 8*1024; aio->format_context->max_analyze_duration = 5*AV_TIME_BASE; ``` -------------------------------- ### ff_open_format_context() Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Opens an input file or URL and allocates an AVFormatContext for it, but does not open the audio stream with a decoder. Returns a negative value if something goes wrong. ```APIDOC ## ff_open_format_context() ### Description Opens the input file/url and allocates a AVFormatContext for it, but does not open the audio stream with an appropriate decoder. ### Function Signature int ff_open_format_context(JNIEnv *env, AVFormatContext **format_context, const char *url) ### Parameters - **env** (JNIEnv*) - Required - JNI environment pointer. - **format_context** (AVFormatContext**) - Required - Pointer to the AVFormatContext pointer to be allocated. - **url** (const char*) - Required - URL to open. ### Returns - Negative value if something went wrong. ``` -------------------------------- ### ff_init_encoder Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Allocates and initializes the encoder context and frame in FFAudioIO. ```APIDOC ## ff_init_encoder ### Description Allocates and initializes the encoder context and frame in FFAudioIO. ### Signature int ff_init_encoder(JNIEnv *, FFAudioIO *, AVCodec *) ### Parameters - **JNIEnv*** - JNI environment pointer. - **FFAudioIO*** - Pointer to the FFAudioIO context. - **AVCodec*** - Pointer to the encoder codec. ### Returns int - 0 on success, negative error code on failure. ``` -------------------------------- ### FFNativeLibraryLoader Source: https://www.tagtraum.com/ffsampledsp/apidocs/index-all.html Loads the native library, first via System.loadLibrary, then falls back to the class package or jar directory. ```APIDOC ## FFNativeLibraryLoader ### Description First tries to load a library the default way using `System.loadLibrary(String)`, upon failure falls back to the base directory of the given class package or the jar the class is in. ``` -------------------------------- ### ff_open_stream Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Opens the given audio stream and initializes the codec context for decoding. ```APIDOC ## ff_open_stream ### Description Opens the given stream, i.e. initializes the codec context for decoding. ### Function Signature int ff_open_stream(JNIEnv *env, AVStream *stream, AVCodecContext **context) ### Parameters - **env** (JNIEnv*) - Required - JNI environment. - **stream** (AVStream*) - Required - The audio stream to open. - **context** (AVCodecContext**) - Required - Pointer to the codec context to be initialized. ### Returns - **int** - 0 on success, or an error code on failure. ``` -------------------------------- ### FFEncoding(FFAudioFormat.FFEncoding.Codec codec) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/class-use/FFAudioFormat.FFEncoding.Codec.html Creates an FFAudioFormat.FFEncoding backed by the given FFAudioFormat.FFEncoding.Codec. This constructor can be called directly to instantiate an FFEncoding object. ```APIDOC ## FFEncoding(FFAudioFormat.FFEncoding.Codec codec) ### Description Creates an FFAudioFormat.FFEncoding backed by the given FFAudioFormat.FFEncoding.Codec. ### Constructor FFEncoding(FFAudioFormat.FFEncoding.Codec codec) ### Parameters - **codec** (FFAudioFormat.FFEncoding.Codec) - Required - The codec to back this FFEncoding instance. ``` -------------------------------- ### loadLibrary(String libName) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFNativeLibraryLoader.html Loads a library by its name. ```APIDOC ## loadLibrary(String libName) ### Description Loads a library by name. ### Method loadLibrary ### Signature `public static void loadLibrary(String libName)` ### Parameters - `libName` (String) - Required - name of the library, as described in `System.loadLibrary(String)` ``` -------------------------------- ### init_swr function Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8c_source.html Initializes the software resampler context for audio processing. It configures sample formats, channel layouts, and sample rates based on the provided stream parameters. ```c static int init_swr(JNIEnv *env, FFAudioIO *aio) { int res = 0; aio->swr_context = swr_alloc(); if (!aio->swr_context) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not allocate swr context."); goto bail; } av_opt_set_sample_fmt(aio->swr_context, "in_sample_fmt", aio->stream->codecpar->format, 0); // make sure we get interleaved/packed output av_opt_set_sample_fmt(aio->swr_context, "out_sample_fmt", av_get_packed_sample_fmt(aio->stream->codecpar->format), 0); // keep everything else the way it was... av_opt_set_int(aio->swr_context, "in_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "out_channel_count", aio->stream->codecpar->channels, 0); av_opt_set_int(aio->swr_context, "in_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "out_channel_layout", aio->stream->codecpar->channel_layout, 0); av_opt_set_int(aio->swr_context, "in_sample_rate", aio->stream->codecpar->sample_rate, 0); av_opt_set_int(aio->swr_context, "out_sample_rate", aio->stream->codecpar->sample_rate, 0); res = swr_init(aio->swr_context); if (res < 0) { res = AVERROR(ENOMEM); throwIOExceptionIfError(env, res, "Could not initialize swr context"); goto bail; } //fprintf(stderr, "init_swr: dither context: %d\n", aio->swr_context->dither); //fprintf(stderr, "init_swr: output sample bits: %d\n", aio->swr_context->dither.output_sample_bits); bail: return res; } ``` -------------------------------- ### Constructor: FFAudioInputStream(FFNativePeerInputStream, AudioFormat, long) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFAudioInputStream.html Creates a new FFAudioInputStream backed by the given native peer. The native peer reads and decodes audio data, the format specifies the decoded PCM audio format, and the frame length indicates the total number of frames or AudioSystem.NOT_SPECIFIED. ```APIDOC ## Constructor: FFAudioInputStream ### Description Creates a new `FFAudioInputStream` backed by the given native peer. ### Signature ```java public FFAudioInputStream(FFNativePeerInputStream nativePeerInputStream, AudioFormat format, long frameLength) ``` ### Parameters - **nativePeerInputStream** (FFNativePeerInputStream) - Required - Native peer that reads and decodes audio data. - **format** (AudioFormat) - Required - Audio format of the decoded PCM data. - **frameLength** (long) - Required - Total frame count, or `AudioSystem.NOT_SPECIFIED`. ### Usage Example ```java FFNativePeerInputStream peer = ...; AudioFormat format = ...; long frameLength = ...; FFAudioInputStream stream = new FFAudioInputStream(peer, format, frameLength); ``` ``` -------------------------------- ### ff_open_stream() Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Opens the given stream, i.e., sets up a decoder. Returns a negative value if something goes wrong. ```APIDOC ## ff_open_stream() ### Description Opens the given stream, i.e., sets up a decoder. ### Function Signature int ff_open_stream(JNIEnv *env, AVStream *stream, AVCodecContext **context) ### Parameters - **env** (JNIEnv*) - Required - JNI environment pointer. - **stream** (AVStream*) - Required - The stream to open. - **context** (AVCodecContext**) - Required - Pointer to the AVCodecContext pointer to be set up. ### Returns - Negative value if something went wrong. ``` -------------------------------- ### ff_init_encoder Source: https://www.tagtraum.com/ffsampledsp/doxygen/_f_f_utils_8h.html Allocates and initializes the encoder context and frame in FFAudioIO. The SwrContext must be set up first for this to succeed. Returns a negative value if something goes wrong. ```APIDOC ## ff_init_encoder ### Description Allocates and initializes the encoder context and frame in FFAudioIO. The SwrContext must be set up first for this to succeed. ### Function Signature int ff_init_encoder(JNIEnv *env, FFAudioIO *aio, AVCodec *encoder) ### Parameters - **env** (JNIEnv*) - Required - JNI environment - **aio** (FFAudioIO*) - Required - FFAudioIO (our context) - **encoder** (AVCodec*) - Required - AVCodec to use to setup the encoder AVCodecContext ### Returns - A negative value if something goes wrong. ``` -------------------------------- ### FFStreamInputStream(InputStream stream) Source: https://www.tagtraum.com/ffsampledsp/apidocs/com/tagtraum/ffsampledsp/FFStreamInputStream.html Opens the first audio stream from the given InputStream. Throws IOException if an I/O error occurs and UnsupportedAudioFileException if the stream format is not supported. ```APIDOC ## Constructor: FFStreamInputStream(InputStream stream) ### Description Opens the first audio stream from the given `InputStream`. ### Signature `public FFStreamInputStream(InputStream stream) throws IOException, UnsupportedAudioFileException` ### Parameters - **stream** (InputStream) - Required - Input stream to decode ### Throws - **IOException** - if an I/O error occurs - **UnsupportedAudioFileException** - if the stream format is not supported ``` -------------------------------- ### Access source repository via web browser Source: https://www.tagtraum.com/ffsampledsp/ffsampledsp-complete/scm.html Provides the URL to browse the source repository directly in a web browser. ```text https://github.com/hendriks73/ffsampledsp/tree/main/ffsampledsp-complete ```