mirror of https://github.com/godotengine/godot
Don't start decoding video before keyframe
This commit is contained in:
parent
8e7b47840f
commit
69baa6de16
|
|
@ -214,14 +214,14 @@ int64_t VideoStreamPlaybackTheora::seek_streams(double p_time, int64_t &cur_vide
|
||||||
audio_catch = cur_audio_granulepos != -1;
|
audio_catch = cur_audio_granulepos != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_video_granulepos == -1) {
|
if (cur_video_granulepos < (1LL << ti.keyframe_granule_shift)) {
|
||||||
video_seek_pos = stream_data_offset;
|
video_seek_pos = stream_data_offset;
|
||||||
cur_video_granulepos = 1LL << ti.keyframe_granule_shift;
|
cur_video_granulepos = 1LL << ti.keyframe_granule_shift;
|
||||||
}
|
}
|
||||||
if (has_audio) {
|
if (has_audio) {
|
||||||
if (cur_audio_granulepos == -1) {
|
if (cur_audio_granulepos == -1) {
|
||||||
audio_seek_pos = stream_data_offset;
|
audio_seek_pos = stream_data_offset;
|
||||||
cur_audio_granulepos = 1LL << ti.keyframe_granule_shift;
|
cur_audio_granulepos = 0;
|
||||||
}
|
}
|
||||||
seek_pos = MIN(video_seek_pos, audio_seek_pos);
|
seek_pos = MIN(video_seek_pos, audio_seek_pos);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -682,15 +682,13 @@ void VideoStreamPlaybackTheora::seek(double p_time) {
|
||||||
|
|
||||||
time = p_time;
|
time = p_time;
|
||||||
|
|
||||||
// We need to reset video granulepos in case decoding has to start from the beginning.
|
|
||||||
int64_t granulepos = 0;
|
|
||||||
th_decode_ctl(td, TH_DECCTL_SET_GRANPOS, &granulepos, sizeof(granulepos));
|
|
||||||
|
|
||||||
double last_audio_time = 0;
|
double last_audio_time = 0;
|
||||||
double last_video_time = 0;
|
double last_video_time = 0;
|
||||||
bool first_frame_decoded = false;
|
bool first_frame_decoded = false;
|
||||||
bool start_audio = false;
|
bool start_audio = false;
|
||||||
bool start_video = false;
|
bool start_video = false;
|
||||||
|
bool keyframe_found = false;
|
||||||
|
uint64_t current_frame = 0;
|
||||||
// Read from the streams skipping pages until we reach the granules we want. We won't skip pages from both video and
|
// Read from the streams skipping pages until we reach the granules we want. We won't skip pages from both video and
|
||||||
// audio streams, only one of them, until decoding of both starts.
|
// audio streams, only one of them, until decoding of both starts.
|
||||||
// video_granulepos and audio_granulepos are guaranteed to be found by checking the granulepos in the packets, no
|
// video_granulepos and audio_granulepos are guaranteed to be found by checking the granulepos in the packets, no
|
||||||
|
|
@ -722,15 +720,27 @@ void VideoStreamPlaybackTheora::seek(double p_time) {
|
||||||
}
|
}
|
||||||
while (last_video_time <= p_time && ogg_stream_packetout(&to, &op) > 0) {
|
while (last_video_time <= p_time && ogg_stream_packetout(&to, &op) > 0) {
|
||||||
if (!start_video && (op.granulepos >= video_granulepos || video_granulepos == (1LL << ti.keyframe_granule_shift))) {
|
if (!start_video && (op.granulepos >= video_granulepos || video_granulepos == (1LL << ti.keyframe_granule_shift))) {
|
||||||
|
if (op.granulepos > 0) {
|
||||||
|
current_frame = th_granule_frame(td, op.granulepos);
|
||||||
|
}
|
||||||
start_video = true;
|
start_video = true;
|
||||||
th_decode_ctl(td, TH_DECCTL_SET_GRANPOS, &op.granulepos, sizeof(op.granulepos));
|
|
||||||
}
|
}
|
||||||
|
// Don't start decoding until a keyframe is found, but count frames.
|
||||||
if (start_video) {
|
if (start_video) {
|
||||||
int64_t videobuf_granulepos;
|
if (!keyframe_found && th_packet_iskeyframe(&op)) {
|
||||||
int ret = th_decode_packetin(td, &op, &videobuf_granulepos);
|
keyframe_found = true;
|
||||||
if (ret == 0 || ret == TH_DUPFRAME) {
|
int64_t cur_granulepos = (current_frame + 1) << ti.keyframe_granule_shift;
|
||||||
last_video_time = th_granule_time(td, videobuf_granulepos);
|
th_decode_ctl(td, TH_DECCTL_SET_GRANPOS, &cur_granulepos, sizeof(cur_granulepos));
|
||||||
first_frame_decoded = true;
|
}
|
||||||
|
if (keyframe_found) {
|
||||||
|
int64_t videobuf_granulepos;
|
||||||
|
int ret = th_decode_packetin(td, &op, &videobuf_granulepos);
|
||||||
|
if (ret == 0 || ret == TH_DUPFRAME) {
|
||||||
|
last_video_time = th_granule_time(td, videobuf_granulepos);
|
||||||
|
first_frame_decoded = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current_frame++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue