Fix guide misalignment

This commit is contained in:
markmental 2026-03-28 10:56:27 -04:00
commit 8890d7f527
10 changed files with 167 additions and 33 deletions

View file

@ -419,6 +419,80 @@ static int decode_context_open(DecodeContext *ctx, const ProgramEntry *program,
return 0;
}
static int decode_context_seek_to_seconds(DecodeContext *ctx, double seek_seconds) {
int64_t seek_target;
if (!ctx || seek_seconds <= 0.0 || !ctx->format_context || ctx->video_stream_index < 0) {
return 0;
}
seek_target = (int64_t) (seek_seconds / av_q2d(ctx->video_time_base));
if (avformat_seek_file(ctx->format_context, ctx->video_stream_index, INT64_MIN, seek_target, INT64_MAX, 0) < 0) {
return -1;
}
avcodec_flush_buffers(ctx->video_codec_context);
if (ctx->audio_codec_context) {
avcodec_flush_buffers(ctx->audio_codec_context);
}
return 0;
}
static int decode_context_sync_to_schedule(Player *player,
const Channel *channel,
DecodeContext *ctx,
const ProgramEntry **program,
int *current_program_index,
double *seek_seconds,
int force_reopen,
int *queued_any_audio,
int *queued_first_video) {
const ProgramEntry *scheduled_program;
int scheduled_program_index = -1;
double scheduled_seek_seconds = 0.0;
if (!player || !channel || !ctx || !program || !current_program_index || !seek_seconds) {
return -1;
}
scheduled_program = channel_resolve_program(channel,
player->app_start_ticks,
SDL_GetTicks64(),
&scheduled_seek_seconds,
&scheduled_program_index);
if (!scheduled_program) {
return -1;
}
if (!force_reopen && *program == scheduled_program && *current_program_index == scheduled_program_index) {
*seek_seconds = scheduled_seek_seconds;
return 0;
}
if (decode_context_open(ctx, scheduled_program, player) != 0) {
return -1;
}
if (decode_context_seek_to_seconds(ctx, scheduled_seek_seconds) != 0) {
player_set_error(player, "Unable to seek to scheduled program position");
return -1;
}
frame_queue_clear(&player->frame_queue);
player_clear_audio(player);
*program = scheduled_program;
*current_program_index = scheduled_program_index;
*seek_seconds = scheduled_seek_seconds;
if (queued_any_audio) {
*queued_any_audio = 0;
}
if (queued_first_video) {
*queued_first_video = 0;
}
return 0;
}
static int decode_thread_main(void *userdata) {
DecoderThreadArgs *args = (DecoderThreadArgs *) userdata;
Player *player = args->player;
@ -438,29 +512,42 @@ static int decode_thread_main(void *userdata) {
ctx.audio_stream_index = -1;
free(args);
program = channel_resolve_program(channel, player->app_start_ticks, SDL_GetTicks64(), &seek_seconds, &current_program_index);
if (!program || decode_context_open(&ctx, program, player) != 0) {
if (decode_context_sync_to_schedule(player,
channel,
&ctx,
&program,
&current_program_index,
&seek_seconds,
1,
&queued_any_audio,
&queued_first_video) != 0) {
decode_context_reset(&ctx);
return -1;
}
if (seek_seconds > 0.0) {
int64_t seek_target = (int64_t) (seek_seconds / av_q2d(ctx.video_time_base));
avformat_seek_file(ctx.format_context, ctx.video_stream_index, INT64_MIN, seek_target, INT64_MAX, 0);
avcodec_flush_buffers(ctx.video_codec_context);
if (ctx.audio_codec_context) {
avcodec_flush_buffers(ctx.audio_codec_context);
}
}
player_clear_audio(player);
while (!should_stop(player)) {
if (decode_context_sync_to_schedule(player,
channel,
&ctx,
&program,
&current_program_index,
&seek_seconds,
0,
&queued_any_audio,
&queued_first_video) != 0) {
goto cleanup;
}
if (av_read_frame(ctx.format_context, ctx.packet) < 0) {
current_program_index = (current_program_index + 1) % channel->program_count;
program = channel_program_at_index(channel, current_program_index);
queued_any_audio = 0;
queued_first_video = 0;
if (!program || decode_context_open(&ctx, program, player) != 0) {
if (decode_context_sync_to_schedule(player,
channel,
&ctx,
&program,
&current_program_index,
&seek_seconds,
1,
&queued_any_audio,
&queued_first_video) != 0) {
goto cleanup;
}
continue;