@@ -112,7 +112,7 @@ namespace
112112 {
113113 public:
114114 explicit VideoReaderImpl (const Ptr<VideoSource>& source, const int minNumDecodeSurfaces, const bool allowFrameDrop = false , const bool udpSource = false ,
115- const Size targetSz = Size(), const Rect srcRoi = Rect(), const Rect targetRoi = Rect(), const bool enableHistogram = false);
115+ const Size targetSz = Size(), const Rect srcRoi = Rect(), const Rect targetRoi = Rect(), const bool enableHistogram = false, const int firstFrameIdx = 0 );
116116 ~VideoReaderImpl ();
117117
118118 bool nextFrame (GpuMat& frame, Stream& stream) CV_OVERRIDE;
@@ -135,6 +135,9 @@ namespace
135135 bool get (const int propertyId, double & propertyVal) const CV_OVERRIDE;
136136
137137 private:
138+ bool skipFrame ();
139+ bool aquireFrameInfo (std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo, Stream& stream = Stream::Null());
140+ void releaseFrameInfo (const std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo);
138141 bool internalGrab (GpuMat & frame, GpuMat & histogram, Stream & stream);
139142 void waitForDecoderInit ();
140143
@@ -154,6 +157,7 @@ namespace
154157 static const int rawPacketsBaseIdx = 2 ;
155158 ColorFormat colorFormat = ColorFormat::BGRA;
156159 static const String errorMsg;
160+ int iFrame = 0 ;
157161 };
158162
159163 const String VideoReaderImpl::errorMsg = " Parsing/Decoding video source failed, check GPU memory is available and GPU supports requested functionality." ;
@@ -173,7 +177,7 @@ namespace
173177 }
174178
175179 VideoReaderImpl::VideoReaderImpl (const Ptr<VideoSource>& source, const int minNumDecodeSurfaces, const bool allowFrameDrop, const bool udpSource,
176- const Size targetSz, const Rect srcRoi, const Rect targetRoi, const bool enableHistogram) :
180+ const Size targetSz, const Rect srcRoi, const Rect targetRoi, const bool enableHistogram, const int firstFrameIdx ) :
177181 videoSource_ (source),
178182 lock_ (0 )
179183 {
@@ -190,6 +194,8 @@ namespace
190194 videoSource_->setVideoParser (videoParser_);
191195 videoSource_->start ();
192196 waitForDecoderInit ();
197+ for (iFrame = videoSource_->getFirstFrameIdx (); iFrame < firstFrameIdx; iFrame++)
198+ CV_Assert (skipFrame ());
193199 videoSource_->updateFormat (videoDecoder_->format ());
194200 }
195201
@@ -209,10 +215,7 @@ namespace
209215 CUvideoctxlock m_lock;
210216 };
211217
212- bool VideoReaderImpl::internalGrab (GpuMat& frame, GpuMat& histogram, Stream& stream) {
213- if (videoParser_->hasError ())
214- CV_Error (Error::StsError, errorMsg);
215- cudacodec::FormatInfo fmt;
218+ bool VideoReaderImpl::aquireFrameInfo (std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo, Stream& stream) {
216219 if (frames_.empty ())
217220 {
218221 CUVIDPARSERDISPINFO displayInfo;
@@ -234,34 +237,53 @@ namespace
234237
235238 bool isProgressive = displayInfo.progressive_frame != 0 ;
236239 const int num_fields = isProgressive ? 1 : 2 + displayInfo.repeat_first_field ;
237- fmt = videoDecoder_->format ();
238- videoSource_->updateFormat (fmt);
239240
240241 for (int active_field = 0 ; active_field < num_fields; ++active_field)
241242 {
242243 CUVIDPROCPARAMS videoProcParams;
243244 std::memset (&videoProcParams, 0 , sizeof (CUVIDPROCPARAMS));
244245
245246 videoProcParams.progressive_frame = displayInfo.progressive_frame ;
246- videoProcParams.second_field = active_field;
247- videoProcParams.top_field_first = displayInfo.top_field_first ;
248- videoProcParams.unpaired_field = (num_fields == 1 );
247+ videoProcParams.second_field = active_field;
248+ videoProcParams.top_field_first = displayInfo.top_field_first ;
249+ videoProcParams.unpaired_field = (num_fields == 1 );
249250 videoProcParams.output_stream = StreamAccessor::getStream (stream);
250251
251252 frames_.push_back (std::make_pair (displayInfo, videoProcParams));
252253 }
253254 }
255+ else {
256+ for (auto & frame : frames_)
257+ frame.second .output_stream = StreamAccessor::getStream (stream);
258+ }
254259
255260 if (frames_.empty ())
256261 return false ;
257262
258- std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo = frames_.front ();
263+ frameInfo = frames_.front ();
259264 frames_.pop_front ();
265+ return true ;
266+ }
267+
268+ void VideoReaderImpl::releaseFrameInfo (const std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS>& frameInfo) {
269+ // release the frame, so it can be re-used in decoder
270+ if (frames_.empty ())
271+ frameQueue_->releaseFrame (frameInfo.first );
272+ }
273+
274+ bool VideoReaderImpl::internalGrab (GpuMat& frame, GpuMat& histogram, Stream& stream) {
275+ if (videoParser_->hasError ())
276+ CV_Error (Error::StsError, errorMsg);
277+
278+ std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo;
279+ if (!aquireFrameInfo (frameInfo, stream))
280+ return false ;
260281
261282 {
262283 VideoCtxAutoLock autoLock (lock_);
263284
264285 unsigned long long cuHistogramPtr = 0 ;
286+ const cudacodec::FormatInfo fmt = videoDecoder_->format ();
265287 if (fmt.enableHistogram )
266288 frameInfo.second .histogram_dptr = &cuHistogramPtr;
267289
@@ -281,10 +303,16 @@ namespace
281303 videoDecoder_->unmapFrame (decodedFrame);
282304 }
283305
284- // release the frame, so it can be re-used in decoder
285- if (frames_.empty ())
286- frameQueue_->releaseFrame (frameInfo.first );
306+ releaseFrameInfo (frameInfo);
307+ iFrame++;
308+ return true ;
309+ }
287310
311+ bool VideoReaderImpl::skipFrame () {
312+ std::pair<CUVIDPARSERDISPINFO, CUVIDPROCPARAMS> frameInfo;
313+ if (!aquireFrameInfo (frameInfo))
314+ return false ;
315+ releaseFrameInfo (frameInfo);
288316 return true ;
289317 }
290318
@@ -399,6 +427,10 @@ namespace
399427 }
400428
401429 bool VideoReaderImpl::get (const int propertyId, double & propertyVal) const {
430+ if (propertyId == cv::VideoCaptureProperties::CAP_PROP_POS_FRAMES) {
431+ propertyVal = static_cast <double >(iFrame);
432+ return true ;
433+ }
402434 return videoSource_->get (propertyId, propertyVal);
403435 }
404436
@@ -421,28 +453,26 @@ Ptr<VideoReader> cv::cudacodec::createVideoReader(const String& filename, const
421453 CV_Assert (!filename.empty ());
422454
423455 Ptr<VideoSource> videoSource;
424-
425456 try
426457 {
427458 // prefer ffmpeg to cuvidGetSourceVideoFormat() which doesn't always return the corrct raw pixel format
428- Ptr<RawVideoSource> source (new FFmpegVideoSource (filename, sourceParams));
459+ Ptr<RawVideoSource> source (new FFmpegVideoSource (filename, sourceParams, params. firstFrameIdx ));
429460 videoSource.reset (new RawVideoSourceWrapper (source, params.rawMode ));
430461 }
431462 catch (...)
432463 {
433464 if (sourceParams.size ()) throw ;
434465 videoSource.reset (new CuvidVideoSource (filename));
435466 }
436-
437467 return makePtr<VideoReaderImpl>(videoSource, params.minNumDecodeSurfaces , params.allowFrameDrop , params.udpSource , params.targetSz ,
438- params.srcRoi , params.targetRoi , params.enableHistogram );
468+ params.srcRoi , params.targetRoi , params.enableHistogram , params. firstFrameIdx );
439469}
440470
441471Ptr<VideoReader> cv::cudacodec::createVideoReader (const Ptr<RawVideoSource>& source, const VideoReaderInitParams params)
442472{
443473 Ptr<VideoSource> videoSource (new RawVideoSourceWrapper (source, params.rawMode ));
444474 return makePtr<VideoReaderImpl>(videoSource, params.minNumDecodeSurfaces , params.allowFrameDrop , params.udpSource , params.targetSz ,
445- params.srcRoi , params.targetRoi , params.enableHistogram );
475+ params.srcRoi , params.targetRoi , params.enableHistogram , params. firstFrameIdx );
446476}
447477
448478void cv::cudacodec::MapHist (const GpuMat& hist, Mat& histFull) {
0 commit comments