[FIX] Use fixed-width format specifiers for 64-bit values (#2337)

X-TIMESTAMP-MAP emitted a truncated MPEGTS value on every Windows build.
sync_pts2fts_pts is LLONG (int64_t) but was printed with %ld, and long is
32 bits on Windows (LLP64 on x64, ILP32 on Win32). A 90kHz PTS of 2^33
printed as "MPEGTS:0"; 2^31 printed as "MPEGTS:-2147483648". On Win32 the
argument slots also desynchronise, so the trailing %s reads the PTS high
dword as a char *. HLS players use this field to anchor a WebVTT segment
to the transport clock, so the result is caption desync.

Linux and macOS are LP64, where long is 64 bits and %ld happens to be
correct, which is why this went unnoticed. For the same reason %lld would
be wrong there, since int64_t is long on LP64. Use the <inttypes.h> macros
instead, which are correct on every target and already used elsewhere in
the tree; ccx_common_platform.h already includes <inttypes.h>.

The same defect class appears at 22 sites across 10 files. They are
invisible to the build because mprint() and dbg_print() carry no
format(printf) attribute, so the compiler never checks those call sites.
Adding the attributes locally surfaced all of them; this commit fixes them
with PRId64/PRIu64/PRIx64 for fixed-width types, %zu for size_t, and an
explicit (long long) cast for pointer differences.

Also fixes ts_readpacket() printing payload->start, an unsigned char *,
under the label "PES start". The intended field is payload->pesstart; the
pointer was truncated to int and shifted the three arguments after it, so
counter, payload length and adapt length were all wrong in the trace.

Output on Linux and macOS is byte-identical before and after. No
signature, struct, option or output-format change.

Refs #2336
This commit is contained in:
pranayr710
2026-09-13 04:11:21 +05:30
committed by GitHub
parent 683bb39d4b
commit cb421dbec6
8 changed files with 24 additions and 24 deletions

View File

@@ -122,8 +122,8 @@ void do_NAL(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned
NAL_stop = remove_03emu(NAL_start + nal_header_size, NAL_stop);
payload_start = NAL_start + nal_header_size;
dvprint("BEGIN NAL unit type: %d length %d ref_idc: %d - Buffered captions before: %d (HEVC: %d)\n",
nal_unit_type, NAL_stop - NAL_start - nal_header_size, dec_ctx->avc_ctx->nal_ref_idc,
dvprint("BEGIN NAL unit type: %d length %lld ref_idc: %d - Buffered captions before: %d (HEVC: %d)\n",
nal_unit_type, (long long)(NAL_stop - NAL_start - nal_header_size), dec_ctx->avc_ctx->nal_ref_idc,
!dec_ctx->avc_ctx->cc_buffer_saved, dec_ctx->avc_ctx->is_hevc);
if (NAL_stop == NULL) // remove_03emu failed.
@@ -188,8 +188,8 @@ void do_NAL(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, unsigned
dump(CCX_DMT_VIDES, payload_start, len > 160 ? 160 : len, 0, 0);
}
dvprint("END NAL unit type: %d length %d ref_idc: %d - Buffered captions after: %d\n",
nal_unit_type, NAL_stop - NAL_start - nal_header_size, dec_ctx->avc_ctx->nal_ref_idc, !dec_ctx->avc_ctx->cc_buffer_saved);
dvprint("END NAL unit type: %d length %lld ref_idc: %d - Buffered captions after: %d\n",
nal_unit_type, (long long)(NAL_stop - NAL_start - nal_header_size), dec_ctx->avc_ctx->nal_ref_idc, !dec_ctx->avc_ctx->cc_buffer_saved);
}
// Process inbuf bytes in buffer holding and AVC (H.264) video stream.
@@ -775,7 +775,7 @@ void seq_parameter_set_rbsp(struct avc_ctx *ctx, unsigned char *seqbuf, unsigned
for (int i = 0; i < num_ref_frame_in_pic_order_cnt_cycle; i++)
{
tmp = read_exp_golomb(&q1);
dvprint("offset_for_ref_frame [%d / %d] = % 4lld (%#llX)\n", i, num_ref_frame_in_pic_order_cnt_cycle, tmp, tmp);
dvprint("offset_for_ref_frame [%d / %" PRId64 "] = % 4lld (%#llX)\n", i, num_ref_frame_in_pic_order_cnt_cycle, tmp, tmp);
}
}
else

View File

@@ -222,7 +222,7 @@ void write_webvtt_header(struct encoder_ctx *context)
// If the user has enabled X-TIMESTAMP-MAP
// LOCAL must come before MPEGTS for HLS compatibility (issue #1743)
snprintf(header_string, sizeof(header_string), "X-TIMESTAMP-MAP=LOCAL:%02u:%02u:%02u.%03u,MPEGTS:%ld%s",
snprintf(header_string, sizeof(header_string), "X-TIMESTAMP-MAP=LOCAL:%02u:%02u:%02u.%03u,MPEGTS:%" PRId64 "%s",
h1, m1, s1, ms1, context->timing->sync_pts2fts_pts,
ccx_options.enc_cfg.line_terminator_lf ? "\n\n" : "\r\n\r\n");

View File

@@ -1913,8 +1913,8 @@ int dvbsub_decode(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, co
if (p_end - p < segment_length)
{
mprint("dvbsub_decode: incomplete, broken or empty packet, remaining bytes=%d, segment_length=%d\n",
p_end - p, segment_length);
mprint("dvbsub_decode: incomplete, broken or empty packet, remaining bytes=%lld, segment_length=%d\n",
(long long)(p_end - p), segment_length);
return -1;
}
@@ -1922,7 +1922,7 @@ int dvbsub_decode(struct encoder_ctx *enc_ctx, struct lib_cc_decode *dec_ctx, co
{
// debug traces
dbg_print(CCX_DMT_DVB, "DVBSUB - PTS: %" PRId64 ", ", dec_ctx->timing->current_pts);
dbg_print(CCX_DMT_DVB, "FTS: %d, ", dec_ctx->timing->fts_now);
dbg_print(CCX_DMT_DVB, "FTS: %" PRId64 ", ", dec_ctx->timing->fts_now);
dbg_print(CCX_DMT_DVB, "SEGMENT TYPE: %2X, ", segment_type);
switch (segment_type)

View File

@@ -278,7 +278,7 @@ int ps_get_more_data(struct lib_ccx_ctx *ctx, struct demuxer_data **ppdata)
if (want != peslen)
{
mprint("General LOOP: want(%d) != peslen(%d) \n", want, peslen);
mprint("General LOOP: want(%d) != peslen(%zu) \n", want, peslen);
continue;
}
if (want == 0) // Found package with header but without payload
@@ -1673,11 +1673,11 @@ int general_loop(struct lib_ccx_ctx *ctx)
if (dec_ctx->has_ccdata_buffered)
process_hdcc(enc_ctx, dec_ctx, &dec_ctx->dec_sub);
mprint("\nNumber of NAL_type_7: %ld\n", dec_ctx->avc_ctx->num_nal_unit_type_7);
mprint("Number of VCL_HRD: %ld\n", dec_ctx->avc_ctx->num_vcl_hrd);
mprint("Number of NAL HRD: %ld\n", dec_ctx->avc_ctx->num_nal_hrd);
mprint("Number of jump-in-frames: %ld\n", dec_ctx->avc_ctx->num_jump_in_frames);
mprint("Number of num_unexpected_sei_length: %ld", dec_ctx->avc_ctx->num_unexpected_sei_length);
mprint("\nNumber of NAL_type_7: %" PRId64 "\n", dec_ctx->avc_ctx->num_nal_unit_type_7);
mprint("Number of VCL_HRD: %" PRId64 "\n", dec_ctx->avc_ctx->num_vcl_hrd);
mprint("Number of NAL HRD: %" PRId64 "\n", dec_ctx->avc_ctx->num_nal_hrd);
mprint("Number of jump-in-frames: %" PRId64 "\n", dec_ctx->avc_ctx->num_jump_in_frames);
mprint("Number of num_unexpected_sei_length: %" PRId64, dec_ctx->avc_ctx->num_unexpected_sei_length);
free(dec_ctx->xds_ctx);
}

View File

@@ -822,7 +822,7 @@ ssize_t read_block(int fd, char *command, char *buf, size_t *buf_len)
if (len > *buf_len)
{
ign_bytes = len - *buf_len;
mprint("read_block() warning: Buffer overflow, ignoring %d bytes\n",
mprint("read_block() warning: Buffer overflow, ignoring %zu bytes\n",
ign_bytes);
len = *buf_len;
}

View File

@@ -590,7 +590,7 @@ int fuzzy_memcmp(const char *c1, const char *c2, const uint64_t *ucs2_buf1, unsi
// For the second string, only take the first chars (up to the first string length, that's upto).
l = (size_t)levenshtein_dist(ucs2_buf1, ucs2_buf2, ucs2_buf1_len, upto);
int res = (l > max);
dbg_print(CCX_DMT_LEVENSHTEIN, "\rLEV | %s | %s | Max: %d | Calc: %d | Match: %d\n", c1, c2, max, l, !res);
dbg_print(CCX_DMT_LEVENSHTEIN, "\rLEV | %s | %s | Max: %zu | Calc: %zu | Match: %d\n", c1, c2, max, l, !res);
return res;
}
@@ -1482,7 +1482,7 @@ int tlt_process_pes_packet(struct lib_cc_decode *dec_ctx, uint8_t *buffer, uint1
pes_crc_flag = (uint8_t)(buffer[7] << 6) >> 7;
pes_ext_flag = (uint8_t)(buffer[7] << 7) >> 7;
printf("Packet start code prefix: %04lx # ", pes_prefix);
printf("Packet start code prefix: %04" PRIx64 " # ", pes_prefix);
printf("Stream ID: %04x # ", pes_stream_id);
printf("Packet length: %d ", pes_packet_length);
printf("PESSC: 0x%x ", pes_scrambling_control);

View File

@@ -90,7 +90,7 @@ void pes_header_dump(uint8_t *buffer, long len)
pes_packet_length = 6 + ((buffer[4] << 8) | buffer[5]); // 5th and 6th byte of the header define the length of the rest of the packet (+6 is for the prefix, stream ID and packet length)
printf("Packet start code prefix: %04lx # ", pes_prefix);
printf("Packet start code prefix: %04" PRIx64 " # ", pes_prefix);
printf("Stream ID: %04x # ", pes_stream_id);
printf("Packet length: %d ", pes_packet_length);
@@ -342,8 +342,8 @@ int ts_readpacket(struct ccx_demuxer *ctx, struct ts_payload *payload)
else
payload->has_random_access_indicator = 0;
dbg_print(CCX_DMT_PARSE, "TS pid: %d PES start: %d counter: %u payload length: %u adapt length: %d\n",
payload->pid, payload->start, payload->counter, payload->length,
dbg_print(CCX_DMT_PARSE, "TS pid: %d PES start: %u counter: %u payload length: %u adapt length: %d\n",
payload->pid, payload->pesstart, payload->counter, payload->length,
(int)(adaptation_field_length));
if (payload->length == 0)
@@ -1021,7 +1021,7 @@ int64_t ts_readstream(struct ccx_demuxer *ctx, struct demuxer_data **data)
// If the buffer is empty we just started this function
if (payload.pesstart && cinfo->capbuflen > 0)
{
dbg_print(CCX_DMT_PARSE, "\nPES finished (%ld bytes/%ld PES packets/%ld total packets)\n",
dbg_print(CCX_DMT_PARSE, "\nPES finished (%" PRId64 " bytes/%ld PES packets/%ld total packets)\n",
cinfo->capbuflen, pespcount, pcount);
// Keep the data from capbuf to be worked on

View File

@@ -322,7 +322,7 @@ int read_header(struct ccx_demuxer *ctx, struct wtv_chunked_buffer *cb)
memcpy(&len, parsebuf + 16, 2);
dbg_print(CCX_DMT_PARSE, "len: %x\n", len);
memcpy(&file_length, parsebuf + 24, 8);
dbg_print(CCX_DMT_PARSE, "file_length: %x\n", file_length);
dbg_print(CCX_DMT_PARSE, "file_length: %" PRIx64 "\n", file_length);
if (len > 1024)
{
mprint("Too large for buffer!\n");
@@ -546,7 +546,7 @@ LLONG get_data(struct lib_ccx_ctx *ctx, struct wtv_chunked_buffer *cb, struct de
return CCX_EOF;
memcpy(&time, cb->buffer + 0x8, 8); // Read the timestamp
dbg_print(CCX_DMT_PARSE, "TIME: %ld\n", time);
dbg_print(CCX_DMT_PARSE, "TIME: %" PRId64 "\n", time);
if (time != -1 && time != WTV_CC_TIMESTAMP_MAGIC)
{ // Ignore -1 timestamps
LLONG pes_time = time_to_pes_time(time);