DMARC-Filter: OpenDMARC Filter v1.4.2 delorie.com 64SMwBqa2862053
Authentication-Results: delorie.com; dmarc=pass (p=none dis=none) header.from=cygwin.com
Authentication-Results: delorie.com; spf=pass smtp.mailfrom=cygwin.com
DKIM-Filter: OpenDKIM Filter v2.11.0 delorie.com 64SMwBqa2862053
Authentication-Results: delorie.com;
	dkim=pass (1024-bit key, unprotected) header.d=cygwin.com header.i=@cygwin.com header.a=rsa-sha256 header.s=default header.b=Vn/J5HhQ
X-Recipient: archive-cygwin@delorie.com
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EE7FD4BA2E2D
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cygwin.com;
	s=default; t=1780009090;
	bh=hrWbJ58rxakrl6VEWWTBBQZlvfwop1AdGKnxv30R6U8=;
	h=Date:To:Subject:In-Reply-To:References:List-Id:List-Unsubscribe:
	 List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:
	 From;
	b=Vn/J5HhQFtVStYaMVWSkYupmUnTJFg4ujaTSFDedMZkrzCzWWzbYCqgF1MS9GvKd1
	 +rVEEWrHHSCb7F7mgdfKL4yi7S9t5NJ6a9HdiFMNJIFEw7za7ImpT0dbn9Y/agpo46
	 EWfcOzW/bxj0SQgm2NAwvnKFsT9CLMNqB0hZ9aiY=
X-Original-To: cygwin@cygwin.com
Delivered-To: cygwin@cygwin.com
DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 87A954BA2E1B
ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 87A954BA2E1B
ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780009067; cv=none;
 b=mgSPYlqlRf8KvKUctwNgrRU2fCAKwOxoUiAG94UtHKc8gVON9wpavNqQOdpNKfzCZXE78HPAfJC2bp8nY7DdpORp+WSU709bfSTcsmMV69v4xtX1AI5RbTVg6SGdkfO/lzHb7QIh1ghiwbSb8RSfpZLtLqjp6KkMd9DE4SDVY8Y=
ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key;
 t=1780009067; c=relaxed/simple;
 bh=I6k7IKEraSo8uvIuAtxPUxSyXQFeQXQT8vd1Omqk8I0=;
 h=Date:From:To:Subject:Message-Id:Mime-Version:DKIM-Signature;
 b=vbuhYbEkJigmB7dYq4jxfnR4OS7ZDmXzLJJS06i5Cy7wV0CKZRkEGPiE6LeWbSTkVYT0860mywzBBp8vRqd5cFNKzyV7vV5tgkrbH13CQu1blGRQUWKyE6LkEb5PM2wnfit21K8clu41WZbCmwGFfEm6w3350fJcZbfjPnik6bo=
ARC-Authentication-Results: i=1; sourceware.org;
 dkim=pass (2048-bit key, unprotected)
 header.d=nifty.ne.jp header.i=@nifty.ne.jp header.a=rsa-sha256
 header.s=default-1th84yt82rvi header.b=eePTRfcL
DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 87A954BA2E1B
Date: Fri, 29 May 2026 07:57:43 +0900
To: "cygwin@cygwin.com" <cygwin@cygwin.com>
Subject: Re: "Invalid DTS" warnings only in Cygwin version of ffmpeg
Message-Id: <20260529075743.9c2466366921f6171f280ef9@nifty.ne.jp>
In-Reply-To: <PR3PR09MB433011445CBFA2C376E5ECACB0082@PR3PR09MB4330.eurprd09.prod.outlook.com>
References: <PR3PR09MB433011445CBFA2C376E5ECACB0082@PR3PR09MB4330.eurprd09.prod.outlook.com>
X-Mailer: Sylpheed 3.7.0 (GTK+ 2.24.30; i686-pc-mingw32)
Mime-Version: 1.0
Content-Type: multipart/mixed;
 boundary="Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8"
X-BeenThere: cygwin@cygwin.com
X-Mailman-Version: 2.1.30
Precedence: list
List-Id: General Cygwin discussions and problem reports <cygwin.cygwin.com>
List-Unsubscribe: <https://cygwin.com/mailman/options/cygwin>,
 <mailto:cygwin-request@cygwin.com?subject=unsubscribe>
List-Archive: <https://cygwin.com/pipermail/cygwin/>
List-Post: <mailto:cygwin@cygwin.com>
List-Help: <mailto:cygwin-request@cygwin.com?subject=help>
List-Subscribe: <https://cygwin.com/mailman/listinfo/cygwin>,
 <mailto:cygwin-request@cygwin.com?subject=subscribe>
From: Takashi Yano via Cygwin <cygwin@cygwin.com>
Reply-To: Takashi Yano <takashi.yano@nifty.ne.jp>
Errors-To: cygwin-bounces~archive-cygwin=delorie.com@cygwin.com
Sender: "Cygwin" <cygwin-bounces~archive-cygwin=delorie.com@cygwin.com>

This is a multi-part message in MIME format.

--Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

Hi destal,

On Wed, 27 May 2026 06:20:36 +0000
destal takul wrote:
> Thank you for the clarification. Is there any way to fix the files that were remuxed with those warnings, or do I have to remux from the original? I have been using the Cygwin version of ffmpeg to cut the end of videos muxed with mkvmerge on non-key-frames since mkvmerge itself doesn't support this, and I probably have hundreds of files that have been remuxed with such warnings over the course of the past few years.

Sorry for inconvinience.
Could you please try attached tool? This should fix the broken
timestamp.

Usage: fix_ts broken.mkv output.mkv

To compile this, you need libavformat-devel, libavcodec-devel,
and libavutil-deve packages.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

--Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8
Content-Type: text/x-csrc;
 name="fix_ts.c"
Content-Disposition: attachment;
 filename="fix_ts.c"
Content-Transfer-Encoding: 7bit

#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
	int index;
	int display_rank;
} FrameMap;

static int cmp_frame(const void *a, const void *b) {
	return ((FrameMap*)a)->display_rank - ((FrameMap*)b)->display_rank;
}

#define MAX_REORDER_DELAY 16

void cleanup(AVFormatContext *ifmt, AVFormatContext *ofmt,
		AVCodecParserContext *parser, AVCodecContext *codec_ctx,
		FrameMap *map, FrameMap *sorted) {
	if (parser) av_parser_close(parser);
	if (codec_ctx) avcodec_free_context(&codec_ctx);
	if (ifmt) avformat_close_input(&ifmt);
	if (ofmt) {
		if (!(ofmt->oformat->flags & AVFMT_NOFILE)) avio_closep(&ofmt->pb);
		avformat_free_context(ofmt);
	}
	if (map) free(map);
	if (sorted) free(sorted);
}

int main(int argc, char **argv) {
	int ret = 1;
	if (argc < 3) {
		fprintf(stderr, "Usage: %s in.mkv out.mkv\n", argv[0]);
		return 1;
	}

	AVFormatContext *ifmt = NULL, *ofmt = NULL;
	AVCodecParserContext *parser = NULL;
	AVCodecContext *codec_ctx = NULL;
	FrameMap *map = NULL, *sorted = NULL;
	int frame_count = 0, frame_cap = 10000;

	if (avformat_open_input(&ifmt, argv[1], NULL, NULL) < 0) {
		fprintf(stderr, "avformat_open_input() failed.\n");
		goto end;
	}
	if (avformat_find_stream_info(ifmt, NULL) < 0) {
		fprintf(stderr, "avformat_find_stream_info() failed.\n");
		goto end;
	}

	int video_index = -1;
	for (unsigned i = 0; i < ifmt->nb_streams; i++)
		if (ifmt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
			video_index = i;

	parser = av_parser_init(AV_CODEC_ID_H264);
	codec_ctx = avcodec_alloc_context3(NULL);
	avcodec_parameters_to_context(codec_ctx,
			ifmt->streams[video_index]->codecpar);

	map = malloc(frame_cap * sizeof(FrameMap));
	AVPacket pkt;
	uint64_t pict_num_msb = 0;
	int prev_pict_num = -1;

	while (av_read_frame(ifmt, &pkt) >= 0) {
		if (pkt.stream_index == video_index) {
			if (frame_count >= frame_cap) {
				frame_cap *= 2;
				map = realloc(map, frame_cap * sizeof(FrameMap));
			}
			uint8_t *data; int size;
			av_parser_parse2(parser, codec_ctx, &data, &size,
					pkt.data, pkt.size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
			if (prev_pict_num >= 0 &&
					parser->output_picture_number - prev_pict_num
					< -MAX_REORDER_DELAY)
				pict_num_msb++;
			map[frame_count] =
				(FrameMap){frame_count, parser->output_picture_number
					+ (int)(pict_num_msb * 1024)};
			prev_pict_num = parser->output_picture_number;
			frame_count++;
		}
		av_packet_unref(&pkt);
	}

	sorted = malloc(frame_count * sizeof(FrameMap));
	memcpy(sorted, map, frame_count * sizeof(FrameMap));
	qsort(sorted, frame_count, sizeof(FrameMap), cmp_frame);
	for (int i = 0; i < frame_count; i++)
		map[sorted[i].index].display_rank = i;

	if (avformat_alloc_output_context2(&ofmt, NULL, NULL, argv[2]) != 0) {
		fprintf(stderr, "avformat_alloc_output_context2() failed.\n");
		goto end;
	}
	for (unsigned i = 0; i < ifmt->nb_streams; i++) {
		AVStream *out_st = avformat_new_stream(ofmt, NULL);
		avcodec_parameters_copy(out_st->codecpar, ifmt->streams[i]->codecpar);
	}

	AVStream *in_st = ifmt->streams[video_index];

	if (!(ofmt->oformat->flags & AVFMT_NOFILE))
		avio_open(&ofmt->pb, argv[2], AVIO_FLAG_WRITE);
	if (avformat_write_header(ofmt, NULL) < 0) {
		fprintf(stderr, "avformat_write_header() failed.\n");
		goto end;
	}

	AVRational out_tb = ofmt->streams[video_index]->time_base;

	AVRational frame_rate = in_st->avg_frame_rate;
	if (frame_rate.num == 0)
		frame_rate = in_st->r_frame_rate;

	av_seek_frame(ifmt, video_index, 0, AVSEEK_FLAG_BACKWARD);
	int current = 0;
	while (av_read_frame(ifmt, &pkt) >= 0) {
		if (pkt.stream_index == video_index) {
			pkt.pts = av_rescale_q(map[current].display_rank,
					av_inv_q(frame_rate), out_tb);
			pkt.dts = av_rescale_q(current - MAX_REORDER_DELAY,
					av_inv_q(frame_rate), out_tb);
			pkt.duration = av_rescale_q(1, av_inv_q(frame_rate), out_tb);
			current++;
		}
		if (ifmt->streams[pkt.stream_index]->codecpar->codec_type
				== AVMEDIA_TYPE_AUDIO)
			av_packet_rescale_ts(&pkt,
					ifmt->streams[pkt.stream_index]->time_base,
					ofmt->streams[pkt.stream_index]->time_base);
		av_interleaved_write_frame(ofmt, &pkt);
		av_packet_unref(&pkt);
	}
	av_write_trailer(ofmt);
	ret = 0;

end:
	cleanup(ifmt, ofmt, parser, codec_ctx, map, sorted);
	return ret;
}

--Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8
Content-Type: text/plain;
 name="Makefile"
Content-Disposition: attachment;
 filename="Makefile"
Content-Transfer-Encoding: base64

Zml4X3RzOiBmaXhfdHMuYw0KCSQoQ0MpICQ8IC1vICRAIC1sYXZmb3JtYXQgLWxhdmNvZGVjIC1s
YXZ1dGlsDQoNCmNsZWFuOg0KCSQoUk0pIGZpeF90cw0K

--Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline


-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

--Multipart=_Fri__29_May_2026_07_57_43_+0900_E78XSD=eOhsy1bz8--
