Skip to content

Commit

Permalink
[editor] Try to not drop bframes that will be used later as reference…
Browse files Browse the repository at this point in the history
… (h264/h265 in copy mode). Experimental, that can cause problems
  • Loading branch information
mean committed Jul 26, 2016
1 parent fc80c1a commit a1806d3
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 23 deletions.
7 changes: 4 additions & 3 deletions avidemux/common/ADM_editor/include/ADM_edit.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ public:
public:
uint64_t getLastKeyFramePts(void);
uint64_t getCurrentFramePts(void);
bool setCurrentFramePts(uint64_t pts);
bool setCurrentFramePts(uint64_t pts);
bool goToTimeVideo(uint64_t time);
void getCurrentFrameFlags(uint32_t *flags, uint32_t *quantiser);
void getCurrentFrameFlags(uint32_t *flags, uint32_t *quantiser);
bool goToIntraTimeVideo(uint64_t time);
bool nextPicture(ADMImage *image,bool dontcross=false);
bool samePicture(ADMImage *image);
Expand All @@ -239,6 +239,7 @@ public:
public:
uint8_t updateVideoInfo(aviInfo *info);
uint32_t getSpecificMpeg4Info( void );
bool getNonClosedGopDelay(uint64_t time,uint32_t *delay);
/************************************ /audioStream ******************************/
bool getAudioStreamsInfo(uint64_t xtime,uint32_t *nbStreams, audioInfo **infos);
bool changeAudioStream(uint64_t xtime,uint32_t newstream);
Expand Down Expand Up @@ -267,7 +268,7 @@ public:
bool getPKFramePTS(uint64_t *frameTime);
bool getDtsFromPts(uint64_t *time);
/// Returns pts-dts for given frame
bool getPtsDtsDelta(uint64_t *frameTime);
bool getPtsDtsDelta(uint64_t frametime, uint64_t *delta);
/******************************* Post Processing ************************************/
uint8_t setPostProc( uint32_t type, uint32_t strength, bool swapuv);
uint8_t getPostProc( uint32_t *type, uint32_t *strength,bool *swapuv);
Expand Down
9 changes: 7 additions & 2 deletions avidemux/common/ADM_editor/include/ADM_segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,27 @@ class _VIDEOS
\brief The video is a collection of segment.
Each segment refers to its source (the reference) and the part of the source the segment is made of.
*/

#define ADM_NO_DROP 0
#define ADM_DROPPING 2
#define ADM_DROP_MAYBE_AFER_SWITCH 1

class _SEGMENT
{
public:
uint32_t _reference; /// Reference video
uint64_t _refStartTimeUs; /// Starting time in reference
uint64_t _startTimeUs; /// Start time in current (=sum(_duration of previous seg))
uint64_t _durationUs; ///
uint32_t _dropBframes;
uint32_t _dropBframes; /// Internal state machine to know is we should drop bframe that are orphean
uint64_t _refStartDts;
void clear(void)
{
_reference=0;
_refStartTimeUs=0;
_startTimeUs=0;
_durationUs=0;
_dropBframes=0;
_dropBframes=ADM_NO_DROP;
_refStartDts=0;
}
_SEGMENT() {clear();}
Expand Down
2 changes: 1 addition & 1 deletion avidemux/common/ADM_editor/src/ADM_edRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ bool ADM_Composer::GoToIntraTime_noDecoding(uint64_t time,uint32_t *tofra
dts=time;

_nextFrameDts=dts;
seg->_dropBframes=1;
seg->_dropBframes=ADM_DROP_MAYBE_AFER_SWITCH;
return true;
}
/**
Expand Down
12 changes: 6 additions & 6 deletions avidemux/common/ADM_editor/src/ADM_edSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,21 +149,21 @@ bool r;
\fn getPtsDtsDelta
*/

bool ADM_Composer::getPtsDtsDelta(uint64_t *frameTime)
bool ADM_Composer::getPtsDtsDelta(uint64_t frameTime, uint64_t *outDelta)
{
uint64_t refTime,nkTime,segTime;
int lastSeg=_segments.getNbSegments();
uint32_t seg;
bool r;
// 1- Convert frameTime to segments
if(false== _segments.convertLinearTimeToSeg( *frameTime, &seg, &segTime))
if(false== _segments.convertLinearTimeToSeg( frameTime, &seg, &segTime))
{
ADM_warning(" Cannot find seg for time %" PRId64"\n",*frameTime);
ADM_warning(" Cannot find seg for time %" PRId64"\n",frameTime);
return false;
}
//
_SEGMENT *s=_segments.getSegment(seg);
int64_t delta=*frameTime-s->_startTimeUs; // Delta compared to the beginning of this seg
int64_t delta=(int64_t)frameTime-(int64_t)s->_startTimeUs; // Delta compared to the beginning of this seg

delta+=s->_refStartTimeUs;
if(delta<0)
Expand All @@ -178,11 +178,11 @@ bool r;
if(false==_segments.dtsFromPts(ref,refTime,&dts))
{
ADM_error("Cannot get dtsFromDts for time %" PRIu64"\n",refTime);
*frameTime=0;
*outDelta=0;
return false;
}
// Ok we have PTS and DTS, returns difference
*frameTime=refTime-dts;
*outDelta=refTime-dts;
return true;
}
/**
Expand Down
95 changes: 87 additions & 8 deletions avidemux/common/ADM_editor/src/ADM_edVideoCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,87 @@ bool ADM_Composer::checkCutsAreOnIntra(void)
*/
static bool bFrameDroppable(uint32_t fcc)
{
if(isH264Compatible(fcc)) return false;
if(isH264Compatible(fcc))
return false;
if(isH265Compatible(fcc))
return false;
return true;
}
/**
*
* @param time
* @param delay
* @return
*/
bool ADM_Composer::getNonClosedGopDelay(uint64_t time,uint32_t *delay)
{
aviInfo info;
uint32_t segNo;
uint64_t segTime;
*delay=0;
if(!_segments.convertLinearTimeToSeg(time,&segNo,&segTime))
{
ADM_warning("Cannot navigate to get nonclosedgop\n");
return false;
}
_SEGMENT *seg=_segments.getSegment(segNo);
ADM_assert(seg);
_VIDEOS *vid=_segments.getRefVideo(seg->_reference);
uint64_t pts,dts;

vid->_aviheader->getVideoInfo (&info);
//
if(bFrameDroppable(info.fcc))
{
return true; // no need to add extra delay
}
// Look ahead to see if we have some late bframe in the past
int nb=vid->_aviheader->getMainHeader ()->dwTotalFrames;
int found=-1;
if(!segTime)
{
found=0;
vid->_aviheader->getPtsDts(0,&pts,&dts);
}
else
for(int i=0;i<nb;i++)
{
vid->_aviheader->getPtsDts (i,&pts,&dts);
if(pts==segTime)
{
found=i;
break;
}
}
if(found==-1)
{
ADM_warning("Cannot find the frame\n");
return false;
}
for(int i=found+1;i<found+16;i++)
{
uint32_t flags;
vid->_aviheader->getFlags(i,&flags);
if(!(flags & AVI_B_FRAME))
{
ADM_info("Not a bframe, stopping (%d)\n",i-found);
break;
}
vid->_aviheader->getPtsDts(i,&pts,&dts);
if(pts<segTime)
{
ADM_info("frame %d is early \n",i);
uint32_t delta=segTime-pts;
if(delta>*delay) *delay=delta;
}else
{
ADM_info("Pts delta = %d\n",(int)(pts-segTime));
}
}
ADM_info("Found maximum non closed gop delay = %d\n",*delay);
return true;
}

/**
\fn getCompressedPicture
\brief bypass decoder and directly get the source image
Expand Down Expand Up @@ -143,7 +221,7 @@ bool ADM_Composer::getCompressedPicture(uint64_t videoDelay,ADMCompressed
{
if(img->flags & AVI_B_FRAME)
{
if(seg->_dropBframes==2)
if(seg->_dropBframes==ADM_DROPPING)
{
ADM_warning("%" PRIu32" Dropping bframes\n",fn);
goto againGet;
Expand All @@ -152,8 +230,9 @@ bool ADM_Composer::getCompressedPicture(uint64_t videoDelay,ADMCompressed
{ // not a bframe
switch(seg->_dropBframes)
{
case 2: seg->_dropBframes=0;break;
case 1: seg->_dropBframes=2;break;
case ADM_NO_DROP : break;
case ADM_DROPPING : seg->_dropBframes=ADM_NO_DROP;break;
case ADM_DROP_MAYBE_AFER_SWITCH : seg->_dropBframes=ADM_DROPPING;break;
default: break;
}
}
Expand All @@ -174,7 +253,7 @@ bool ADM_Composer::getCompressedPicture(uint64_t videoDelay,ADMCompressed
}
// Seeking is not accurate when cutting on non intra
// we might have some frames that are clearly too early , even in seg0
if(img->demuxerPts!=ADM_NO_PTS)
if(img->demuxerPts!=ADM_NO_PTS && bFrameDroppable(info.fcc))
{
if(img->demuxerPts+seg->_startTimeUs<seg->_refStartTimeUs)
{
Expand Down Expand Up @@ -232,8 +311,8 @@ bool ADM_Composer::getCompressedPicture(uint64_t videoDelay,ADMCompressed
// border case due to rounding we can have pts slighly above dts
if(signedPts!=ADM_NO_PTS && _nextFrameDts!=ADM_NO_PTS)
{
signedDts=_nextFrameDts;
if(signedPts != ADM_NO_PTS && signedDts>signedPts)
signedDts=_nextFrameDts;
if(signedPts != ADM_NO_PTS && signedDts>signedPts)
{
// not sure it is correct. We may want to do it the other way around, i.e. bumping pts
ADM_warning("Compensating for rounding error with PTS=%" PRId64"ms DTS=%" PRId64"ms \n",signedPts,signedDts);
Expand Down Expand Up @@ -305,7 +384,7 @@ bool ADM_Composer::getCompressedPicture(uint64_t videoDelay,ADMCompressed
}
// Mark it as drop b frames...
_SEGMENT *thisseg=_segments.getSegment(_currentSegment);
thisseg->_dropBframes=1;
thisseg->_dropBframes=ADM_DROP_MAYBE_AFER_SWITCH;
ADM_info("Retrying for next segment\n");
return getCompressedPicture(videoDelay,img);

Expand Down
19 changes: 16 additions & 3 deletions avidemux/common/ADM_muxerGate/src/ADM_videoCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,25 @@ ADM_videoStreamCopy::ADM_videoStreamCopy(uint64_t startTime,uint64_t endTime)
ptsStart=dtsStart=startTime;
}else
{
uint64_t delta=ptsStart;
video_body->getPtsDtsDelta(&delta);
// Do we have non droppable b frame ?
uint32_t bframeDelay;
if(true==video_body->getNonClosedGopDelay(ptsStart,&bframeDelay))
{
ADM_info("Some B frames are non droppable, increasing delat by %d us\n",bframeDelay);
videoDelay+=bframeDelay;
}else
{
videoDelay=0;
}

uint64_t delta=0;
video_body->getPtsDtsDelta(ptsStart,&delta);

ADM_info("PTS/DTS delta=%" PRIu64" us\n",delta);
//videoDelay
if(delta>ptsStart)
{
videoDelay=delta-ptsStart;
videoDelay+=delta-ptsStart;
dtsStart=0;
ADM_info("Dts is too early, delaying everything by %" PRIu64" ms\n",videoDelay/1000);
}else
Expand All @@ -68,6 +79,8 @@ ADM_videoStreamCopy::ADM_videoStreamCopy(uint64_t startTime,uint64_t endTime)
}
eofMet=false;



this->startTimeDts=dtsStart;
this->startTimePts=ptsStart;
this->endTimePts=endTime;
Expand Down

0 comments on commit a1806d3

Please sign in to comment.