X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=mux.cpp;fp=mux.cpp;h=aec124b34aea7be5f5c5de7e9ec36a2eb86b0980;hb=db03cd080a4b38d76b85d3acf88a1bac0e84e734;hp=326c73f69cf2e4be34004bb209359a0751b838c4;hpb=dd64578c19aace6c4a946af40a5716c716f20ce9;p=nageru diff --git a/mux.cpp b/mux.cpp index 326c73f..aec124b 100644 --- a/mux.cpp +++ b/mux.cpp @@ -118,26 +118,57 @@ void Mux::add_packet(const AVPacket &pkt, int64_t pts, int64_t dts) assert(false); } - if (keyframe_signal_receiver) { - if (pkt.flags & AV_PKT_FLAG_KEY) { - av_write_frame(avctx, nullptr); - keyframe_signal_receiver->signal_keyframe(); - } - } - { lock_guard lock(mu); if (plug_count > 0) { plugged_packets.push_back(av_packet_clone(&pkt_copy)); - } else if (av_interleaved_write_frame(avctx, &pkt_copy) < 0) { - fprintf(stderr, "av_interleaved_write_frame() failed\n"); - exit(1); + } else { + add_interleaved_packet(pkt_copy); } } av_packet_unref(&pkt_copy); } +void Mux::add_interleaved_packet(const AVPacket &pkt) +{ + if (waiting_packets.empty() || waiting_packets.front()->stream_index == pkt.stream_index) { + // We could still get packets of the other type with earlier pts/dts, + // so we'll have to queue and wait. + waiting_packets.push(av_packet_clone(const_cast(&pkt))); + return; + } + + // Flush all the queued packets that are supposed to go before this. + PacketBefore before(avctx); + while (!waiting_packets.empty() && !before(&pkt, waiting_packets.front())) { + AVPacket *queued_pkt = waiting_packets.front(); + waiting_packets.pop(); + write_packet_with_signal(*queued_pkt); + av_packet_unref(queued_pkt); + } + + if (waiting_packets.empty()) { + waiting_packets.push(av_packet_clone(const_cast(&pkt))); + } else { + write_packet_with_signal(pkt); + } +} + +void Mux::write_packet_with_signal(const AVPacket &pkt) +{ + if (keyframe_signal_receiver) { + if (pkt.flags & AV_PKT_FLAG_KEY) { + av_write_frame(avctx, nullptr); + keyframe_signal_receiver->signal_keyframe(); + } + } + if (av_write_frame(avctx, const_cast(&pkt)) < 0) { + fprintf(stderr, "av_interleaved_write_frame() failed\n"); + exit(1); + } +} + void Mux::plug() { lock_guard lock(mu); @@ -155,10 +186,7 @@ void Mux::unplug() sort(plugged_packets.begin(), plugged_packets.end(), PacketBefore(avctx)); for (AVPacket *pkt : plugged_packets) { - if (av_interleaved_write_frame(avctx, pkt) < 0) { - fprintf(stderr, "av_interleaved_write_frame() failed\n"); - exit(1); - } + add_interleaved_packet(*pkt); av_packet_free(&pkt); } plugged_packets.clear();