Add rollback to FFmpeg loop seeking, since FFmpeg doesn't seem to institute any rollback of its own.

This commit is contained in:
Christopher Snowhill 2016-08-14 15:18:34 -07:00
parent c4c7ec55bf
commit 42c00f304b
3 changed files with 29 additions and 1 deletions

View File

@ -178,6 +178,21 @@ void decode_ffmpeg(VGMSTREAM *vgmstream,
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) {
memmove(targetBuf + bytesRead, (lastDecodedFrame->data[0] + bytesConsumedFromDecodedFrame), toConsume);
}

View File

@ -520,6 +520,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
data->framesRead = 0;
data->endOfStream = 0;
data->endOfAudio = 0;
data->samplesToDiscard = 0;
}
#endif
@ -1782,7 +1783,16 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) {
if (vgmstream->coding_type==coding_FFmpeg) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *)(vgmstream->codec_data);
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;
avformat_seek_file(data->formatCtx, -1, ts - 1000, ts, ts, AVSEEK_FLAG_ANY);
avcodec_flush_buffers(data->codecCtx);

View File

@ -884,6 +884,9 @@ typedef struct {
int readNextPacket;
int endOfStream;
int endOfAudio;
// Seeking is not ideal, so rollback is necessary
int samplesToDiscard;
} ffmpeg_codec_data;
#endif