Update PTS Offset (if any)
| 2483 | |
| 2484 | // Update PTS Offset (if any) |
| 2485 | void FFmpegReader::UpdatePTSOffset() { |
| 2486 | if (pts_offset_seconds != NO_PTS_OFFSET) { |
| 2487 | // Skip this method if we have already set PTS offset |
| 2488 | return; |
| 2489 | } |
| 2490 | pts_offset_seconds = 0.0; |
| 2491 | double video_pts_offset_seconds = 0.0; |
| 2492 | double audio_pts_offset_seconds = 0.0; |
| 2493 | |
| 2494 | bool has_video_pts = false; |
| 2495 | if (!info.has_video) { |
| 2496 | // Mark as checked |
| 2497 | has_video_pts = true; |
| 2498 | } |
| 2499 | bool has_audio_pts = false; |
| 2500 | if (!info.has_audio) { |
| 2501 | // Mark as checked |
| 2502 | has_audio_pts = true; |
| 2503 | } |
| 2504 | |
| 2505 | // Loop through the stream (until a packet from all streams is found) |
| 2506 | while (!has_video_pts || !has_audio_pts) { |
| 2507 | // Get the next packet (if any) |
| 2508 | if (GetNextPacket() < 0) |
| 2509 | // Break loop when no more packets found |
| 2510 | break; |
| 2511 | |
| 2512 | // Get PTS of this packet |
| 2513 | int64_t pts = GetPacketPTS(); |
| 2514 | |
| 2515 | // Video packet |
| 2516 | if (!has_video_pts && packet->stream_index == videoStream) { |
| 2517 | // Get the video packet start time (in seconds) |
| 2518 | video_pts_offset_seconds = 0.0 - (pts * info.video_timebase.ToDouble()); |
| 2519 | |
| 2520 | // Is timestamp close to zero (within X seconds) |
| 2521 | // Ignore wildly invalid timestamps (i.e. -234923423423) |
| 2522 | if (std::abs(video_pts_offset_seconds) <= 10.0) { |
| 2523 | has_video_pts = true; |
| 2524 | } |
| 2525 | } |
| 2526 | else if (!has_audio_pts && packet->stream_index == audioStream) { |
| 2527 | // Get the audio packet start time (in seconds) |
| 2528 | audio_pts_offset_seconds = 0.0 - (pts * info.audio_timebase.ToDouble()); |
| 2529 | |
| 2530 | // Is timestamp close to zero (within X seconds) |
| 2531 | // Ignore wildly invalid timestamps (i.e. -234923423423) |
| 2532 | if (std::abs(audio_pts_offset_seconds) <= 10.0) { |
| 2533 | has_audio_pts = true; |
| 2534 | } |
| 2535 | } |
| 2536 | } |
| 2537 | |
| 2538 | // Choose timestamp origin: |
| 2539 | // - If video exists, anchor timeline frame mapping to video start. |
| 2540 | // This avoids AAC priming / audio preroll shifting video frame 1 to frame 2. |
| 2541 | // - If no video exists (audio-only readers), use audio start. |
| 2542 | if (info.has_video && has_video_pts) { |