Skip to content

Rework wait for segment code#2076

Merged
CastagnaIT merged 2 commits into
xbmc:Piersfrom
CastagnaIT:wait_segments
Jun 30, 2026
Merged

Rework wait for segment code#2076
CastagnaIT merged 2 commits into
xbmc:Piersfrom
CastagnaIT:wait_segments

Conversation

@CastagnaIT

@CastagnaIT CastagnaIT commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Description

This will rework the WaitingForSegment code, moving it from CRepresentation class to the AdaptiveStream class
the AdaptiveStream class will be the main place where manage buffering cases, without having to manage buffering per representation (stream) basis,
IMO i don't see negative effects doing this change since one AdaptiveStream can manage only one stream at time

Motivation and context

fix #2075

1° problem:
from PR #1867 has been added InsertLiveSegment call inside AdaptiveStream::waitingForSegment
this is good when called from CSession::GetNextSample

but this cause wrong things when called from demuxers
what happens, the demuxer try to read data from a segment, and if there is no segment AdaptiveStream::ensureSegment set IsWaitForSegment on the representation to "true", after this the demuxer call AdaptiveStream::waitingForSegment to check if has to trigger EOS, but calling AdaptiveStream::waitingForSegment cause to call InsertLiveSegment that invalidate the IsWaitForSegment status previously set, triggering EOS playback will freeze/stall

so the demuxers must not cause a call to InsertLiveSegment

2° problem:
when there are no new segments CSession::GetNextSample call AdaptiveStream::waitingForSegment to call InsertLiveSegment, but if InsertLiveSegment at the moment dont insert new segments, cause a "cat and mice" behaviour like the following:

2026-06-24 18:21:26.417 T:20052   debug <inputstream.adaptive>: adaptive::AdaptiveStream::ensureSegment: [AS-1] Begin WaitForSegment stream rep. id "pa3" period id "1"
2026-06-24 18:21:26.684 T:29408   debug <inputstream.adaptive>: adaptive::CDashTree::InsertLiveSegment: End WaitForSegment repr. id pa3
2026-06-24 18:21:26.685 T:20052   debug <inputstream.adaptive>: adaptive::AdaptiveStream::ensureSegment: [AS-1] Begin WaitForSegment stream rep. id "pa3" period id "1"
2026-06-24 18:21:27.184 T:29408   debug <inputstream.adaptive>: adaptive::CDashTree::InsertLiveSegment: End WaitForSegment repr. id pa3
2026-06-24 18:21:27.185 T:20052   debug <inputstream.adaptive>: adaptive::AdaptiveStream::ensureSegment: [AS-1] Begin WaitForSegment stream rep. id "pa3" period id "1"
2026-06-24 18:21:27.684 T:29408   debug <inputstream.adaptive>: adaptive::CDashTree::InsertLiveSegment: End WaitForSegment repr. id pa3
2026-06-24 18:21:27.685 T:20052   debug <inputstream.adaptive>: adaptive::AdaptiveStream::ensureSegment: [AS-1] Begin WaitForSegment stream rep. id "pa3" period id "1"
2026-06-24 18:21:28.184 T:29408   debug <inputstream.adaptive>: adaptive::CDashTree::InsertLiveSegment: End WaitForSegment repr. id pa3

between ensureSegment and InsertLiveSegment, so InsertLiveSegment should set IsWaitForSegment to false only when a new segment exists

3° problem:
When the stream is on buffering (e.g. loading wheel on GUI) the CPU starts to get very busy,
by debugging with in my PC (16 core, not so slow) i can observe CPU spike from 8% to 13% on Kodi when buffering (and fan speed go high), when playback back to normal CPU go down to about 1-7%,
i discovered that kodi VP do callbacks DemuxRead in a uncontrolled loop

DEMUX_PACKET* CInputStreamAdaptive::DemuxRead(void)

so when we are in buffering we return empty packets too fast, this cause the CPU spikes.
Add a thread sleep mitigate the problem, but seem that there is something else on VP to be fixed that cause slightly higher CPU usage

How has this been tested?

Screenshots (if appropriate):

Types of change

  • Bug fix (non-breaking change which fixes an issue)
  • Clean up (non-breaking change which removes non-working, unmaintained functionality)
  • Improvement (non-breaking change which improves existing functionality)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that will cause existing functionality to change)
  • Cosmetic change (non-breaking change that doesn't touch code)
  • None of the above (please explain below)

Checklist:

  • I have read the Contributing document
  • My code follows the Code Guidelines of this project
  • My change requires a change to the Wiki documentation
  • I have updated the documentation accordingly

@kodiai

kodiai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Decision: APPROVE

Issues: none

Evidence:

  • Review prompt covered 9 changed files.
Review Details
  • Review plan: ready hash=c417a77d0510 route=standard task=review.full files=9 lines=45(local-diff) budget=na/774s gates=3/3 publish=canonical-visible-surface graph=skipped candidates=preferred doctrine=disabled/0/0/0 reasons=disabled

  • Review reducer: ready input=6 kept=6 suppressed=0 rewritten=0 deprioritized=0 lowConfidence=0 auditEvents=0 severityDemoted=0 graphValidated=0 graphUncertain=0 doctrine=disabled/0/0/0 reasons=disabled

  • Review candidates: shadow recorded=6 rejected=0 errors=0 artifact=present repo=xbmc-inputstream.adaptive pr=2076 key=kodiai-review-output:v1:inst-109141824:xbmc-inputstream.adaptive:pr-2076:action- delivery=7c031970-6ff3-11f1-80ef-567c9382849a

  • Review candidate publication: mode=blocked approved=6 rewritten=0 publishable=0 nonPublishable=6 fixBlocked=6 published=0 directFallback=0 reasons=fix-eligibility-blocked movedToDetails=0 detailsOmitted=0 buckets=blocked:6:fix-eligibility-blocked+missing-replacement

  • M072 candidate publication bridge: status=denied; bridgeVersion=candidate-publication-bridge.v1; bridgeId=candidate-publication-record:3d1dffe341acad7e1d1401d598779fa7; recordKey=candidate-publication-record:3d1dffe341acad7e1d1401d598779fa7; correlationKey=candidate-publication-bridge:b2fb3b8bb333cf8c1268113fa11a56f7; source=review-handler-publication; candidateRef=candidate-publication-summary-25b4737e; verification=none; counts=candidateCount:0,evidenceCount:0,verifiedCount:0,partiallyVerifiedCount:0,unverifiedCount:0,disprovenCount:0,publicationEligibleCount:0,malformedRecordCount:0,unsafeInputFieldCount:0; reasons=no-evidence,publication-ineligible; malformed=none; presence=deliveryId:y,reviewOutputKey:y,upstreamCorrelationKey:y,policyCorrelationKey:y; handoffOwner=available; redaction=privateOnly:y,rawPayloads:n,publicationFields:n,evidencePayloads:n,githubCommentBody:n,reducerRawPayload:n,discardedRawPayload:n,discardedPublicationFields:n,discardedEvidencePayloads:n

  • Review finding lifecycle: status=normalized; counts=input:6,recorded:6,rejected:0,unsafeInputFields:0; correlation=repo:y,pull:y,reviewOutputKey:y,deliveryId:y,commit:y; statuses=detected:6,open:6,suggested:0,validated:0,revalidated:0,resolved:0,blocked:0,degraded:0; severity=critical:3,major:3,medium:0,minor:0; actionability=actionable:0,needs-human-review:6,needs-reproduction:0,blocked:0,not-actionable:0; reasons=automatic-detected,automatic-open,automatic-review; rejected=none; redaction=privateOnly:y,rawPrompts:n,rawModelOutput:n,candidateBodies:n,toolPayloads:n,secretLike:n,diffs:n,unboundedArrays:n,unsafeFields:0

  • Review validation truth: status=normalized; counts=detected:6,suggested:0,validated:0,revalidated:0,resolved:0,blocked:0,degraded:0,open:6,uncertain:0,inputFindings:6,unsafeInputFields:0; evidence=fresh:0,stale:0,missingValidation:6,missingRevalidation:6; reasons=validation-missing:6; refs=rfl-c43c7b740967be15:open:validation-missing:fix:n:validation:n:revalidation:n,rfl-1b2936fa7e3e30da:open:validation-missing:fix:n:validation:n:revalidation:n,rfl-3dc8c89e83aa0861:open:validation-missing:fix:n:validation:n:revalidation:n,rfl-ab144df33fe6db9a:open:validation-missing:fix:n:validation:n:revalidation:n,rfl-f20c177eddcee0fa:open:validation-missing:fix:n:validation:n:revalidation:n +1 omitted; correlation=reviewOutputKey:y,deliveryId:y; redaction=privateOnly:y,rawPrompts:n,rawModelOutput:n,candidateBodies:n,replacementText:n,toolPayloads:n,secretLike:n,diffs:n,unboundedArrays:n,unsafeFields:0

  • Files reviewed: 9

  • Findings: 0 critical, 0 major, 0 medium, 0 minor

  • Lines changed: +38 -7

  • Profile: strict (auto, lines changed: 45)

  • Contributor experience: profile-backed (using linked contributor profile guidance)

  • Shadow specialist: lane=docs-config-truth status=skipped reason=no-operator-truth-paths candidateCount=0 decisionCount=0 decisionCounts=candidate:0,duplicate:0,disagreement:0,dismissed:0,unclassifiable:0 duplicateCount=0 disagreementCount=0 dismissedCount=0 unclassifiableCount=0 truncatedCandidateCount=0 metricAvailability=token:n,cost:n,latency:n visiblePublicationDenied=true approvalPublicationDenied=true privateOnly=true shadowOnly=true redacted=raw:n,publication:n,approval:n,unsafe:0 correlationKey=ec45bf536cba135d deliveryId=7c031970-6ff3-11f1-80ef-567c938… reviewOutputKey=kodiai-review-output:v1:inst-10…

  • Review completed: 2026-06-24T17:45:23.077Z

  • Total wall-clock: 7m 4s

  • Phase timings:

    • queue wait: 0ms
    • workspace preparation: 822ms
    • retrieval/context assembly: 6.9s
    • executor handoff: 38s
    • remote runtime: 6m 14s
    • publication: 2.6s
  • Claude Code usage: 8% of five_hour limit remaining | resets 2026-06-24T18:00:00.000Z

  • Tokens: 210 in / 16,798 out | 0.6082

  • Keyword parsing: No keywords detected

  • Budget behavior: complete (within-budget).

  • Prompt budget: 5 sections, 0 trimmed, 0 bypassed, 0 trimmed tokens.

  • Cache behavior: 2 observations, 1 hits, 1 misses, 0 degraded, 0 bypassed.

  • Continuation behavior: 0 observations, 0 compacted, 0 fallback, 0 degraded, 0 bypassed.

@CastagnaIT CastagnaIT force-pushed the wait_segments branch 5 times, most recently from 634c851 to 38dfda6 Compare June 29, 2026 07:36
@CastagnaIT CastagnaIT marked this pull request as ready for review June 29, 2026 07:41
@CastagnaIT

Copy link
Copy Markdown
Collaborator Author

@kodiai review

@CastagnaIT CastagnaIT changed the title Wait for segment fixes Rework wait for segment code Jun 29, 2026
@CastagnaIT CastagnaIT added Type: Fix non-breaking change which fixes an issue Type: Improvement non-breaking change which improves existing functionality v22 Piers labels Jun 29, 2026
@kodiai

kodiai Bot commented Jun 29, 2026

Copy link
Copy Markdown
kodiai response

I ran out of steps analyzing this and wasn't able to post a complete response.

No review findings were published for this request.

This usually means the agent got stuck in tool use or exceeded its step budget for this run.
Try a narrower request such as kodiai review path/to/file.cpp if it repeats.

@CastagnaIT

Copy link
Copy Markdown
Collaborator Author

@kodiai review

@kodiai

kodiai Bot commented Jun 29, 2026

Copy link
Copy Markdown
kodiai response

I ran out of steps analyzing this and wasn't able to post a complete response.

No review findings were published for this request.

This usually means the agent got stuck in tool use or exceeded its step budget for this run.
Try a narrower request such as kodiai review path/to/file.cpp if it repeats.

@CastagnaIT

Copy link
Copy Markdown
Collaborator Author

@kodiai review

@kodiai

kodiai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Kodiai Review Summary

What Changed

This PR refactors wait-for-segment buffering logic from per-representation to centralized AdaptiveStream management. Reviewed: core logic

Observations

Impact

[CRITICAL] src/common/AdaptiveStream.cpp (1285): Null pointer dereference of thread_data_
The method calls thread_data_->State() without null check causing crash when invoked before start_stream() initializes it at line 654 or after Stop() but before Dispose() deletes it at line 1410

[CRITICAL] src/common/AdaptiveStream.cpp (1281-1295): Null pointer dereferences of current_rep_ and current_period_
InsertLiveSegment at line 1281, GetNextSegment at line 1289, and GetId at line 1295 access these pointers causing segfault when clear() sets current_rep_ = 0 at line 1398

[MAJOR] src/common/AdaptiveStream.cpp (1283-1300): Race condition on m_isWaitingForSegment flag
Plain bool accessed from ensureSegment at lines 973-981 and OnSampleRequested at lines 1283-1300 without synchronization causing lost updates and incorrect EOS signaling

[MAJOR] src/common/SegmentBuffer.cpp (199): Off-by-one error in boundary validation
Check uses size() less-than downloadIndex instead of less-than-or-equal allowing downloadIndex to reach size then line 205 increments it causing out-of-bounds exception at line 193

[MAJOR] src/common/AdaptiveStream.cpp (976-977): Null pointer dereference in logging
LOG::LogF calls current_rep_->GetId() and current_period_->GetId() without null checks causing crash when clear() nullifies pointers at lines 1393-1398

Verdict

🔴 Address before merging -- 5 blocking issue(s) found

When you are waiting for buffer, the VP do DemuxRead callbacks in very fast way
causing CPU spikes until 13% (on a fast CPU)
add a thread sleep help to mitigate the problem
@CastagnaIT

Copy link
Copy Markdown
Collaborator Author

Only this was taken into account, the others are irrelevant on how the code works atm

[CRITICAL] src/common/AdaptiveStream.cpp (1285): Null pointer dereference of thread_data_
The method calls thread_data_->State() without null check causing crash when invoked before start_stream() initializes it at line 654 or after Stop() but before Dispose() deletes it at line 1410

the following one, should not happens because CSession::GetNextSample guard the call with IsReadSampleAsyncWorking

[MAJOR] src/common/AdaptiveStream.cpp (1283-1300): Race condition on m_isWaitingForSegment flag
Plain bool accessed from ensureSegment at lines 973-981 and OnSampleRequested at lines 1283-1300 without synchronization causing lost updates and incorrect EOS signaling

@CastagnaIT CastagnaIT merged commit 103f110 into xbmc:Piers Jun 30, 2026
11 checks passed
@CastagnaIT CastagnaIT deleted the wait_segments branch June 30, 2026 06:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Fix non-breaking change which fixes an issue Type: Improvement non-breaking change which improves existing functionality v22 Piers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] video freezes while audio continues

1 participant