Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions src/torchcodec/_core/SingleStreamDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,9 +626,17 @@ FrameOutput SingleStreamDecoder::getFrameAtIndexInternal(
}
validateFrameIndex(streamMetadata, frameIndex);

int64_t pts = getPts(frameIndex);
setCursorPtsInSeconds(ptsToSeconds(pts, streamInfo.timeBase));
return getNextFrameInternal(preAllocatedOutputTensor);
// Only set cursor if we're not decoding sequentially: when decoding
// sequentially, we don't need to seek anywhere, so by *not* setting the
// cursor we allow canWeAvoidSeeking() to return true early.
if (frameIndex != lastDecodedFrameIndex_ + 1) {
int64_t pts = getPts(frameIndex);
setCursorPtsInSeconds(ptsToSeconds(pts, streamInfo.timeBase));
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I included the changes from #1039 in this PR.

@scotts , does the comment make sense now? What the comment is not saying is why returning early in canWeAvoidSeeking() is important. It's important because it avoids the calls to av_index_search_timestamp which are potentially slow. I don't know if we want to get to that level of detail in the comment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this greatly helps with understanding.

I do think we should explain somewhere that canWeAvoidSeeking() is itself expensive in some circumstances. . That's deeply counter-intuitive, that the function we're calling as an optimization to avoid the slow thing is itself also a slow thing. (But hopefully less slow.) Perhaps that should belong at the top of canWeAvoidSeeking().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will address that in an immediate follow-up


auto result = getNextFrameInternal(preAllocatedOutputTensor);
lastDecodedFrameIndex_ = frameIndex;
return result;
}

FrameBatchOutput SingleStreamDecoder::getFramesAtIndices(
Expand Down Expand Up @@ -1100,6 +1108,9 @@ I P P P I P P P I P P I P P I P
*/
bool SingleStreamDecoder::canWeAvoidSeeking() const {
const StreamInfo& streamInfo = streamInfos_.at(activeStreamIndex_);
if (!cursorWasJustSet_) {
return true;
}
if (streamInfo.avMediaType == AVMEDIA_TYPE_AUDIO) {
// For audio, we only need to seek if a backwards seek was requested
// within getFramesPlayedInRangeAudio(), when setCursorPtsInSeconds() was
Expand Down Expand Up @@ -1181,10 +1192,8 @@ UniqueAVFrame SingleStreamDecoder::decodeAVFrame(

resetDecodeStats();

if (cursorWasJustSet_) {
maybeSeekToBeforeDesiredPts();
cursorWasJustSet_ = false;
}
maybeSeekToBeforeDesiredPts();
cursorWasJustSet_ = false;

UniqueAVFrame avFrame(av_frame_alloc());
AutoAVPacket autoAVPacket;
Expand Down
1 change: 1 addition & 0 deletions src/torchcodec/_core/SingleStreamDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ class SingleStreamDecoder {
bool cursorWasJustSet_ = false;
int64_t lastDecodedAvFramePts_ = 0;
int64_t lastDecodedAvFrameDuration_ = 0;
int64_t lastDecodedFrameIndex_ = INT64_MIN;

// Stores various internal decoding stats.
DecodeStats decodeStats_;
Expand Down
Loading