Improve handling of recording termination

This change hopefully helps to terminate FFmpeg reliably once a
recording terminates.
This commit is contained in:
0xboobface 2020-04-25 15:15:03 +02:00
parent 3c86310edf
commit d78f96fef6
1 changed files with 15 additions and 8 deletions

View File

@ -42,6 +42,7 @@ import okhttp3.Response;
public class MergedFfmpegHlsDownload extends AbstractHlsDownload { public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(MergedFfmpegHlsDownload.class); private static final Logger LOG = LoggerFactory.getLogger(MergedFfmpegHlsDownload.class);
private static final boolean IGNORE_CACHE = true; private static final boolean IGNORE_CACHE = true;
private ZonedDateTime splitRecStartTime; private ZonedDateTime splitRecStartTime;
@ -95,7 +96,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
// end of playlist reached // end of playlist reached
LOG.debug("Reached end of playlist for model {}", model); LOG.debug("Reached end of playlist for model {}", model);
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Couldn't download segment", e); throw new IOException("Exception while downloading segments", e);
} finally { } finally {
internalStop(); internalStop();
downloadThreadPool.shutdown(); downloadThreadPool.shutdown();
@ -133,6 +134,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
stdout.start(); stdout.start();
stderr.start(); stderr.start();
exitCode = ffmpeg.waitFor(); exitCode = ffmpeg.waitFor();
LOG.debug("FFmpeg exited with code {}", exitCode);
stdout.join(); stdout.join();
stderr.join(); stderr.join();
mergeLogStream.flush(); mergeLogStream.flush();
@ -142,15 +144,18 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
Files.delete(ffmpegLog.toPath()); Files.delete(ffmpegLog.toPath());
} }
} else { } else {
LOG.info("FFmpeg exit code was {}. Logfile: {}", exitCode, ffmpegLog.getAbsolutePath()); if (running) {
throw new ProcessExitedUncleanException("FFmpeg exit code was " + exitCode); LOG.info("FFmpeg exit code was {}. Logfile: {}", exitCode, ffmpegLog.getAbsolutePath());
throw new ProcessExitedUncleanException("FFmpeg exit code was " + exitCode);
}
} }
} catch (IOException | ProcessExitedUncleanException e) { } catch (IOException | ProcessExitedUncleanException e) {
LOG.error("Error in FFMpeg thread", e); LOG.error("Error in FFMpeg thread", e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
LOG.info("Interrupted while waiting for ffmpeg", e); if (running) {
// maybe kill / terminate ffmpeg here?!? LOG.info("Interrupted while waiting for ffmpeg", e);
}
} }
}); });
ffmpegThread.setName("FFmpeg"); ffmpegThread.setName("FFmpeg");
@ -209,7 +214,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
running = false; running = false;
} }
} }
internalStop(); ffmpegThread.interrupt();
} }
private void downloadRecording(SegmentPlaylist lsp) throws IOException { private void downloadRecording(SegmentPlaylist lsp) throws IOException {
@ -365,10 +370,12 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
ffmpegStdIn.close(); ffmpegStdIn.close();
} catch (IOException e) { } catch (IOException e) {
LOG.error("Couldn't terminate FFmpeg by closing stdin", e); LOG.error("Couldn't terminate FFmpeg by closing stdin", e);
} finally {
ffmpeg.destroy();
} }
} }
if (ffmpeg != null && ffmpeg.isAlive()) {
ffmpeg.destroyForcibly();
ffmpeg = null;
}
} }
private class SegmentDownload implements Callable<byte[]> { private class SegmentDownload implements Callable<byte[]> {