]> git.sesse.net Git - nageru/blobdiff - nageru/ffmpeg_capture.cpp
Add a failsafe for interrupted FFmpeg streams.
[nageru] / nageru / ffmpeg_capture.cpp
index 8f15973ba7eba8fc5d05d21268b873140023655a..722d313da4d65cdc6efb3c0fab692d70fb763cf5 100644 (file)
@@ -394,6 +394,8 @@ bool FFmpegCapture::play_video(const string &pathname)
        }
 
        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;
@@ -449,13 +451,17 @@ bool FFmpegCapture::play_video(const string &pathname)
                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;
                }
@@ -636,7 +642,7 @@ namespace {
 }  // 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;
@@ -672,6 +678,9 @@ AVFrameWithDeleter FFmpegCapture::decode_frame(AVFormatContext *format_ctx, AVCo
                                        *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.