summaryrefslogtreecommitdiff
path: root/src/lib/subtitle_sync_packet_queue.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2026-04-18 13:39:33 +0200
committerCarl Hetherington <cth@carlh.net>2026-04-23 16:49:48 +0200
commit9f828b327e680c322a70883910233337a37e481e (patch)
treee7fb8e4c3ef3ed6324cc1a9e25fd97af3c8bd5e1 /src/lib/subtitle_sync_packet_queue.cc
parent2666e3232a9520c3b0fa94c48a689880cdde13fc (diff)
Fix late subtitles when they are muxed late with respect to the video.
In one example we have the sequence video 3088,377 sub 3087,334 sub 3088,710 video 3088,419 so the 3087,334 sub is very late. Here we insert a queue to bring subtitle packets a little forward for processing. There is already a similar thing in the player (_delay) but adding a longer delay there seems wasteful because a) the video is by that point already decompressed and b) this problem only applies to FFmpeg-decoded files (and then, I think only if we are previewing or burning in subtitles).
Diffstat (limited to 'src/lib/subtitle_sync_packet_queue.cc')
-rw-r--r--src/lib/subtitle_sync_packet_queue.cc99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/lib/subtitle_sync_packet_queue.cc b/src/lib/subtitle_sync_packet_queue.cc
new file mode 100644
index 000000000..6a96924df
--- /dev/null
+++ b/src/lib/subtitle_sync_packet_queue.cc
@@ -0,0 +1,99 @@
+/*
+ Copyright (C) 2026 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "dcpomatic_log.h"
+#include "subtitle_sync_packet_queue.h"
+extern "C" {
+#include <libavcodec/packet.h>
+#include <libavutil/avutil.h>
+}
+#include <iostream>
+
+
+using boost::optional;
+
+
+void
+SubtitleSyncPacketQueue::add(AVPacket* packet, Type type)
+{
+ switch (type) {
+ case Type::VIDEO:
+ ++_num_video;
+ _other.push_back({packet, type});
+ break;
+ case Type::AUDIO:
+ _other.push_back({packet, type});
+ break;
+ case Type::DROP:
+ _other.push_back({PacketInfo(packet), type});
+ av_packet_free(&packet);
+ break;
+ case Type::SUBTITLE:
+ _subtitle.push_back(packet);
+ break;
+ }
+}
+
+
+optional<std::pair<PacketQueue::Packet, PacketQueue::Type>>
+SubtitleSyncPacketQueue::get(bool flushing)
+{
+ if (!_subtitle.empty()) {
+ /* Any subtitle packets we have get returned first */
+ auto packet = _subtitle.front();
+ _subtitle.pop_front();
+ return std::make_pair(Packet(packet), Type::SUBTITLE);
+ }
+
+ if (_other.size() > 4096) {
+ LOG_WARNING("SubtitleSyncPacketQueue is getting large: {} (_num_video={})", _other.size(), _num_video);
+ }
+
+ if ((!flushing && _num_video < 48 && _other.size() < 8192) || _other.empty()) {
+ /* We haven't queued up enough video yet, or we don't have anything */
+ return boost::none;
+ }
+
+ auto packet = _other.front();
+ if (packet.second == Type::VIDEO) {
+ --_num_video;
+ }
+ _other.pop_front();
+ return packet;
+}
+
+
+void
+SubtitleSyncPacketQueue::clear()
+{
+ for (auto i: _other) {
+ if (auto packet = boost::get<AVPacket*>(&i.first)) {
+ av_packet_free(packet);
+ }
+ }
+ for (auto i: _subtitle) {
+ av_packet_free(&i);
+ }
+ _other.clear();
+ _subtitle.clear();
+ _num_video = 0;
+}
+