vcap/file: fix raw HEVC rewinding

Rewinding the file (:loop option) doesn't work using raw HEVC like with
the [file].

avformat_seek_file retrurns EPERM, which was handled as an error, so
stopped the worker.

avio_seek seems to do the job but must be performed _after_ (unsuccessful)
avformat_seek_file.

[file]:
https://ultravideo.fi/video/ReadySetGo_3840x2160_120fps_420_8bit_HEVC_RAW.hevc
This commit is contained in:
Martin Pulec
2025-10-01 11:05:59 +02:00
parent 1f1505ab12
commit 9891f19a71

View File

@@ -465,6 +465,19 @@ static void print_packet_info(const AVPacket *pkt, const AVStream *st) {
pts_val, dts_val, pkt->duration, tb.num, tb.den, pkt->size);
}
static void
rewind_file(struct vidcap_state_lavf_decoder *s)
{
CHECK_FF(avformat_seek_file(s->fmt_ctx, -1, INT64_MIN,
s->fmt_ctx->start_time, INT64_MAX, 0),
{});
// handle single JPEG loop, inspired by libavformat's seek_frame_generic
// because img_read_seek (AVInputFormat::read_seek) doesn't do the job -
// seeking is inmplemeted just in img2dec if VideoDemuxData::loop == 1
CHECK_FF(avio_seek(s->fmt_ctx->pb, s->video_stream_idx, SEEK_SET), {});
flush_captured_data(s);
}
#define FAIL_WORKER { pthread_mutex_lock(&s->lock); s->failed = true; pthread_mutex_unlock(&s->lock); pthread_cond_signal(&s->new_frame_ready); return NULL; }
static void *vidcap_file_worker(void *state) {
set_thread_name(__func__);
@@ -497,9 +510,7 @@ static void *vidcap_file_worker(void *state) {
int ret = av_read_frame(s->fmt_ctx, pkt);
if (ret == AVERROR_EOF) {
if (s->loop) {
CHECK_FF(avio_seek(s->fmt_ctx->pb, s->video_stream_idx, SEEK_SET), {}); // handle single JPEG loop, inspired by libavformat's seek_frame_generic because img_read_seek (AVInputFormat::read_seek) doesn't do the job - seeking is inmplemeted just in img2dec if VideoDemuxData::loop == 1
CHECK_FF(avformat_seek_file(s->fmt_ctx, -1, INT64_MIN, s->fmt_ctx->start_time, INT64_MAX, 0), FAIL_WORKER);
flush_captured_data(s);
rewind_file(s);
log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Rewinding the file.\n");
continue;
} else {