526 lines
20 KiB
Diff
526 lines
20 KiB
Diff
diff --git a/Source_Files/FFmpeg/Movie.cpp b/Source_Files/FFmpeg/Movie.cpp
|
|
index d78b0a88..c95bfe27 100644
|
|
--- a/Source_Files/FFmpeg/Movie.cpp
|
|
+++ b/Source_Files/FFmpeg/Movie.cpp
|
|
@@ -114,10 +114,27 @@ static int get_cpu_count(void)
|
|
return cpu_count;
|
|
}
|
|
|
|
+#define AV_FIFO_BUFFER_SIZE (1<<18)
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ #define AV_FIFO_POLL_DELAY_MS 1
|
|
+ #define AV_FIFO_MAX_WAIT_MS 10
|
|
+
|
|
+ #ifdef __WIN32__
|
|
+ #define SleepForMlliseconds Sleep
|
|
+ #else
|
|
+ #include <unistd.h>
|
|
+ #define SleepForMilliseconds(X) usleep(1000 * (X))
|
|
+ #endif
|
|
+#endif
|
|
+
|
|
struct libav_vars {
|
|
bool inited;
|
|
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ AVFifo *audio_fifo;
|
|
+#else
|
|
AVFifoBuffer *audio_fifo;
|
|
+#endif
|
|
|
|
SDL_ffmpegFile* ffmpeg_file;
|
|
SDL_ffmpegAudioFrame* audio_frame;
|
|
@@ -279,7 +296,11 @@ bool Movie::Setup()
|
|
|
|
if (avformat_write_header(av->ffmpeg_file->_ffmpeg, 0) < 0) { ThrowUserError("Could not write header"); return false; }
|
|
|
|
- av->audio_fifo = av_fifo_alloc(262144);
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av->audio_fifo = av_fifo_alloc2(AV_FIFO_BUFFER_SIZE / AV_FIFO_CHUNK_SIZE, AV_FIFO_CHUNK_SIZE, 0);
|
|
+#else
|
|
+ av->audio_fifo = av_fifo_alloc(AV_FIFO_BUFFER_SIZE);
|
|
+#endif
|
|
if (!av->audio_fifo) { ThrowUserError("Could not allocate audio fifo"); return false; }
|
|
|
|
// set up our threads and intermediate storage
|
|
@@ -335,18 +356,56 @@ void Movie::EncodeVideo(bool last)
|
|
|
|
void Movie::EncodeAudio(bool last)
|
|
{
|
|
- av_fifo_generic_write(av->audio_fifo, &audiobuf[0], audiobuf.size(), NULL);
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ size_t max_write = audiobuf.size();
|
|
+ size_t written_so_far = 0, sleep_counter = 0;
|
|
+
|
|
+ while (written_so_far < max_write) {
|
|
+ int writable = MAX(av_fifo_can_write(av->audio_fifo) * AV_FIFO_CHUNK_SIZE, max_write - written_so_far);
|
|
+
|
|
+ if (!writable) {
|
|
+ if (sleep_counter * AV_FIFO_POLL_DELAY_MS >= AV_FIFO_MAX_WAIT_MS)
|
|
+ break;
|
|
+ SleepForMilliseconds(AV_FIFO_POLL_DELAY_MS);
|
|
+ sleep_counter++;
|
|
+ } else {
|
|
+ if (av_fifo_write(av->audio_fifo, &audiobuf[0], writable) < 0)
|
|
+ break;
|
|
+ written_so_far += writable;
|
|
+ sleep_counter = 0;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ av_fifo_generic_write(av->audio_fifo, &audiobuf[0], audiobuf.size(), NULL);
|
|
+#endif
|
|
+
|
|
auto acodec = av->ffmpeg_file->audioStream->_ctx;
|
|
|
|
// bps: bytes per sample
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int channels = acodec->ch_layout.nb_channels;
|
|
+#else
|
|
int channels = acodec->channels;
|
|
+#endif
|
|
|
|
- int max_read = acodec->frame_size * in_bps * channels;
|
|
- int min_read = last ? in_bps * channels : max_read;
|
|
+ size_t max_read = acodec->frame_size * in_bps * channels;
|
|
+ size_t min_read = last ? in_bps * channels : max_read;
|
|
+
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ size_t read_so_far = 0;
|
|
+ while (read_so_far < max_read && av_fifo_can_read(av->audio_fifo) >= min_read)
|
|
+ {
|
|
+ int read_bytes = av->audio_frame->size = MIN(AV_FIFO_CHUNK_SIZE * av_fifo_can_read(av->audio_fifo), max_read);
|
|
+
|
|
+ if (av_fifo_read(av->audio_fifo, av->audio_frame->buffer, read_bytes) < 0)
|
|
+ break;
|
|
+ read_so_far += read_bytes;
|
|
+#else
|
|
while (av_fifo_size(av->audio_fifo) >= min_read)
|
|
{
|
|
int read_bytes = av->audio_frame->size = MIN(av_fifo_size(av->audio_fifo), max_read);
|
|
av_fifo_generic_read(av->audio_fifo, av->audio_frame->buffer, read_bytes, NULL);
|
|
+#endif
|
|
SDL_ffmpegAddAudioFrame(av->ffmpeg_file, av->audio_frame, &av->audio_counter, last);
|
|
}
|
|
}
|
|
@@ -466,8 +525,12 @@ void Movie::StopRecording()
|
|
}
|
|
if (av->audio_fifo)
|
|
{
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av_fifo_freep2(&av->audio_fifo);
|
|
+#else
|
|
av_fifo_free(av->audio_fifo);
|
|
- av->audio_fifo = NULL;
|
|
+ av->audio_fifo = NULL;
|
|
+#endif
|
|
}
|
|
|
|
moviefile = "";
|
|
diff --git a/Source_Files/FFmpeg/SDL_ffmpeg.c b/Source_Files/FFmpeg/SDL_ffmpeg.c
|
|
index 73740e25..eb6322bc 100644
|
|
--- a/Source_Files/FFmpeg/SDL_ffmpeg.c
|
|
+++ b/Source_Files/FFmpeg/SDL_ffmpeg.c
|
|
@@ -444,6 +444,19 @@ SDL_ffmpegFile* SDL_ffmpegOpen( const char* filename )
|
|
}
|
|
else
|
|
{
|
|
+ int rv = 0;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int channel_layout = stream->_ffmpeg->codecpar->ch_layout.u.mask ? stream->_ffmpeg->codecpar->ch_layout.u.mask :
|
|
+ (stream->_ffmpeg->codecpar->ch_layout.nb_channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO);
|
|
+ AVChannelLayout in_layout, out_layout;
|
|
+
|
|
+ in_layout = out_layout = stream->_ffmpeg->codecpar->ch_layout;
|
|
+ in_layout.u.mask = out_layout.u.mask = channel_layout;
|
|
+ rv = swr_alloc_set_opts2(&stream->swr_context, &out_layout, AV_SAMPLE_FMT_FLT,
|
|
+ stream->_ffmpeg->codecpar->sample_rate, &in_layout,
|
|
+ stream->_ffmpeg->codecpar->format, stream->_ffmpeg->codecpar->sample_rate,
|
|
+ 0, NULL);
|
|
+#else
|
|
int channel_layout = stream->_ffmpeg->codecpar->channel_layout ? stream->_ffmpeg->codecpar->channel_layout :
|
|
(stream->_ffmpeg->codecpar->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO);
|
|
|
|
@@ -451,8 +464,9 @@ SDL_ffmpegFile* SDL_ffmpegOpen( const char* filename )
|
|
stream->_ffmpeg->codecpar->sample_rate, channel_layout,
|
|
stream->_ffmpeg->codecpar->format, stream->_ffmpeg->codecpar->sample_rate,
|
|
0, NULL);
|
|
+#endif
|
|
|
|
- if (!stream->swr_context || swr_init(stream->swr_context) < 0) {
|
|
+ if (rv < 0 || !stream->swr_context || swr_init(stream->swr_context) < 0) {
|
|
free(stream);
|
|
SDL_ffmpegSetError("could not initialize resampler");
|
|
continue;
|
|
@@ -648,7 +662,11 @@ int SDL_ffmpegAddAudioFrame( SDL_ffmpegFile *file, SDL_ffmpegAudioFrame *frame,
|
|
|
|
// convert
|
|
int32_t write_bps = av_get_bytes_per_sample(acodec->sample_fmt);
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int32_t read_samples = frame->size / (av_get_bytes_per_sample(file->audioStream->audioFormat) * acodec->ch_layout.nb_channels);
|
|
+#else
|
|
int32_t read_samples = frame->size / (av_get_bytes_per_sample(file->audioStream->audioFormat) * acodec->channels);
|
|
+#endif
|
|
int32_t write_samples = read_samples;
|
|
if (read_samples < acodec->frame_size)
|
|
{
|
|
@@ -665,9 +683,14 @@ int SDL_ffmpegAddAudioFrame( SDL_ffmpegFile *file, SDL_ffmpegAudioFrame *frame,
|
|
av_frame_unref(audio_frame);
|
|
|
|
//Needed since ffmpeg 4.4
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ audio_frame->ch_layout.nb_channels = acodec->ch_layout.nb_channels;
|
|
+ audio_frame->ch_layout.u.mask = acodec->ch_layout.u.mask;
|
|
+#else
|
|
audio_frame->channels = acodec->channels;
|
|
- audio_frame->format = acodec->sample_fmt;
|
|
audio_frame->channel_layout = acodec->channel_layout;
|
|
+#endif
|
|
+ audio_frame->format = acodec->sample_fmt;
|
|
audio_frame->sample_rate = acodec->sample_rate;
|
|
audio_frame->nb_samples = write_samples;
|
|
|
|
@@ -675,10 +698,17 @@ int SDL_ffmpegAddAudioFrame( SDL_ffmpegFile *file, SDL_ffmpegAudioFrame *frame,
|
|
audio_frame->pts = av_rescale_q(*frameCounter, avSampleRate, acodec->time_base);
|
|
|
|
*frameCounter += write_samples;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int asize = avcodec_fill_audio_frame(audio_frame, acodec->ch_layout.nb_channels,
|
|
+ acodec->sample_fmt,
|
|
+ frame->conversionBuffer[0],
|
|
+ write_samples * write_bps * acodec->ch_layout.nb_channels, 1);
|
|
+#else
|
|
int asize = avcodec_fill_audio_frame(audio_frame, acodec->channels,
|
|
acodec->sample_fmt,
|
|
frame->conversionBuffer[0],
|
|
write_samples * write_bps * acodec->channels, 1);
|
|
+#endif
|
|
|
|
if (asize >= 0)
|
|
{
|
|
@@ -762,10 +792,18 @@ SDL_ffmpegAudioFrame* SDL_ffmpegCreateAudioFrame( SDL_ffmpegFile *file, uint32_t
|
|
|
|
if ( file->type == SDL_ffmpegOutputStream )
|
|
{
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ bytes = file->audioStream->encodeAudioInputSize * av_get_bytes_per_sample(file->audioStream->audioFormat) * file->audioStream->_ctx->ch_layout.nb_channels;
|
|
+#else
|
|
bytes = file->audioStream->encodeAudioInputSize * av_get_bytes_per_sample(file->audioStream->audioFormat) * file->audioStream->_ctx->channels;
|
|
+#endif
|
|
|
|
// allocate conversion buffer only when output, input does it differently
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ if (av_samples_alloc_array_and_samples(&frame->conversionBuffer, NULL, file->audioStream->_ctx->ch_layout.nb_channels, file->audioStream->encodeAudioInputSize, file->audioStream->_ctx->sample_fmt, 0) < 0)
|
|
+#else
|
|
if (av_samples_alloc_array_and_samples(&frame->conversionBuffer, NULL, file->audioStream->_ctx->channels, file->audioStream->encodeAudioInputSize, file->audioStream->_ctx->sample_fmt, 0) < 0)
|
|
+#endif
|
|
{
|
|
return 0;
|
|
}
|
|
@@ -1355,7 +1393,11 @@ SDL_AudioSpec SDL_ffmpegGetAudioSpec( SDL_ffmpegFile *file, uint16_t samples, SD
|
|
spec.userdata = file;
|
|
spec.callback = callback;
|
|
spec.freq = file->audioStream->_ctx->sample_rate;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ spec.channels = ( uint8_t )file->audioStream->_ctx->ch_layout.nb_channels;
|
|
+#else
|
|
spec.channels = ( uint8_t )file->audioStream->_ctx->channels;
|
|
+#endif
|
|
}
|
|
else
|
|
{
|
|
@@ -1687,8 +1729,13 @@ SDL_ffmpegStream* SDL_ffmpegAddAudioStream( SDL_ffmpegFile *file, SDL_ffmpegCode
|
|
stream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
|
|
stream->codecpar->sample_rate = codec.sampleRate;
|
|
stream->codecpar->format = AV_SAMPLE_FMT_FLTP;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ stream->codecpar->ch_layout.nb_channels = codec.channels;
|
|
+ stream->codecpar->ch_layout.u.mask = codec.channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
|
|
+#else
|
|
stream->codecpar->channels = codec.channels;
|
|
stream->codecpar->channel_layout = codec.channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
|
|
+#endif
|
|
|
|
if (avcodec_parameters_to_context(context, stream->codecpar) < 0)
|
|
{
|
|
@@ -1721,6 +1768,11 @@ SDL_ffmpegStream* SDL_ffmpegAddAudioStream( SDL_ffmpegFile *file, SDL_ffmpegCode
|
|
|
|
if ( str )
|
|
{
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ AVChannelLayout in_layout, out_layout;
|
|
+#endif
|
|
+ int rv = 0;
|
|
+
|
|
/* we set our stream to zero */
|
|
memset( str, 0, sizeof( SDL_ffmpegStream ) );
|
|
|
|
@@ -1734,10 +1786,16 @@ SDL_ffmpegStream* SDL_ffmpegAddAudioStream( SDL_ffmpegFile *file, SDL_ffmpegCode
|
|
str->audioFormat = codec.audioFormat;
|
|
|
|
// init resampler
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ in_layout = out_layout = context->ch_layout;
|
|
+ rv = swr_alloc_set_opts2(&str->swr_context, &out_layout, context->sample_fmt, context->sample_rate,
|
|
+ &in_layout, str->audioFormat, context->sample_rate, 0, NULL);
|
|
+#else
|
|
str->swr_context = swr_alloc_set_opts(str->swr_context, context->channel_layout, context->sample_fmt, context->sample_rate,
|
|
context->channel_layout, str->audioFormat, context->sample_rate, 0, NULL);
|
|
+#endif
|
|
|
|
- if (!str->swr_context || swr_init(str->swr_context) < 0)
|
|
+ if (rv < 0 || !str->swr_context || swr_init(str->swr_context) < 0)
|
|
{
|
|
SDL_ffmpegSetError("could not initialize resampler");
|
|
return 0;
|
|
@@ -1745,9 +1803,15 @@ SDL_ffmpegStream* SDL_ffmpegAddAudioStream( SDL_ffmpegFile *file, SDL_ffmpegCode
|
|
|
|
str->mutex = SDL_CreateMutex();
|
|
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ str->sampleBufferSize = av_samples_get_buffer_size(0, stream->codecpar->ch_layout.nb_channels, stream->codecpar->frame_size, AV_SAMPLE_FMT_FLT, 0);
|
|
+
|
|
+ if (av_samples_alloc((uint8_t**)(&str->sampleBuffer), 0, stream->codecpar->ch_layout.nb_channels, stream->codecpar->frame_size, AV_SAMPLE_FMT_FLT, 0) < 0)
|
|
+#else
|
|
str->sampleBufferSize = av_samples_get_buffer_size(0, stream->codecpar->channels, stream->codecpar->frame_size, AV_SAMPLE_FMT_FLT, 0);
|
|
|
|
if (av_samples_alloc((uint8_t**)(&str->sampleBuffer), 0, stream->codecpar->channels, stream->codecpar->frame_size, AV_SAMPLE_FMT_FLT, 0) < 0)
|
|
+#endif
|
|
{
|
|
SDL_ffmpegSetError("could not allocate samples for audio buffer");
|
|
return 0;
|
|
@@ -1757,7 +1821,11 @@ SDL_ffmpegStream* SDL_ffmpegAddAudioStream( SDL_ffmpegFile *file, SDL_ffmpegCode
|
|
support to compute the input frame size in samples */
|
|
if ( stream->codecpar->frame_size <= 1 )
|
|
{
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ str->encodeAudioInputSize = str->sampleBufferSize / stream->codecpar->ch_layout.nb_channels;
|
|
+#else
|
|
str->encodeAudioInputSize = str->sampleBufferSize / stream->codecpar->channels;
|
|
+#endif
|
|
|
|
switch ( stream->codecpar->codec_id )
|
|
{
|
|
@@ -1946,7 +2014,11 @@ int SDL_ffmpegDecodeAudioFrame( SDL_ffmpegFile *file, AVPacket *pack, SDL_ffmpeg
|
|
{
|
|
int audioSize = AVCODEC_MAX_AUDIO_FRAME_SIZE * sizeof( float );
|
|
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int channels = file->audioStream->_ctx->ch_layout.nb_channels;
|
|
+#else
|
|
int channels = file->audioStream->_ctx->channels;
|
|
+#endif
|
|
enum AVSampleFormat format = AV_SAMPLE_FMT_FLT;
|
|
int bps = av_get_bytes_per_sample(format);
|
|
|
|
@@ -2020,10 +2092,14 @@ int SDL_ffmpegDecodeAudioFrame( SDL_ffmpegFile *file, AVPacket *pack, SDL_ffmpeg
|
|
AVFrame* convertedFrame = file->audioStream->encodeFrame;
|
|
|
|
while (avcodec_receive_frame(avctx, dframe) == 0) {
|
|
-
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ dframe->ch_layout.u.mask |= dframe->ch_layout.nb_channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
|
|
+ convertedFrame->ch_layout.u.mask = dframe->ch_layout.u.mask;
|
|
+#else
|
|
dframe->channel_layout |= dframe->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
|
|
- convertedFrame->nb_samples = dframe->nb_samples;
|
|
convertedFrame->channel_layout = dframe->channel_layout;
|
|
+#endif
|
|
+ convertedFrame->nb_samples = dframe->nb_samples;
|
|
convertedFrame->sample_rate = dframe->sample_rate;
|
|
convertedFrame->format = AV_SAMPLE_FMT_FLT;
|
|
|
|
@@ -2036,15 +2112,27 @@ int SDL_ffmpegDecodeAudioFrame( SDL_ffmpegFile *file, AVPacket *pack, SDL_ffmpeg
|
|
int planar = av_sample_fmt_is_planar(convertedFrame->format);
|
|
int plane_size;
|
|
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ int data_size = av_samples_get_buffer_size(&plane_size, convertedFrame->ch_layout.nb_channels, convertedFrame->nb_samples, convertedFrame->format, 1);
|
|
+#else
|
|
int data_size = av_samples_get_buffer_size(&plane_size, convertedFrame->channels, convertedFrame->nb_samples, convertedFrame->format, 1);
|
|
+#endif
|
|
|
|
memcpy(file->audioStream->sampleBuffer, convertedFrame->extended_data[0], plane_size);
|
|
audioSize = plane_size;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ if (planar && convertedFrame->ch_layout.nb_channels > 1)
|
|
+#else
|
|
if (planar && convertedFrame->channels > 1)
|
|
+#endif
|
|
{
|
|
int8_t* out = file->audioStream->sampleBuffer + plane_size;
|
|
int ch;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ for (ch = 1; ch < convertedFrame->ch_layout.nb_channels; ch++)
|
|
+#else
|
|
for (ch = 1; ch < convertedFrame->channels; ch++)
|
|
+#endif
|
|
{
|
|
memcpy(out, convertedFrame->extended_data[ch], plane_size);
|
|
out += plane_size;
|
|
diff --git a/Source_Files/FFmpeg/SDL_ffmpeg.h b/Source_Files/FFmpeg/SDL_ffmpeg.h
|
|
index 26d5c92b..253e48a5 100644
|
|
--- a/Source_Files/FFmpeg/SDL_ffmpeg.h
|
|
+++ b/Source_Files/FFmpeg/SDL_ffmpeg.h
|
|
@@ -40,6 +40,14 @@ extern "C" {
|
|
#define EXPORT
|
|
// #endif
|
|
|
|
+// The avutil FIFO API underwent major changes in version 57.20.100
|
|
+// (cf. https://git.videolan.org/?p=ffmpeg.git;a=blob_plain;f=doc/APIchanges;hb=n7.0 )
|
|
+#include <libavutil/version.h>
|
|
+#if LIBAVUTIL_VERSION_MAJOR > 57 || LIBAVUTIL_VERSION_MAJOR == 57 && LIBAVUTIL_VERSION_MINOR >= 20
|
|
+ #define USE_NEW_AV_FIFO_API 1
|
|
+ #define AV_FIFO_CHUNK_SIZE 4
|
|
+#endif
|
|
+
|
|
enum SDL_ffmpegStreamType
|
|
{
|
|
SDL_ffmpegUninitialized = 0,
|
|
diff --git a/Source_Files/Sound/FFmpegDecoder.cpp b/Source_Files/Sound/FFmpegDecoder.cpp
|
|
index a166155b..a97c405b 100644
|
|
--- a/Source_Files/Sound/FFmpegDecoder.cpp
|
|
+++ b/Source_Files/Sound/FFmpegDecoder.cpp
|
|
@@ -50,10 +50,16 @@ extern "C"
|
|
}
|
|
#endif
|
|
|
|
+#define AV_FIFO_BUFFER_SIZE (1<<19)
|
|
+
|
|
struct ffmpeg_vars {
|
|
SDL_ffmpegFile* file;
|
|
SDL_ffmpegAudioFrame* frame;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ AVFifo *fifo;
|
|
+#else
|
|
AVFifoBuffer *fifo;
|
|
+#endif
|
|
bool started;
|
|
};
|
|
typedef struct ffmpeg_vars ffmpeg_vars_t;
|
|
@@ -64,14 +70,22 @@ FFmpegDecoder::FFmpegDecoder() :
|
|
av = new ffmpeg_vars_t;
|
|
memset(av, 0, sizeof(ffmpeg_vars_t));
|
|
|
|
- av->fifo = av_fifo_alloc(524288);
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av->fifo = av_fifo_alloc2(AV_FIFO_BUFFER_SIZE / AV_FIFO_CHUNK_SIZE, AV_FIFO_CHUNK_SIZE, 0);
|
|
+#else
|
|
+ av->fifo = av_fifo_alloc(AV_FIFO_BUFFER_SIZE);
|
|
+#endif
|
|
}
|
|
|
|
FFmpegDecoder::~FFmpegDecoder()
|
|
{
|
|
Close();
|
|
if (av && av->fifo)
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av_fifo_freep2(&av->fifo);
|
|
+#else
|
|
av_fifo_free(av->fifo);
|
|
+#endif
|
|
}
|
|
|
|
bool FFmpegDecoder::Open(FileSpecifier& File)
|
|
@@ -99,30 +113,47 @@ bool FFmpegDecoder::Open(FileSpecifier& File)
|
|
return false;
|
|
}
|
|
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ channels = av->file->audioStream->_ffmpeg->codecpar->ch_layout.nb_channels;
|
|
+#else
|
|
channels = av->file->audioStream->_ffmpeg->codecpar->channels;
|
|
+#endif
|
|
rate = av->file->audioStream->_ffmpeg->codecpar->sample_rate;
|
|
return true;
|
|
}
|
|
|
|
int32 FFmpegDecoder::Decode(uint8* buffer, int32 max_length)
|
|
{
|
|
- int32 total_bytes_read = 0;
|
|
- uint8* cur = buffer;
|
|
+ size_t total_bytes_read = 0;
|
|
+
|
|
while (total_bytes_read < max_length)
|
|
{
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ size_t fifo_chunks_waiting = av_fifo_can_read(av->fifo);
|
|
+ if (!fifo_chunks_waiting)
|
|
+ {
|
|
+ if (!GetAudio())
|
|
+ break;
|
|
+ fifo_chunks_waiting = av_fifo_can_read(av->fifo);
|
|
+ }
|
|
+ size_t chunks_to_read = std::min(fifo_chunks_waiting * AV_FIFO_CHUNK_SIZE, (max_length - total_bytes_read + AV_FIFO_CHUNK_SIZE - 1) / AV_FIFO_CHUNK_SIZE);
|
|
+ if (!chunks_to_read || av_fifo_read(av->fifo, buffer + total_bytes_read, chunks_to_read) < 0)
|
|
+ break;
|
|
+ total_bytes_read += chunks_to_read * AV_FIFO_CHUNK_SIZE;
|
|
+#else
|
|
int32 fifo_size = av_fifo_size(av->fifo);
|
|
if (!fifo_size)
|
|
{
|
|
if (!GetAudio())
|
|
break;
|
|
fifo_size = av_fifo_size(av->fifo);
|
|
- }
|
|
- int bytes_read = std::min(fifo_size, max_length - total_bytes_read);
|
|
- av_fifo_generic_read(av->fifo, cur, bytes_read, NULL);
|
|
+ }
|
|
+ int bytes_read = std::min(fifo_size, max_length - (int) total_bytes_read);
|
|
+ av_fifo_generic_read(av->fifo, buffer + total_bytes_read, bytes_read, NULL);
|
|
total_bytes_read += bytes_read;
|
|
- cur += bytes_read;
|
|
+#endif
|
|
}
|
|
-
|
|
+
|
|
memset(&buffer[total_bytes_read], 0, max_length - total_bytes_read);
|
|
return total_bytes_read;
|
|
}
|
|
@@ -132,7 +163,11 @@ void FFmpegDecoder::Rewind()
|
|
if (av->started)
|
|
{
|
|
SDL_ffmpegSeekRelative(av->file, 0);
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av_fifo_reset2(av->fifo);
|
|
+#else
|
|
av_fifo_reset(av->fifo);
|
|
+#endif
|
|
av->started = false;
|
|
}
|
|
}
|
|
@@ -144,15 +179,32 @@ void FFmpegDecoder::Close()
|
|
if (av && av->frame)
|
|
SDL_ffmpegFreeAudioFrame(av->frame);
|
|
if (av && av->fifo)
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ av_fifo_reset2(av->fifo);
|
|
+#else
|
|
av_fifo_reset(av->fifo);
|
|
+#endif
|
|
if (av)
|
|
av->started = false;
|
|
}
|
|
|
|
bool FFmpegDecoder::GetAudio()
|
|
{
|
|
- if (!SDL_ffmpegGetAudioFrame(av->file, av->frame)) return false;
|
|
+ if (!SDL_ffmpegGetAudioFrame(av->file, av->frame))
|
|
+ return false;
|
|
+#if USE_NEW_AV_FIFO_API
|
|
+ for (size_t bytes_written = 0; bytes_written < av->frame->size; )
|
|
+ {
|
|
+ size_t free_chunks_in_fifo = av_fifo_can_write(av->fifo);
|
|
+ size_t chunks_to_write = std::min((av->frame->size - bytes_written + AV_FIFO_CHUNK_SIZE - 1) / AV_FIFO_CHUNK_SIZE, free_chunks_in_fifo);
|
|
+ if (!free_chunks_in_fifo || av_fifo_write(av->fifo, av->frame->buffer + bytes_written, chunks_to_write) < 0)
|
|
+ break;
|
|
+ bytes_written += chunks_to_write * AV_FIFO_CHUNK_SIZE;
|
|
+ }
|
|
+#else
|
|
av_fifo_generic_write(av->fifo, av->frame->buffer, av->frame->size, NULL);
|
|
+#endif
|
|
+
|
|
av->started = true;
|
|
return true;
|
|
}
|