Ejemplo n.º 1
0
/**
    \fn NextPicture
    \brief decode & returns the next picture
*/
bool        ADM_Composer::nextPicture(ADMImage *image,bool dontcross)
{
uint64_t pts;
uint64_t tail;
    
        // Decode image...
        _SEGMENT *seg=_segments.getSegment(_currentSegment);
        // Search it in the cache...
        _VIDEOS *vid=_segments.getRefVideo(seg->_reference);
        
        uint64_t refPts;
        _segments.LinearToRefTime(_currentSegment,_currentPts,&refPts);
        ADMImage *cached=vid->_videoCache->getAfter(refPts);
        if(cached)
        {
            uint64_t delta=cached->Pts-seg->_refStartTimeUs;
            if(delta<seg->_durationUs)
            {
                // Got it
                image->duplicate(cached);
            }else
                goto np_nextSeg;
        }else 
        { // Not in cache, decode next one
            if(false== nextPictureInternal(seg->_reference,image))
            {
                goto np_nextSeg;
            }
        }
        // Got it, update timing
        updateImageTiming(seg,image);
        // no we have our image, let's check it is within this segment range..
        pts=image->Pts;
        tail=seg->_startTimeUs+seg->_durationUs;
        if(pts>=tail)
        {
                ADM_info("Got an image (%"PRIu32" ms, but is out of this segment (%"PRIu32"+%"PRIu32"=%"PRIu32" ms)\n",
                                                                    pts,seg->_startTimeUs,seg->_durationUs,tail);
                _segments.dump();
                goto np_nextSeg;
        }
        
        SET_CURRENT_PTS(pts);
        //ADM_info("Current PTS:%"PRIu64"\n",_currentPts);
        return true;

// Try to get an image for the following segment....
np_nextSeg:
        if(true==dontcross)
        {
            ADM_warning("Not allowed to cross segment\n");
            return false;
        }
        if(_currentSegment+1<_segments.getNbSegments())
        {
            if(switchToNextSegment()==false)
            {
                ADM_warning("Cannot get next picture. cannot go to next segment also !\n");
                return false;
            }
            ADM_info("Switched to next segment\n");
            seg=_segments.getSegment(_currentSegment);
            samePictureInternal(seg->_reference,image);
            updateImageTiming(seg,image);
            SET_CURRENT_PTS(pts);
            return true;
        } 
        ADM_warning("Cannot get next picture. Last segment\n");
        return false;
}
/**
    \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;
}