Update VGMStream so its FFmpeg component performs loop pre-roll, since FFmpeg itself doesn't seem to do this. Now loops should be as seamless as they were intended.
parent
e4f3d02473
commit
9c9f8952d3
|
@ -178,6 +178,21 @@ void decode_ffmpeg(VGMSTREAM *vgmstream,
|
||||||
|
|
||||||
toConsume = FFMIN((dataSize - bytesConsumedFromDecodedFrame), (bytesToRead - bytesRead));
|
toConsume = FFMIN((dataSize - bytesConsumedFromDecodedFrame), (bytesToRead - bytesRead));
|
||||||
|
|
||||||
|
if (data->samplesToDiscard) {
|
||||||
|
int bytesPerFrame = ((data->bitsPerSample / 8) * channels);
|
||||||
|
int samplesToConsume = toConsume / bytesPerFrame;
|
||||||
|
if (data->samplesToDiscard >= samplesToConsume) {
|
||||||
|
data->samplesToDiscard -= samplesToConsume;
|
||||||
|
bytesConsumedFromDecodedFrame = dataSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bytesConsumedFromDecodedFrame += data->samplesToDiscard * bytesPerFrame;
|
||||||
|
toConsume -= data->samplesToDiscard * bytesPerFrame;
|
||||||
|
data->samplesToDiscard = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!planar || channels == 1) {
|
if (!planar || channels == 1) {
|
||||||
memmove(targetBuf + bytesRead, (lastDecodedFrame->data[0] + bytesConsumedFromDecodedFrame), toConsume);
|
memmove(targetBuf + bytesRead, (lastDecodedFrame->data[0] + bytesConsumedFromDecodedFrame), toConsume);
|
||||||
}
|
}
|
||||||
|
|
|
@ -520,6 +520,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||||
data->framesRead = 0;
|
data->framesRead = 0;
|
||||||
data->endOfStream = 0;
|
data->endOfStream = 0;
|
||||||
data->endOfAudio = 0;
|
data->endOfAudio = 0;
|
||||||
|
data->samplesToDiscard = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1782,7 +1783,16 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) {
|
||||||
if (vgmstream->coding_type==coding_FFmpeg) {
|
if (vgmstream->coding_type==coding_FFmpeg) {
|
||||||
ffmpeg_codec_data *data = (ffmpeg_codec_data *)(vgmstream->codec_data);
|
ffmpeg_codec_data *data = (ffmpeg_codec_data *)(vgmstream->codec_data);
|
||||||
int64_t ts;
|
int64_t ts;
|
||||||
data->framesRead = vgmstream->loop_start_sample;
|
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;
|
||||||
|
}
|
||||||
|
data->framesRead = (int)ts;
|
||||||
ts = data->framesRead * (data->formatCtx->duration) / data->totalFrames;
|
ts = data->framesRead * (data->formatCtx->duration) / data->totalFrames;
|
||||||
avformat_seek_file(data->formatCtx, -1, ts - 1000, ts, ts, AVSEEK_FLAG_ANY);
|
avformat_seek_file(data->formatCtx, -1, ts - 1000, ts, ts, AVSEEK_FLAG_ANY);
|
||||||
avcodec_flush_buffers(data->codecCtx);
|
avcodec_flush_buffers(data->codecCtx);
|
||||||
|
|
|
@ -897,6 +897,9 @@ typedef struct {
|
||||||
int readNextPacket;
|
int readNextPacket;
|
||||||
int endOfStream;
|
int endOfStream;
|
||||||
int endOfAudio;
|
int endOfAudio;
|
||||||
|
|
||||||
|
// Seeking is not ideal, so rollback is necessary
|
||||||
|
int samplesToDiscard;
|
||||||
} ffmpeg_codec_data;
|
} ffmpeg_codec_data;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue