/** \fn decodeTillPicture \brief that one is a bit different compare to goToTime as we dont want to decode the targetPts if it is a keyframe but have the frame before */ bool ADM_Composer::decodeTillPictureAtPts(uint64_t targetPts,ADMImage *image) { // Go to the previous keyframe and decode forward... uint32_t thisSeg=_currentSegment; _SEGMENT *seg=_segments.getSegment(_currentSegment); int ref=seg->_reference; uint64_t refTime; if(false==_segments.LinearToRefTime(_currentSegment,targetPts-1,&refTime)) { ADM_warning("Cannot find ref time\n"); return false; } uint64_t previousKf; if(false==searchPreviousKeyFrameInRef(ref,refTime,&previousKf)) { ADM_warning("Cannot find previous keyframe in ref %d, time=%"PRIu64" \n",ref,refTime); return false; } // go to it... if(false==seektoTime(ref,previousKf,false)) { ADM_warning("Cannot seek to time=%"PRIu64" \n",previousKf); return false; } // Now forward till we reach out frame while(1) { if(false==nextPicture(image,true)) { ADM_warning("Error in decoding forward"); return false; } if(image->Pts>=targetPts) break; if(thisSeg!=_currentSegment) break; } if(image->Pts!=targetPts) { ADM_error("Could not retrieve our own frame at PTS=%"PRIu64" ms\n",targetPts/1000); return false; } return true; }
/** \fn seektoFrame \brief Seek to frame with timestamp given as arg */ bool ADM_Composer::seektoTime(uint32_t ref,uint64_t timeToSeek,bool dontdecode) { _VIDEOS *vid=_segments.getRefVideo(ref); vidHeader *demuxer=vid->_aviheader; EditorCache *cache =vid->_videoCache; ADM_assert(cache); bool found=false; // Search the previous keyframe for segment.... uint64_t seekTime; if(_segments.isKeyFrameByTime(ref,timeToSeek)) { seekTime=timeToSeek; ADM_info("First frame of the new segment is a keyframe at %"PRIu32"ms\n",seekTime/1000); found=true; }else { if(false==searchPreviousKeyFrameInRef(ref,timeToSeek,&seekTime)) { ADM_warning("Cannot identify the keyframe before %"PRIu64" ms\n",seekTime/1000); return false; } } uint32_t frame=_segments.intraTimeToFrame(ref,seekTime); if(dontdecode==true) { vid->lastSentFrame=frame; ADM_info("Seek to time without decoding ok\n"); return true; } // ok now seek... if(false==DecodePictureUpToIntra(ref,frame)) { ADM_warning("Cannot decode up to intra %"PRIu64" at %"PRIu64" ms\n",frame,seekTime/1000); return false; } if(found==true) return true; // Now forward... while(nextPictureInternal(ref,NULL)==true) { uint64_t pts=vid->lastDecodedPts; if(pts==ADM_NO_PTS) { ADM_warning("No PTS out of decoder\n"); continue; } vid->lastReadPts=pts; if(pts==timeToSeek) { ADM_info("Image found, pts=%"PRIu64" ms\n",pts/1000); return true; } if(pts>timeToSeek) { ADM_info("Image not found,searching %"PRIu64" ms, got pts=%"PRIu64" ms\n",timeToSeek/1000,pts/1000); return false; } } ADM_warning("seekToFrame failed for frame at PTS= %"PRIu64" ms, next image failed\n",timeToSeek/1000); return false; }