diff options
Diffstat (limited to 'src/decoder/plugins')
-rw-r--r-- | src/decoder/plugins/FfmpegDecoderPlugin.cxx | 29 | ||||
-rw-r--r-- | src/decoder/plugins/GmeDecoderPlugin.cxx | 1 | ||||
-rw-r--r-- | src/decoder/plugins/SndfileDecoderPlugin.cxx | 26 |
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 |