}
int audio_stream_index = find_stream_index(format_ctx.get(), AVMEDIA_TYPE_AUDIO);
+ int subtitle_stream_index = find_stream_index(format_ctx.get(), AVMEDIA_TYPE_SUBTITLE);
+ has_last_subtitle = false;
// Open video decoder.
const AVCodecParameters *video_codecpar = format_ctx->streams[video_stream_index]->codecpar;
if (process_queued_commands(format_ctx.get(), pathname, last_modified, /*rewound=*/nullptr)) {
return true;
}
+ if (should_interrupt.load()) {
+ // Check as a failsafe, so that we don't need to rely on avio if we don't have to.
+ return false;
+ }
UniqueFrame audio_frame = audio_frame_allocator->alloc_frame();
AudioFormat audio_format;
int64_t audio_pts;
bool error;
AVFrameWithDeleter frame = decode_frame(format_ctx.get(), video_codec_ctx.get(), audio_codec_ctx.get(),
- pathname, video_stream_index, audio_stream_index, audio_frame.get(), &audio_format, &audio_pts, &error);
+ pathname, video_stream_index, audio_stream_index, subtitle_stream_index, audio_frame.get(), &audio_format, &audio_pts, &error);
if (error) {
return false;
}
if (frame == nullptr) {
// EOF. Loop back to the start if we can.
+ if (format_ctx->pb != nullptr && format_ctx->pb->seekable == 0) {
+ // Not seekable (but seemingly, sometimes av_seek_frame() would return 0 anyway,
+ // so don't try).
+ return true;
+ }
if (av_seek_frame(format_ctx.get(), /*stream_index=*/-1, /*timestamp=*/0, /*flags=*/0) < 0) {
fprintf(stderr, "%s: Rewind failed, not looping.\n", pathname.c_str());
return true;
} // namespace
AVFrameWithDeleter FFmpegCapture::decode_frame(AVFormatContext *format_ctx, AVCodecContext *video_codec_ctx, AVCodecContext *audio_codec_ctx,
- const std::string &pathname, int video_stream_index, int audio_stream_index,
+ const std::string &pathname, int video_stream_index, int audio_stream_index, int subtitle_stream_index,
FrameAllocator::Frame *audio_frame, AudioFormat *audio_format, int64_t *audio_pts, bool *error)
{
*error = false;
*error = true;
return AVFrameWithDeleter(nullptr);
}
+ } else if (pkt.stream_index == subtitle_stream_index) {
+ last_subtitle = string(reinterpret_cast<const char *>(pkt.data), pkt.size);
+ has_last_subtitle = true;
}
} else {
eof = true; // Or error, but ignore that for the time being.