@@ -1034,24 +1034,57 @@ VideoDecoder::BatchDecodedOutput VideoDecoder::getFramesAtIndices(
10341034 validateUserProvidedStreamIndex (streamIndex);
10351035 validateScannedAllStreams (" getFramesAtIndices" );
10361036
1037+ auto indicesAreSorted =
1038+ std::is_sorted (frameIndices.begin (), frameIndices.end ());
1039+
1040+ std::vector<size_t > argsort;
1041+ if (!indicesAreSorted) {
1042+ // if frameIndices is [13, 10, 12, 11]
1043+ // when sorted, it's [10, 11, 12, 13] <-- this is the sorted order we want
1044+ // to use to decode the frames
1045+ // and argsort is [ 1, 3, 2, 0]
1046+ argsort.resize (frameIndices.size ());
1047+ for (size_t i = 0 ; i < argsort.size (); ++i) {
1048+ argsort[i] = i;
1049+ }
1050+ std::sort (
1051+ argsort.begin (), argsort.end (), [&frameIndices](size_t a, size_t b) {
1052+ return frameIndices[a] < frameIndices[b];
1053+ });
1054+ }
1055+
10371056 const auto & streamMetadata = containerMetadata_.streams [streamIndex];
10381057 const auto & stream = streams_[streamIndex];
10391058 const auto & options = stream.options ;
10401059 BatchDecodedOutput output (frameIndices.size (), options, streamMetadata);
10411060
1061+ auto previousIndexInVideo = -1 ;
10421062 for (auto f = 0 ; f < frameIndices.size (); ++f) {
1043- auto frameIndex = frameIndices[f];
1044- if (frameIndex < 0 || frameIndex >= stream.allFrames .size ()) {
1063+ auto indexInOutput = indicesAreSorted ? f : argsort[f];
1064+ auto indexInVideo = frameIndices[indexInOutput];
1065+ if (indexInVideo < 0 || indexInVideo >= stream.allFrames .size ()) {
10451066 throw std::runtime_error (
1046- " Invalid frame index=" + std::to_string (frameIndex ));
1067+ " Invalid frame index=" + std::to_string (indexInVideo ));
10471068 }
1048- DecodedOutput singleOut =
1049- getFrameAtIndex (streamIndex, frameIndex, output.frames [f]);
1050- if (options.colorConversionLibrary == ColorConversionLibrary::FILTERGRAPH) {
1051- output.frames [f] = singleOut.frame ;
1069+ if ((f > 0 ) && (indexInVideo == previousIndexInVideo)) {
1070+ // Avoid decoding the same frame twice
1071+ auto previousIndexInOutput = indicesAreSorted ? f - 1 : argsort[f - 1 ];
1072+ output.frames [indexInOutput].copy_ (output.frames [previousIndexInOutput]);
1073+ output.ptsSeconds [indexInOutput] =
1074+ output.ptsSeconds [previousIndexInOutput];
1075+ output.durationSeconds [indexInOutput] =
1076+ output.durationSeconds [previousIndexInOutput];
1077+ } else {
1078+ DecodedOutput singleOut = getFrameAtIndex (
1079+ streamIndex, indexInVideo, output.frames [indexInOutput]);
1080+ if (options.colorConversionLibrary ==
1081+ ColorConversionLibrary::FILTERGRAPH) {
1082+ output.frames [indexInOutput] = singleOut.frame ;
1083+ }
1084+ output.ptsSeconds [indexInOutput] = singleOut.ptsSeconds ;
1085+ output.durationSeconds [indexInOutput] = singleOut.durationSeconds ;
10521086 }
1053- // Note that for now we ignore the pts and duration parts of the output,
1054- // because they're never used in any caller.
1087+ previousIndexInVideo = indexInVideo;
10551088 }
10561089 output.frames = MaybePermuteHWC2CHW (options, output.frames );
10571090 return output;
0 commit comments