/**
    \fn removeChunk
    \brief
*/
bool        ADM_EditorSegment::removeChunk(uint64_t from, uint64_t to)
{
    uint32_t startSeg,endSeg;
    uint64_t startOffset,endOffset;

    ADM_info("Cutting from %"PRIu64" to %"PRIu64" ms\n",from/1000,to/1000);
    dump();
    if(false==convertLinearTimeToSeg( from,&startSeg,&startOffset))
    {
        ADM_warning("Cannot get starting point (%"PRIu64" ms\n",from/1000);
        return false;
    }
    if(false==convertLinearTimeToSeg( to,&endSeg,&endOffset))
    {
        ADM_warning("Cannot get starting point (%"PRIu64" ms\n",from/1000);
        return false;
    }

    ADM_info("Start, seg %"PRIu32" Offset :%"PRIu64" ms\n",startSeg,startOffset);
    ADM_info("End  , seg %"PRIu32" Offset :%"PRIu64" ms\n",endSeg,endOffset);
    ListOfSegments tmp=segments;
    

    if(startSeg==endSeg)
    {
        // Split the seg int two..
        segments.insert(segments.begin()+startSeg+1,*getSegment(startSeg));
        endSeg=startSeg+1;

    }
    _SEGMENT *first=getSegment(startSeg);
      // Span over several seg...
    // 1- shorten the start segment..

    first->_durationUs=startOffset;

    // 3- Shorten last segment
    _SEGMENT *last=getSegment(endSeg);
    last->_refStartTimeUs+=endOffset;
    last->_durationUs-=endOffset;
    // 2- Kill the segment in between
    for(int i=startSeg+1;i<endSeg;i++)
    {
        segments.erase(segments.begin()+startSeg+1);
    }
    updateStartTime();
    removeEmptySegments();
    if(isEmpty())
    {
        GUI_Error_HIG(QT_TRANSLATE_NOOP("adm","Error"),QT_TRANSLATE_NOOP("adm","You cannot remove *all* the video\n"));
        segments=tmp;
        updateStartTime();
        return false;

    }
    undoSegments.push_back(tmp);
    dump();
    return true;
}
/**
    \fn updateRefVideo
    \brief Update start time
*/
bool        ADM_EditorSegment::updateRefVideo(void)
{
    int n=videos.size();
    ADM_assert(n);
    _VIDEOS *ref=getRefVideo(n-1);
    vidHeader *demuxer=ref->_aviheader;
    uint64_t pts,dts;

        demuxer->getPtsDts(0,&pts,&dts);
        if(pts!=ADM_NO_PTS && pts >0)
        {
            ADM_warning("Updating firstFramePTS, The first frame has a PTS >0, adjusting to %"PRIu64" ms\n",pts/1000);
            ref->firstFramePts=pts;
        }else
        {
            ADM_info("First PTS is %s\n",ADM_us2plain(pts));
        }

    updateStartTime();
    //
    n=segments.size();
    if(n)
    {
    _SEGMENT *seg=getSegment(n-1);
    uint64_t dur=ref->_aviheader->getVideoDuration();
    printf("Current duration %"PRIu64" ms real one %"PRIu64" ms\n",dur/1000,seg->_durationUs/1000);
    }

    return true;
}
void FCamera::update()
{
    log(Trace, this, "updating ...");
    updateStartTime();
    updateTimeOfDay();
    updateInterval();
}
Beispiel #4
0
/**
    \fn resetSegment
    \brief Redo a 1:1 mapping between videos and segments
*/
bool        ADM_EditorSegment::resetSegment(void)
{
    //
    aviInfo info;
    segments.clear();
    int n=videos.size();
    for(int i=0;i<n;i++)
    {
        _SEGMENT seg;
        _VIDEOS  *vid=&(videos[i]);

        seg._durationUs=vid->_aviheader->getVideoDuration();
#ifdef ADM_ZERO_OFFSET
        uint64_t pts=vid->firstFramePts;
        if(pts!=ADM_NO_PTS && pts)
        {
            ADM_warning("The first frame in ref video %d has PTS = %" PRIu64" us, adjusting the segment\n",i,pts);
            seg._refStartTimeUs=pts;
            seg._durationUs-=pts;
        }
#endif
        seg._reference=i;
        vid->_aviheader->getVideoInfo(&info);
        segments.push_back(seg);
    }
    updateStartTime();
    return true;
}
Beispiel #5
0
/**
    \fn addSegment
    \brief Add a segment to the segments list
*/
bool        ADM_EditorSegment::addSegment(_SEGMENT *seg)
{
    ADM_info("Adding a new segment\n");
    segments.push_back(*seg);
    updateStartTime();
    return true;
}
/**
    \fn undo
    \brief
*/
bool        ADM_EditorSegment::undo(void)
{
    if(undoSegments.empty()) return false;
    clipboard.clear();
    segments=undoSegments.back(); 
    undoSegments.pop_back();
    updateStartTime();
    return true;
}
Beispiel #7
0
/**
    \fn truncateVideo
    \brief Remove a part of the video from the given time to the end
*/
bool ADM_EditorSegment::truncateVideo(uint64_t from)
{
    uint32_t startSeg;
    uint64_t startOffset;

    ADM_info("Truncating from %" PRIu64" ms\n",from/1000);
    dump();
    if(false==convertLinearTimeToSeg(from,&startSeg,&startOffset))
    {
        ADM_warning("Cannot get starting point for linear time %" PRIu64" ms\n",from/1000);
        return false;
    }

    ADM_info("Start in segment %" PRIu32" at offset :%" PRIu64" ms\n",startSeg,startOffset);
    ListOfSegments tmp=segments;

    _SEGMENT *first=getSegment(startSeg);
    _VIDEOS *vid=getRefVideo(first->_reference);
    uint64_t padding=vid->timeIncrementInUs/2;
    // shorten the start segment
    first->_durationUs=startOffset+padding;
    // remove following segments
    int n=segments.size();
    for(int i=startSeg+1;i<n;i++)
    {
        segments.erase(segments.begin()+startSeg+1);
    }
    removeEmptySegments();
    updateStartTime();
    if(isEmpty())
    {
        GUI_Error_HIG(QT_TRANSLATE_NOOP("adm","Error"),QT_TRANSLATE_NOOP("adm","You cannot remove *all* the video\n"));
        segments=tmp;
        updateStartTime();
        return false;
    }
    dump();
    return true;
}
Beispiel #8
0
/**
 * \fn appendFromClipBoard
 * \brief append clipboard at the end of video
 * @return 
 */
bool ADM_EditorSegment::appendFromClipBoard(void)
{
    if(clipboardEmpty())
    {
        ADM_info("The clipboard is empty, nothing to do\n");
        return true;
    }
    ADM_info("Appending from clipboard\n");
    ListOfSegments tmp=segments;
    for(int i=0;i<clipboard.size();i++) segments.push_back(clipboard[i]);
    updateStartTime();
    dump();
    return true;
}
Beispiel #9
0
/**
 * \fn pasteFromClipBoard
 * \brief instert clipboard at currentTime position
 * @param currentTime
 * @return 
 */
bool        ADM_EditorSegment::pasteFromClipBoard(uint64_t currentTime)
{
    if(clipboardEmpty())
    {
        ADM_info("The clipboard is empty, nothing to do\n");
        return true;
    }
    ADM_info("Pasting from clipboard to %s\n",ADM_us2plain(currentTime));
    uint32_t startSeg;
    uint64_t startSegTime;
    convertLinearTimeToSeg(  currentTime, &startSeg,&startSegTime);    
    ListOfSegments tmp=segments;
    ListOfSegments newSegs;
    int n=segments.size();
    for(int i=0;i<n;i++)
    {
        _SEGMENT s=segments[i];
        if(i==startSeg)
        {
            // insert clipboard
            // Do we need to split it ?
            if(currentTime==s._startTimeUs)
            {
                // nope
                for(int j=0;j<clipboard.size();j++) newSegs.push_back(clipboard[j]);
            }else
            {
                 _SEGMENT pre=s,post=s;
                 uint64_t offset=currentTime-s._startTimeUs;
                 pre._durationUs=offset;
                 post._refStartTimeUs+=offset;
                 post._durationUs-=offset;
                 newSegs.push_back(pre);
                 for(int j=0;j<clipboard.size();j++) newSegs.push_back(clipboard[j]);
                 newSegs.push_back(post);
                 continue;
            }
                    
        }
        newSegs.push_back(s);
    }
    segments=newSegs;
    // If a video doesn't start at zero and we paste to its first frame,
    // we end up with an empty segment at the beginning. Remove it.
    removeEmptySegments();
    updateStartTime();
    dump();
    return true;
}
/**
    \fn resetSegment
    \brief Redo a 1:1 mapping between videos and segments
*/
bool        ADM_EditorSegment::resetSegment(void)
{
    //
    aviInfo info;
    segments.clear();
    undoSegments.clear();
    int n=videos.size();
    for(int i=0;i<n;i++)
    {
        _SEGMENT seg;
        _VIDEOS  *vid=&(videos[i]);

        seg._durationUs=vid->_aviheader->getVideoDuration();
        seg._reference=i;
        vid->_aviheader->getVideoInfo(&info);
        segments.push_back(seg);
    }
    updateStartTime();
    return true;
}
/**
 * \fn pasteFromClipBoard
 * \brief instert clipboard at currentTime position
 * @param currentTime
 * @return 
 */
bool        ADM_EditorSegment::pasteFromClipBoard(uint64_t currentTime)
{
    ADM_info("Pasting from clipboard to %s\n",ADM_us2plain(currentTime));
    uint32_t startSeg;
    uint64_t startSegTime;
    convertLinearTimeToSeg(  currentTime, &startSeg,&startSegTime);    
    ListOfSegments newSegs;
    int n=segments.size();
    for(int i=0;i<n;i++)
    {
        _SEGMENT s=segments[i];
        if(i==startSeg)
        {
            // insert clipboard
            // Do we need to split it ?
            if(currentTime==s._startTimeUs)
            {
                // nope
                for(int j=0;j<clipboard.size();j++) newSegs.push_back(clipboard[j]);
            }else
            {
                 _SEGMENT pre=s,post=s;
                 uint64_t offset=currentTime-s._startTimeUs;
                 pre._durationUs=offset;
                 post._refStartTimeUs+=offset;
                 post._durationUs-=offset;
                 newSegs.push_back(pre);
                 for(int j=0;j<clipboard.size();j++) newSegs.push_back(clipboard[j]);
                 newSegs.push_back(post);
                 continue;
            }
                    
        }
        newSegs.push_back(s);
    }
    segments=newSegs;
    updateStartTime();
    return true;
}
/**
    \fn addReferenceVideo
    \brief Add a new source video, fill in the missing info + create automatically the matching seg
*/
bool        ADM_EditorSegment::addReferenceVideo(_VIDEOS *ref)
{
  uint32_t    	l;
  uint8_t 	    *d;
  aviInfo       info;
  _SEGMENT      seg;

  ref->dontTrustBFramePts=ref->_aviheader->unreliableBFramePts();
  ref->_aviheader->getVideoInfo (&info);
  ref->_aviheader->getExtraHeaderData (&l, &d);
  ref->decoder = ADM_getDecoder (info.fcc,  info.width, info.height, l, d,info.bpp);
  ref->_videoCache   =   new EditorCache(8,info.width,info.height) ;

  float frameD=info.fps1000;
  frameD=frameD/1000;
  frameD=1/frameD;
  frameD*=1000000;
  ref->timeIncrementInUs=(uint64_t)frameD;

  // Probe the real time increment as the value determined from FPS may be incorrect due to interlace
  uint64_t firstNonZeroDts=ADM_NO_PTS,pts,dts;
  int firstNonZeroDtsFrame;
  ADM_info("[editor] Original frame increment %s\n",ADM_us2plain(ref->timeIncrementInUs));
  uint64_t minDelta=100000;
  uint64_t maxDelta=0;
  for (int frame=0; frame<info.nb_frames; frame++)
  {
      if (ref->_aviheader->getPtsDts(frame,&pts,&dts) && dts!=ADM_NO_PTS && dts!=0)
      {
          if (firstNonZeroDts==ADM_NO_PTS)
          {
              firstNonZeroDts=dts;
              firstNonZeroDtsFrame=frame;
              continue;
          }

          uint64_t probedTimeIncrement=(dts-firstNonZeroDts)/(frame-firstNonZeroDtsFrame);
          if(probedTimeIncrement<minDelta) minDelta=probedTimeIncrement;
          if(probedTimeIncrement>maxDelta) maxDelta=probedTimeIncrement;
          firstNonZeroDts=dts;
          firstNonZeroDtsFrame=frame;
      }
  }
  ADM_info("[Editor] min increment %s\n",ADM_us2plain(minDelta));
  ADM_info("[Editor] max increment %s\n",ADM_us2plain(maxDelta));
  
  //if (minDelta==ref->timeIncrementInUs*2)
              //ref->timeIncrementInUs=minDelta;

  
  ADM_info("[Editor] About %"PRIu64" microseconds per frame\n",ref->timeIncrementInUs);
  ref->_nb_video_frames = info.nb_frames;
  //
  //  And automatically create the segment
  //
  seg._reference=videos.size();
  if(!videos.size())
  {
        seg._startTimeUs=0;
  }else
  {
//      #warning todo compute cumulative time
   }
   seg._durationUs=ref->_aviheader->getVideoDuration();

    // Set the default startTime to the pts of first Pic
    vidHeader *demuxer=	ref->_aviheader;
    uint32_t flags;
        demuxer->getFlags(0,&flags);
        demuxer->getPtsDts(0,&pts,&dts);
        ref->firstFramePts=0;
        if(pts==ADM_NO_PTS) ADM_warning("First frame has unknown PTS\n");
        if(pts!=ADM_NO_PTS &&pts)
        {
            ADM_warning("The first frame has a PTS >0, adjusting to %"PRIu64" ms\n",pts/1000);
            ref->firstFramePts=pts;
        }

    if(!segments.empty()) undoSegments.push_back(segments);

    segments.push_back(seg);
    videos.push_back(*ref);
    updateStartTime();
    return true;
}