Fix AVPacket struct layout — was missing pts/dts fields

The packet layout is buf(8), pts(8), dts(8), data(8), size(4),
stream_index(4). We had buf, data, size, stream_index — reading
the pts timestamp as the data pointer, so every packet was garbage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
rolandnsharp
2026-04-05 19:56:02 +10:00
parent 9599855766
commit 666af905f3
635 changed files with 42 additions and 20 deletions

View File

@@ -86,21 +86,29 @@ proc readSamples*(cap: var AudioCapture, scope: var Scope) =
if not cap.live: return
const frameSize = 4 # 2ch × 16-bit
var total = 0
while total < scope.samplesL.len:
let ret = av_helper_read_frame(cap.fmtCtx, cap.packet)
if ret < 0: break
if av_helper_packet_stream(cap.packet) == cap.streamIdx:
let data = av_helper_packet_data(cap.packet)
let size = av_helper_packet_size(cap.packet)
for i in 0..<(size div frameSize):
if total >= scope.samplesL.len: break
let off = i * frameSize
let left = cast[int16]((data[off + 1].uint16 shl 8) or data[off].uint16)
let right = cast[int16]((data[off + 3].uint16 shl 8) or data[off + 2].uint16)
scope.samplesL[total] = left.float / 32768.0
scope.samplesR[total] = right.float / 32768.0
total += 1
# Read one packet — av_read_frame blocks until data arrives,
# which naturally rate-limits the render loop to the audio rate
let ret = av_helper_read_frame(cap.fmtCtx, cap.packet)
if ret < 0:
scope.sampleCount = 0
return
if av_helper_packet_stream(cap.packet) != cap.streamIdx:
av_helper_packet_unref(cap.packet)
if total > 0: break
scope.sampleCount = total
scope.sampleCount = 0
return
let data = av_helper_packet_data(cap.packet)
let size = av_helper_packet_size(cap.packet)
let frames = min(size div frameSize, scope.samplesL.len)
for i in 0..<frames:
let off = i * frameSize
let left = cast[int16]((data[off + 1].uint16 shl 8) or data[off].uint16)
let right = cast[int16]((data[off + 3].uint16 shl 8) or data[off + 2].uint16)
scope.samplesL[i] = left.float / 32768.0
scope.samplesR[i] = right.float / 32768.0
scope.sampleCount = frames
av_helper_packet_unref(cap.packet)

View File

@@ -11,11 +11,12 @@ typedef void AVFormatContext;
typedef void AVInputFormat;
typedef void AVDictionary;
/* AVPacket — we only need data, size, stream_index.
Layout is stable across FFmpeg 5.x/6.x/7.x:
first field is AVBufferRef*, then data, size, stream_index */
/* AVPacket partial layout — must match FFmpeg 5.x/6.x/7.x:
buf(8), pts(8), dts(8), data(8), size(4), stream_index(4) */
typedef struct {
void *buf;
int64_t pts;
int64_t dts;
uint8_t *data;
int size;
int stream_index;