#include <libavresample/avresample.h>
#endif
#include <libavutil/opt.h>
-#include <stdlib.h>
// determine whether we use libavformat from ffmpeg or from libav
#define FFMPEG_LIBAVFORMAT (LIBAVFORMAT_VERSION_MICRO > 99 )
#define HAVE_AUBIO_LIBAVCODEC_DEPRECATED 1
#endif
+#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,3,102)
+#define HAVE_AUBIO_LIBAVCODEC_TIMEBASE_FIX 1
+#endif
+
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
#warning "libavcodec < 56 is deprecated"
#define av_frame_alloc avcodec_alloc_frame
#include "aubio_priv.h"
#include "fvec.h"
#include "fmat.h"
+#include "ioutils.h"
#include "source_avcodec.h"
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 56, 0)
uint_t read_index;
sint_t selected_stream;
uint_t eof;
- uint_t multi;
};
// create or re-create the context when _do or _do_multi is called
-void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s,
- uint_t multi);
+void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s);
// actually read a frame
void aubio_source_avcodec_readframe(aubio_source_avcodec_t *s,
uint_t * read_samples);
aubio_source_avcodec_t * new_aubio_source_avcodec(const char_t * path,
uint_t samplerate, uint_t hop_size) {
aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t);
- AVFormatContext *avFormatCtx = s->avFormatCtx;
- AVCodecContext *avCodecCtx = s->avCodecCtx;
- AVFrame *avFrame = s->avFrame;
+ AVFormatContext *avFormatCtx = NULL;
+ AVCodecContext *avCodecCtx = NULL;
+ AVFrame *avFrame = NULL;
sint_t selected_stream = -1;
#if FF_API_LAVF_AVCTX
AVCodecParameters *codecpar;
s->hop_size = hop_size;
s->channels = 1;
- if (s->path) AUBIO_FREE(s->path);
s->path = AUBIO_ARRAY(char_t, strnlen(path, PATH_MAX) + 1);
strncpy(s->path, path, strnlen(path, PATH_MAX) + 1);
av_get_media_type_string(AVMEDIA_TYPE_AUDIO), s->path);
goto beach;
}
+#if HAVE_AUBIO_LIBAVCODEC_TIMEBASE_FIX
+ // avoids 'skipped frames warning' with avecodec < 58, deprecated after
+ av_codec_set_pkt_timebase(avCodecCtx,
+ avFormatCtx->streams[selected_stream]->time_base);
+#endif
#endif
if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {
s->avCodecCtx = avCodecCtx;
s->avFrame = avFrame;
- // default to mono output
- aubio_source_avcodec_reset_resampler(s, 0);
+ aubio_source_avcodec_reset_resampler(s);
if (s->avr == NULL) goto beach;
s->eof = 0;
- s->multi = 0;
//av_log_set_level(AV_LOG_QUIET);
return NULL;
}
-void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s,
- uint_t multi)
+void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s)
{
// create or reset resampler to/from mono/multi-channel
- if ( (multi != s->multi) || (s->avr == NULL) ) {
+ if ( s->avr == NULL ) {
int err;
int64_t input_layout = av_get_default_channel_layout(s->input_channels);
- uint_t output_channels = multi ? s->input_channels : 1;
- int64_t output_layout = av_get_default_channel_layout(output_channels);
+ int64_t output_layout = av_get_default_channel_layout(s->input_channels);
#ifdef HAVE_AVRESAMPLE
AVAudioResampleContext *avr = avresample_alloc_context();
- AVAudioResampleContext *oldavr = s->avr;
#elif defined(HAVE_SWRESAMPLE)
SwrContext *avr = swr_alloc();
- SwrContext *oldavr = s->avr;
#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
av_opt_set_int(avr, "in_channel_layout", input_layout, 0);
return;
}
s->avr = avr;
- if (oldavr != NULL) {
-#ifdef HAVE_AVRESAMPLE
- avresample_close( oldavr );
-#elif defined(HAVE_SWRESAMPLE)
- swr_close ( oldavr );
-#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
- av_free ( oldavr );
- oldavr = NULL;
- }
- s->multi = multi;
}
}
(uint8_t **)&output, max_out_samples,
(const uint8_t **)avFrame->data, in_samples);
#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
- if (out_samples <= 0) {
- AUBIO_WRN("source_avcodec: no sample found while converting frame (%s)\n",
- s->path);
+ if (out_samples < 0) {
+ AUBIO_WRN("source_avcodec: error while resampling %s (%d)\n",
+ s->path, out_samples);
goto beach;
}
*read_samples = out_samples;
beach:
- s->avFormatCtx = avFormatCtx;
- s->avCodecCtx = avCodecCtx;
- s->avFrame = avFrame;
-#if defined(HAVE_AVRESAMPLE) || defined(HAVE_SWRESAMPLE)
- s->avr = avr;
-#endif /* HAVE_AVRESAMPLE || HAVE_SWRESAMPLE */
- s->output = output;
-
av_packet_unref(&avPacket);
}
void aubio_source_avcodec_do(aubio_source_avcodec_t * s, fvec_t * read_data,
uint_t * read) {
- uint_t i;
+ uint_t i, j;
uint_t end = 0;
uint_t total_wrote = 0;
- // switch from multi
- if (s->multi == 1) aubio_source_avcodec_reset_resampler(s, 0);
- while (total_wrote < s->hop_size) {
- end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
+ uint_t length = aubio_source_validate_input_length("source_avcodec", s->path,
+ s->hop_size, read_data->length);
+ if (!s->avr || !s->avFormatCtx || !s->avCodecCtx) {
+ AUBIO_ERR("source_avcodec: could not read from %s (file was closed)\n",
+ s->path);
+ *read= 0;
+ return;
+ }
+ while (total_wrote < length) {
+ end = MIN(s->read_samples - s->read_index, length - total_wrote);
for (i = 0; i < end; i++) {
- read_data->data[i + total_wrote] = s->output[i + s->read_index];
+ read_data->data[i + total_wrote] = 0.;
+ for (j = 0; j < s->input_channels; j++) {
+ read_data->data[i + total_wrote] +=
+ s->output[(i + s->read_index) * s->input_channels + j];
+ }
+ read_data->data[i + total_wrote] *= 1./s->input_channels;
}
total_wrote += end;
- if (total_wrote < s->hop_size) {
+ if (total_wrote < length) {
uint_t avcodec_read = 0;
aubio_source_avcodec_readframe(s, &avcodec_read);
s->read_samples = avcodec_read;
s->read_index += end;
}
}
- if (total_wrote < s->hop_size) {
- for (i = total_wrote; i < s->hop_size; i++) {
- read_data->data[i] = 0.;
- }
- }
+
+ aubio_source_pad_output(read_data, total_wrote);
+
*read = total_wrote;
}
uint_t i,j;
uint_t end = 0;
uint_t total_wrote = 0;
- // switch from mono
- if (s->multi == 0) aubio_source_avcodec_reset_resampler(s, 1);
- while (total_wrote < s->hop_size) {
- end = MIN(s->read_samples - s->read_index, s->hop_size - total_wrote);
- for (j = 0; j < read_data->height; j++) {
+ uint_t length = aubio_source_validate_input_length("source_avcodec", s->path,
+ s->hop_size, read_data->length);
+ uint_t channels = aubio_source_validate_input_channels("source_avcodec",
+ s->path, s->input_channels, read_data->height);
+ if (!s->avr || !s->avFormatCtx || !s->avCodecCtx) {
+ AUBIO_ERR("source_avcodec: could not read from %s (file was closed)\n",
+ s->path);
+ *read= 0;
+ return;
+ }
+ while (total_wrote < length) {
+ end = MIN(s->read_samples - s->read_index, length - total_wrote);
+ for (j = 0; j < channels; j++) {
for (i = 0; i < end; i++) {
read_data->data[j][i + total_wrote] =
s->output[(i + s->read_index) * s->input_channels + j];
}
}
total_wrote += end;
- if (total_wrote < s->hop_size) {
+ if (total_wrote < length) {
uint_t avcodec_read = 0;
aubio_source_avcodec_readframe(s, &avcodec_read);
s->read_samples = avcodec_read;
s->read_index += end;
}
}
- if (total_wrote < s->hop_size) {
- for (j = 0; j < read_data->height; j++) {
- for (i = total_wrote; i < s->hop_size; i++) {
- read_data->data[j][i] = 0.;
- }
- }
- }
+
+ aubio_source_pad_multi_output(read_data, s->input_channels, total_wrote);
+
*read = total_wrote;
}
}
void del_aubio_source_avcodec(aubio_source_avcodec_t * s){
- if (!s) return;
+ AUBIO_ASSERT(s);
aubio_source_avcodec_close(s);
if (s->output != NULL) {
av_free(s->output);