From 2754f05b11e14e6ce98c7aa0dcb06fa583910f9d Mon Sep 17 00:00:00 2001 From: bnnm Date: Wed, 30 Nov 2016 23:48:49 +0100 Subject: [PATCH] Move FFmpeg looping to ffmpeg_decoder for further changes (cleanup) --- src/coding/coding.h | 3 +++ src/coding/ffmpeg_decoder.c | 52 +++++++++++++++++++++++++++++++++++++ src/vgmstream.c | 48 +--------------------------------- 3 files changed, 56 insertions(+), 47 deletions(-) diff --git a/src/coding/coding.h b/src/coding/coding.h index 02e1142f..6b8eeaff 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -111,6 +111,9 @@ void decode_at3plus(VGMSTREAM *vgmstream, #ifdef VGM_USE_FFMPEG void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels); + +void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample); + #endif void decode_acm(ACMStream * acm, sample * outbuf, diff --git a/src/coding/ffmpeg_decoder.c b/src/coding/ffmpeg_decoder.c index a6f0a5d6..eaecf32e 100644 --- a/src/coding/ffmpeg_decoder.c +++ b/src/coding/ffmpeg_decoder.c @@ -247,4 +247,56 @@ end: data->endOfAudio = endOfAudio; } + +void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) { + ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data; + int64_t ts; + +#ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING + /* Seek to loop start by timestamp (closest frame) + adjust skipping some samples */ + /* FFmpeg seeks by ts by design (since not all containers can accurately skip to a frame). */ + /* TODO: this seems to be off by +-1 frames in some cases */ + ts = num_sample; + if (ts >= data->sampleRate * 2) { + data->samplesToDiscard = data->sampleRate * 2; + ts -= data->samplesToDiscard; + } + else { + data->samplesToDiscard = (int)ts; + ts = 0; + } + + /* todo fix this properly */ + if (data->totalFrames) { + data->framesRead = (int)ts; + ts = data->framesRead * (data->formatCtx->duration) / data->totalFrames; + } else { + data->samplesToDiscard = num_sample; + data->framesRead = 0; + ts = 0; + } + + avformat_seek_file(data->formatCtx, -1, ts - 1000, ts, ts, AVSEEK_FLAG_ANY); + avcodec_flush_buffers(data->codecCtx); +#endif /* ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING */ + +#ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING + /* Start from 0 and discard samples until loop_start for accurate looping (slower but not too noticeable) */ + /* We could also seek by offset (AVSEEK_FLAG_BYTE) to the frame closest to the loop then discard + * some samples, which is fast but would need calculations per format / when frame size is not constant */ + data->samplesToDiscard = num_sample; + data->framesRead = 0; + ts = 0; + + avformat_seek_file(data->formatCtx, -1, ts, ts, ts, AVSEEK_FLAG_ANY); + avcodec_flush_buffers(data->codecCtx); +#endif /* ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING */ + + data->readNextPacket = 1; + data->bytesConsumedFromDecodedFrame = INT_MAX; + data->endOfStream = 0; + data->endOfAudio = 0; + +} + #endif diff --git a/src/vgmstream.c b/src/vgmstream.c index ef063f2f..f464e407 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -1789,53 +1789,7 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { } #ifdef VGM_USE_FFMPEG if (vgmstream->coding_type==coding_FFmpeg) { - ffmpeg_codec_data *data = (ffmpeg_codec_data *)(vgmstream->codec_data); - int64_t ts; - -#ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING - /* Seek to loop start by timestamp (closest frame) + adjust skipping some samples */ - /* FFmpeg seeks by ts by design (since not all containers can accurately skip to a frame). */ - /* TODO: this seems to be off by +-1 frames in some cases */ - ts = vgmstream->loop_start_sample; - if (ts >= data->sampleRate * 2) { - data->samplesToDiscard = data->sampleRate * 2; - ts -= data->samplesToDiscard; - } - else { - data->samplesToDiscard = (int)ts; - ts = 0; - } - - /* todo fix this properly */ - if (data->totalFrames) { - data->framesRead = (int)ts; - ts = data->framesRead * (data->formatCtx->duration) / data->totalFrames; - } else { - data->samplesToDiscard = vgmstream->loop_start_sample; - data->framesRead = 0; - ts = 0; - } - - avformat_seek_file(data->formatCtx, -1, ts - 1000, ts, ts, AVSEEK_FLAG_ANY); - avcodec_flush_buffers(data->codecCtx); -#endif /* ifndef VGM_USE_FFMPEG_ACCURATE_LOOPING */ - -#ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING - /* Start from 0 and discard samples until loop_start for accurate looping (slower but not too noticeable) */ - /* We could also seek by offset (AVSEEK_FLAG_BYTE) to the frame closest to the loop then discard - * some samples, which is fast but would need calculations per format / when frame size is not constant */ - data->samplesToDiscard = vgmstream->loop_start_sample; - data->framesRead = 0; - ts = 0; - - avformat_seek_file(data->formatCtx, -1, ts, ts, ts, AVSEEK_FLAG_ANY); - avcodec_flush_buffers(data->codecCtx); -#endif /* ifdef VGM_USE_FFMPEG_ACCURATE_LOOPING */ - - data->readNextPacket = 1; - data->bytesConsumedFromDecodedFrame = INT_MAX; - data->endOfStream = 0; - data->endOfAudio = 0; + seek_ffmpeg(vgmstream, vgmstream->loop_start_sample); } #endif /* VGM_USE_FFMPEG */ #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)