LibMedia: Signal EOF to decoders in the data providers

This lets the FFmpeg H.264 decoder know when we've reached the end of
the available data, so that it will output the remaining buffered video
frames.

Not sure why it needs this signal to output the buffered frames, but
surely there's a good reason. :^)
This commit is contained in:
Zaggy1024 2025-11-03 18:40:15 -06:00 committed by Jelle Raaijmakers
parent 0e9c746b48
commit 9037f4e832
Notes: github-actions[bot] 2025-11-05 17:41:03 +00:00
2 changed files with 63 additions and 48 deletions

View file

@ -175,26 +175,32 @@ bool AudioDataProvider::ThreadData::handle_seek()
auto coded_frame_result = m_demuxer->get_next_sample_for_track(m_track);
if (coded_frame_result.is_error()) {
if (coded_frame_result.error().category() == DecoderErrorCategory::EndOfStream) {
resolve_seek(seek_id);
m_decoder->signal_end_of_stream();
} else {
handle_error(coded_frame_result.release_error());
return true;
}
} else {
auto coded_frame = coded_frame_result.release_value();
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
handle_error(decode_result.release_error());
return true;
}
handle_error(coded_frame_result.release_error());
return true;
}
auto coded_frame = coded_frame_result.release_value();
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
handle_error(decode_result.release_error());
return true;
}
while (new_seek_id == seek_id) {
AudioBlock current_block;
auto block_result = m_decoder->write_next_block(current_block);
if (block_result.is_error()) {
if (block_result.error().category() == DecoderErrorCategory::EndOfStream) {
resolve_seek(seek_id);
return true;
}
if (block_result.error().category() == DecoderErrorCategory::NeedsMoreInput)
break;
handle_error(block_result.release_error());
return true;
}
@ -250,19 +256,19 @@ void AudioDataProvider::ThreadData::push_data_and_decode_a_block()
auto sample_result = m_demuxer->get_next_sample_for_track(m_track);
if (sample_result.is_error()) {
if (sample_result.error().category() == DecoderErrorCategory::NeedsMoreInput) {
if (sample_result.error().category() == DecoderErrorCategory::EndOfStream) {
m_decoder->signal_end_of_stream();
} else {
set_error_and_wait_for_seek(sample_result.release_error());
return;
}
} else {
auto sample = sample_result.release_value();
auto decode_result = m_decoder->receive_coded_data(sample.timestamp(), sample.data());
if (decode_result.is_error()) {
set_error_and_wait_for_seek(decode_result.release_error());
return;
}
// FIXME: Handle the end of the stream.
set_error_and_wait_for_seek(sample_result.release_error());
return;
}
auto sample = sample_result.release_value();
auto decode_result = m_decoder->receive_coded_data(sample.timestamp(), sample.data());
if (decode_result.is_error()) {
set_error_and_wait_for_seek(decode_result.release_error());
return;
}
while (true) {

View file

@ -269,35 +269,41 @@ bool VideoDataProvider::ThreadData::handle_seek()
continue;
}
if (last_frame != nullptr)
CONVERT_AND_QUEUE_A_FRAME(last_frame);
resolve_seek(seek_id, timestamp);
m_decoder->signal_end_of_stream();
} else {
handle_error(coded_frame_result.release_error());
return true;
}
handle_error(coded_frame_result.release_error());
return true;
}
} else {
auto coded_frame = coded_frame_result.release_value();
auto coded_frame = coded_frame_result.release_value();
if (!found_desired_keyframe)
found_desired_keyframe = is_desired_coded_frame(coded_frame);
if (!found_desired_keyframe)
found_desired_keyframe = is_desired_coded_frame(coded_frame);
if (!found_desired_keyframe)
continue;
if (!found_desired_keyframe)
continue;
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
handle_error(decode_result.release_error());
return true;
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
handle_error(decode_result.release_error());
return true;
}
}
while (new_seek_id == seek_id) {
auto frame_result = m_decoder->get_decoded_frame();
if (frame_result.is_error()) {
if (frame_result.error().category() == DecoderErrorCategory::EndOfStream) {
if (last_frame != nullptr)
CONVERT_AND_QUEUE_A_FRAME(last_frame);
resolve_seek(seek_id, timestamp);
return true;
}
if (frame_result.error().category() == DecoderErrorCategory::NeedsMoreInput)
break;
handle_error(frame_result.release_error());
return true;
}
@ -360,16 +366,19 @@ void VideoDataProvider::ThreadData::push_data_and_decode_some_frames()
auto sample_result = m_demuxer->get_next_sample_for_track(m_track);
if (sample_result.is_error()) {
// FIXME: Handle the end of the stream.
set_error_and_wait_for_seek(sample_result.release_error());
return;
}
auto coded_frame = sample_result.release_value();
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
set_error_and_wait_for_seek(decode_result.release_error());
return;
if (sample_result.error().category() == DecoderErrorCategory::EndOfStream) {
m_decoder->signal_end_of_stream();
} else {
set_error_and_wait_for_seek(sample_result.release_error());
return;
}
} else {
auto coded_frame = sample_result.release_value();
auto decode_result = m_decoder->receive_coded_data(coded_frame.timestamp(), coded_frame.data());
if (decode_result.is_error()) {
set_error_and_wait_for_seek(decode_result.release_error());
return;
}
}
while (true) {