--- translate.c with 2016_opus_plc.patch (Debian)
+++ translate.c with the revised patch
@@ -620,6 +620,13 @@
 	return ast_frdup(&res);
 }
 
+/*!
+ * \brief Largest RTP seqno gap concealed as lost packets, and the most a late
+ * packet may lag behind and still be dropped as late. A larger jump either way
+ * starts a new stream, e.g. after an SSRC change. 50 = 1 s of 20 ms packets.
+ */
+#define PLC_MAX_SEQNO_GAP 50
+
 /*! \brief do the actual translation */
 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 {
@@ -635,14 +642,19 @@
 	/* Determine the amount of lost packets for PLC */
 	/* But not at start with first frame = path->f.seqno is still 0x10000 */
 	/* But not when there is no sequence number = frame created internally */
-	if ((path->f.seqno <= rtp_seqno_max_value) && (path->f.seqno != f->seqno)) {
-		if (f->seqno < path->f.seqno) { /* seqno overrun situation */
-			frames_missing = rtp_seqno_max_value + f->seqno - path->f.seqno - 1;
-		} else {
-			frames_missing = f->seqno - path->f.seqno - 1;
-		}
-		/* Out-of-order packet - more precise: late packet */
-		if ((rtp_seqno_max_value + 1) / 2 < frames_missing) {
+	/* But only if the decoder conceals lost frames itself = native PLC */
+	if (path->t->native_plc && (path->f.seqno <= rtp_seqno_max_value) && (path->f.seqno != f->seqno)) {
+		/* Distance from the previous frame, modulo 2^16: 1 = the next one */
+		unsigned int seqno_step = (f->seqno - path->f.seqno) & rtp_seqno_max_value;
+
+		if (seqno_step && seqno_step <= PLC_MAX_SEQNO_GAP + 1) {
+			frames_missing = seqno_step - 1;
+			if (frames_missing) {
+				ast_debug(3, "%d lost frame(s) before seqno %d\n", frames_missing, f->seqno);
+			}
+		} else if (seqno_step >= rtp_seqno_max_value + 1 - PLC_MAX_SEQNO_GAP) {
+			/* Out-of-order packet - more precise: late packet */
+			ast_debug(3, "Late frame seqno %d after %d dropped\n", f->seqno, path->f.seqno);
 			if (consume) {
 				ast_frfree(f);
 			}
@@ -652,14 +664,14 @@
 			 * the next packet, this one is going to be treated as lost packet.
 			 */
 			return NULL;
-		}
-
-		if (frames_missing > 96) {
-			struct ast_str *str = ast_str_alloca(256);
-
-			/* disabled by default to not flood log in production even in non-Opus use
-			/* not DEBUG but NOTICE because of WARNING in main/channel.c:__ast_queue_frame */
-			//ast_log(LOG_NOTICE, "%d lost frame(s) %d/%d %s\n", frames_missing, f->seqno, path->f.seqno, ast_translate_path_to_str(path, &str));
+		} else {
+			/*
+			 * Too far off for loss or reordering: a new RTP stream (another
+			 * SSRC, a restarted sender). Continue with its numbering; there is
+			 * nothing to conceal and no frame is late.
+			 */
+			ast_debug(1, "Seqno jumped from %d to %d, new stream\n", path->f.seqno, f->seqno);
+			frames_missing = 0;
 		}
 	} else {
 		frames_missing = 0;
