aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder/plugins/FfmpegDecoderPlugin.cxx29
-rw-r--r--src/decoder/plugins/GmeDecoderPlugin.cxx1
-rw-r--r--src/decoder/plugins/SndfileDecoderPlugin.cxx26
3 files changed, 47 insertions, 9 deletions
diff --git a/src/decoder/plugins/FfmpegDecoderPlugin.cxx b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
index f2ad714bf..6310ea7fe 100644
--- a/src/decoder/plugins/FfmpegDecoderPlugin.cxx
+++ b/src/decoder/plugins/FfmpegDecoderPlugin.cxx
@@ -197,6 +197,29 @@ time_to_ffmpeg(double t, const AVRational time_base)
time_base);
}
+/**
+ * Replace #AV_NOPTS_VALUE with the given fallback.
+ */
+static constexpr int64_t
+timestamp_fallback(int64_t t, int64_t fallback)
+{
+ return gcc_likely(t != int64_t(AV_NOPTS_VALUE))
+ ? t
+ : fallback;
+}
+
+/**
+ * Accessor for AVStream::start_time that replaces AV_NOPTS_VALUE with
+ * zero. We can't use AV_NOPTS_VALUE in calculations, and we simply
+ * assume that the stream's start time is zero, which appears to be
+ * the best way out of that situation.
+ */
+static int64_t
+start_time_fallback(const AVStream &stream)
+{
+ return timestamp_fallback(stream.start_time, 0);
+}
+
static void
copy_interleave_frame2(uint8_t *dest, uint8_t **src,
unsigned nframes, unsigned nchannels,
@@ -263,7 +286,7 @@ ffmpeg_send_packet(Decoder &decoder, InputStream &is,
{
if (packet->pts >= 0 && packet->pts != (int64_t)AV_NOPTS_VALUE)
decoder_timestamp(decoder,
- time_from_ffmpeg(packet->pts - stream->start_time,
+ time_from_ffmpeg(packet->pts - start_time_fallback(*stream),
stream->time_base));
AVPacket packet2 = *packet;
@@ -496,10 +519,10 @@ ffmpeg_decode(Decoder &decoder, InputStream &input)
int64_t where =
time_to_ffmpeg(decoder_seek_where(decoder),
av_stream->time_base) +
- av_stream->start_time;
+ start_time_fallback(*av_stream);
if (av_seek_frame(format_context, audio_stream, where,
- AV_TIME_BASE) < 0)
+ AVSEEK_FLAG_ANY) < 0)
decoder_seek_error(decoder);
else {
avcodec_flush_buffers(codec_context);
diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx
index 2390af2d2..469da2540 100644
--- a/src/decoder/plugins/GmeDecoderPlugin.cxx
+++ b/src/decoder/plugins/GmeDecoderPlugin.cxx
@@ -120,6 +120,7 @@ gme_container_scan(Path path_fs, const unsigned int tnum)
}
const unsigned num_songs = gme_track_count(emu);
+ gme_delete(emu);
/* if it only contains a single tune, don't treat as container */
if (num_songs < 2)
return nullptr;
diff --git a/src/decoder/plugins/SndfileDecoderPlugin.cxx b/src/decoder/plugins/SndfileDecoderPlugin.cxx
index 72ea77d15..6d9e0d31e 100644
--- a/src/decoder/plugins/SndfileDecoderPlugin.cxx
+++ b/src/decoder/plugins/SndfileDecoderPlugin.cxx
@@ -56,14 +56,28 @@ sndfile_vio_read(void *ptr, sf_count_t count, void *user_data)
{
InputStream &is = *(InputStream *)user_data;
+ sf_count_t total_bytes = 0;
Error error;
- size_t nbytes = is.LockRead(ptr, count, error);
- if (nbytes == 0 && error.IsDefined()) {
- LogError(error);
- return -1;
- }
- return nbytes;
+ /* this loop is necessary because libsndfile chokes on partial
+ reads */
+
+ do {
+ size_t nbytes = is.LockRead((char *)ptr + total_bytes,
+ count - total_bytes, error);
+ if (nbytes == 0) {
+ if (error.IsDefined()) {
+ LogError(error);
+ return -1;
+ }
+
+ break;
+ }
+
+ total_bytes += nbytes;
+ } while (total_bytes < count);
+
+ return total_bytes;
}
static sf_count_t