FFSampledSP
Loading...
Searching...
No Matches
FFURLInputStream.c
Go to the documentation of this file.
1/*
2 * =================================================
3 * Copyright 2013 tagtraum industries incorporated
4 * This file is part of FFSampledSP.
5 *
6 * FFSampledSP is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFSampledSP is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFSampledSP; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * =================================================
20 *
21 * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
22 */
23
24#include "FFUtils.h"
26
34JNIEXPORT void JNICALL
36 JNIEnv *env, jobject stream, jlong aio_pointer) {
37
38 FFAudioIO *aio = (FFAudioIO *)(intptr_t)aio_pointer;
39 aio->env = env;
40 aio->java_instance = stream;
41
42 ff_fill_buffer(aio);
43 // we can ignore the return value,
44 // because all ff_fill_buffer already
45 // throws a suitable Java exception
46 // in the case of an error
47}
48
58 JNIEnv *env, jobject stream, jstring url, jbyteArray urlBytes,
59 jint streamIndex, jint fileBufferSize) {
60
61 int res = 0;
62 FFAudioIO *aio = NULL;
63 char *input_url = NULL;
64
65 {
66 jsize urlLen = (*env)->GetArrayLength(env, urlBytes);
67 jbyte *urlBuf = (*env)->GetByteArrayElements(env, urlBytes, NULL);
68 input_url = (char *)malloc(urlLen + 1);
69 if (!input_url) {
70 (*env)->ReleaseByteArrayElements(env, urlBytes, urlBuf, JNI_ABORT);
71 res = AVERROR(ENOMEM);
72 throwIOExceptionIfError(env, res, "Failed to allocate URL buffer");
73 goto bail;
74 }
75 memcpy(input_url, urlBuf, urlLen);
76 input_url[urlLen] = '\0';
77 (*env)->ReleaseByteArrayElements(env, urlBytes, urlBuf, JNI_ABORT);
78 }
79
80 aio = calloc(1, sizeof(FFAudioIO));
81 if (!aio) {
82 res = AVERROR(ENOMEM);
83 throwIOExceptionIfError(env, res, "Could not allocate audio io");
84 goto bail;
85 }
86 aio->stream_index = (int)streamIndex;
87
88 res = ff_open_file(env, &(aio->format_context), &(aio->stream),
89 &(aio->decode_context), &(aio->stream_index), input_url,
90 (int)fileBufferSize);
91 if (res) {
92 goto bail;
93 }
94 res = ff_init_audioio(env, aio);
95 if (res) {
96 goto bail;
97 }
98
99#ifdef DEBUG
100 fprintf(stderr, "stream->codecpar->bits_per_coded_sample: %i\n",
101 aio->stream->codecpar->bits_per_coded_sample);
102 fprintf(stderr, "stream->codecpar->bits_per_raw_sample : %i\n",
103 aio->stream->codecpar->bits_per_raw_sample);
104 fprintf(stderr, "stream->codecpar->bit_rate: %lli\n",
105 aio->stream->codecpar->bit_rate);
106 fprintf(stderr, "frames : %" PRId64 "\n", aio->stream->nb_frames);
107 fprintf(stderr, "sample_rate: %i\n", aio->stream->codecpar->sample_rate);
108 fprintf(stderr, "channels : %i\n",
109 aio->stream->codecpar->ch_layout.nb_channels);
110 fprintf(stderr, "frame_size : %i\n", aio->stream->codecpar->frame_size);
111 fprintf(stderr, "codec_id : %i\n", aio->stream->codecpar->codec_id);
112#endif
113
114bail:
115
116 if (res)
117 ff_audioio_free(aio);
118 free(input_url);
119
120 return (jlong)(intptr_t)aio;
121}
122
131JNIEXPORT jboolean JNICALL
133 jobject stream,
134 jlong aio_pointer) {
135 FFAudioIO *aio = (FFAudioIO *)(intptr_t)aio_pointer;
136 jboolean seekable = JNI_FALSE;
137 seekable = aio->format_context->pb->seekable != 0;
138 return seekable;
139}
140
150 JNIEnv *env, jobject stream, jlong aio_pointer, jlong microseconds) {
151 FFAudioIO *aio = (FFAudioIO *)(intptr_t)aio_pointer;
152 int res = 0;
153 int64_t seek_target = microseconds;
154 int64_t current_timestamp = 0;
155
156 current_timestamp = aio->timestamp;
157 seek_target =
158 av_rescale_q(seek_target, AV_TIME_BASE_Q, aio->stream->time_base);
159#ifdef DEBUG
160 fprintf(stderr,
161 "Current Timestamp = %" PRId64 ", seek_target = %" PRId64 "\n",
162 current_timestamp, seek_target);
163#endif
164 res =
165 av_seek_frame(aio->format_context, aio->stream_index, seek_target,
166 current_timestamp > seek_target ? AVSEEK_FLAG_BACKWARD : 0);
167 if (res < 0) {
168 throwIOExceptionIfError(env, res, "Failed to seek.");
169 goto bail;
170 }
171
172 // make sure everything is flushed.
173 av_packet_unref(aio->decode_packet);
174 // flush codec
175 avcodec_flush_buffers(aio->decode_context);
176 // set timestamp to seek_target, since that's hopefully now our current
177 // timestamp..
178 aio->timestamp = seek_target;
179
180bail:
181
182 return;
183}
184
193 JNIEnv *env, jobject stream, jlong aio_pointer) {
194 ff_audioio_free((FFAudioIO *)(intptr_t)aio_pointer);
195}
JNIEXPORT void JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_close(JNIEnv *env, jobject stream, jlong aio_pointer)
Free all resources associated with a given FFAudioIO.
JNIEXPORT jlong JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_open(JNIEnv *env, jobject stream, jstring url, jbyteArray urlBytes, jint streamIndex, jint fileBufferSize)
Open a file/URL and create a corresponding FFAudioIO.
JNIEXPORT jboolean JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_isSeekable(JNIEnv *env, jobject stream, jlong aio_pointer)
Indicates whether an FFAudioIO context is seekable.
JNIEXPORT void JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_fillNativeBuffer(JNIEnv *env, jobject stream, jlong aio_pointer)
Fills the java-side buffer (allocated via Java code) with fresh audio data.
JNIEXPORT void JNICALL Java_com_tagtraum_ffsampledsp_FFURLInputStream_seek(JNIEnv *env, jobject stream, jlong aio_pointer, jlong microseconds)
Seeks to a point in time.
void ff_audioio_free(FFAudioIO *aio)
Free all resources held by aio and then itself.
Definition FFUtils.c:1169
int ff_open_file(JNIEnv *env, AVFormatContext **format_context, AVStream **openedStream, AVCodecContext **context, int *stream_index, const char *url, int io_buffer_size)
Opens the input file/url, allocates a AVFormatContext for it and opens the audio stream with an appro...
Definition FFUtils.c:378
int ff_fill_buffer(FFAudioIO *aio)
Reads frames via av_read_frame, decodes them, and writes the result to the Java-side nativeBuffer.
Definition FFUtils.c:1107
int ff_init_audioio(JNIEnv *env, FFAudioIO *aio)
Initialize our main context FFAudioIO, so that SwrContext, decode buffers and the encoder are set to ...
Definition FFUtils.c:663
void throwIOExceptionIfError(JNIEnv *env, int err, const char *message)
Throws an IOException.
Definition FFUtils.c:213
Central context representing the native peer to the Java FFNativePeerInputStream object.
Definition FFUtils.h:59
uint64_t timestamp
Current timestamp (in samples, not seconds).
Definition FFUtils.h:74
AVFormatContext * format_context
Current AVFormatContext.
Definition FFUtils.h:66
int stream_index
Index of the audio stream we are using.
Definition FFUtils.h:68
AVStream * stream
Audio stream we are interested in.
Definition FFUtils.h:67
JNIEnv * env
JNI environment.
Definition FFUtils.h:61
AVPacket * decode_packet
AVPacket for decoding.
Definition FFUtils.h:70
AVCodecContext * decode_context
Codec context for decoding.
Definition FFUtils.h:69
jobject java_instance
Calling Java instance.
Definition FFUtils.h:62