Skip to content

Commit

Permalink
[editor,muxerGate/videoCopy] Double frame increment for field encoded…
Browse files Browse the repository at this point in the history
… ref videos when not in copy mode

This patch relies on demuxer to set flags right. Only MPEG-PS and MPEG-TS demuxers are capable of doing that for now.
  • Loading branch information
eumagga0x2a committed Mar 6, 2020
1 parent fd995c1 commit 4341938
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 15 deletions.
4 changes: 2 additions & 2 deletions avidemux/common/ADM_editor/include/ADM_edit.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -291,9 +291,9 @@ public:
uint8_t getVideoInfo(aviInfo *info); // for common timebase, call getTimeBase afterwards
_VIDEOS* getRefVideo(int videoIndex);
uint64_t getVideoDuration(void);
uint64_t getFrameIncrement(void); /// Returns the # of us between 2 frames or the smaller value of them
uint64_t getFrameIncrement(bool forCopyMode=false); /// Returns the # of us between 2 frames or the smaller value of them
int getVideoCount(void);
bool getTimeBase(uint32_t *scale, uint32_t *rate); // common timebase or an approximation for all videos within the selection
bool getTimeBase(uint32_t *scale, uint32_t *rate, bool forCopyMode=false); // common timebase or an approximation for all videos within the selection

/**************************************** /Video Info **************************/
/***************************************** Project Handling ********************/
Expand Down
3 changes: 3 additions & 0 deletions avidemux/common/ADM_editor/include/ADM_segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class _VIDEOS
decoders *decoder; /// Video codec
ADMColorScalerSimple *color; /// Color conversion if needed
bool dontTrustBFramePts;
bool fieldEncoded;
/* Audio part */
uint32_t currentAudioStream;
std::vector <ADM_audioStreamTrack *> audioTracks;
Expand All @@ -83,6 +84,8 @@ class _VIDEOS

_VIDEOS()
{
dontTrustBFramePts=false;
fieldEncoded=false;
currentAudioStream=0;
_aviheader=NULL;
decoder=NULL;
Expand Down
4 changes: 2 additions & 2 deletions avidemux/common/ADM_editor/include/IEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class IEditor {
virtual void getCurrentFrameFlags(uint32_t *flags, uint32_t *quantiser) = 0;
virtual uint64_t getCurrentFramePts(void) = 0;
virtual bool getDirectImageForDebug(uint32_t frameNum, ADMCompressedImage *img) = 0;
virtual uint64_t getFrameIncrement(void) = 0;
virtual uint64_t getFrameIncrement(bool copy=false) = 0;
virtual uint64_t getMarkerAPts() = 0;
virtual uint64_t getMarkerBPts() = 0;
virtual uint32_t getNbSegment(void) = 0;
Expand All @@ -61,7 +61,7 @@ class IEditor {
virtual int getVideoCount(void) = 0;
virtual uint64_t getVideoDuration(void) = 0;
virtual uint8_t getVideoInfo(aviInfo *info) = 0;
virtual bool getTimeBase(uint32_t *scale, uint32_t *rate) = 0;
virtual bool getTimeBase(uint32_t *scale, uint32_t *rate, bool copy=false) = 0;
virtual _VIDEOS* getRefVideo(int videoIndex) = 0;
virtual bool getVideoPtsDts(uint32_t frame, uint32_t *flags, uint64_t *pts, uint64_t *dts) = 0;
virtual bool goToIntraTimeVideo(uint64_t time) = 0;
Expand Down
2 changes: 1 addition & 1 deletion avidemux/common/ADM_editor/src/ADM_edRenderInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ bool ADM_Composer::DecodeNextPicture(uint32_t ref)
aprintf("[Editor] No PTS, guessing value\n");
aprintf("Image Pts : %s\n",ADM_us2plain(img.demuxerPts));
aprintf("Image Dts : %s\n",ADM_us2plain(img.demuxerDts));
vid->lastDecodedPts+=vid->timeIncrementInUs;
vid->lastDecodedPts += vid->timeIncrementInUs * (vid->fieldEncoded ? 2 : 1);
uint64_t pts=img.demuxerPts;
uint64_t dts=img.demuxerDts;
uint32_t origin=0;
Expand Down
63 changes: 57 additions & 6 deletions avidemux/common/ADM_editor/src/ADM_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ static bool checkStdTimeBase(uint32_t &num, uint32_t &den)
/**
\fn getTimeBase
*/
bool ADM_Composer::getTimeBase(uint32_t *scale, uint32_t *rate)
bool ADM_Composer::getTimeBase(uint32_t *scale, uint32_t *rate, bool copyMode)
{
/* Using MPEG timescale as fallback */
*scale=1;
Expand Down Expand Up @@ -295,6 +295,7 @@ bool ADM_Composer::getTimeBase(uint32_t *scale, uint32_t *rate)
{
_VIDEOS *vid=_segments.getRefVideo(ListOfRefs.at(i));
ADM_assert(vid);
ADM_info("Ref video %u is %s-encoded, copy mode: %d\n",ListOfRefs.at(i),vid->fieldEncoded? "field" : "frame",copyMode);
vidHeader *demuxer=vid->_aviheader;
ADM_assert(demuxer);
aviInfo info;
Expand All @@ -303,11 +304,45 @@ bool ADM_Composer::getTimeBase(uint32_t *scale, uint32_t *rate)
{
myscale=info.timebase_num;
myrate=info.timebase_den;
checkStdTimeBase(myscale,myrate);
if(false==checkStdTimeBase(myscale,myrate))
return false;
if(vid->fieldEncoded && !copyMode)
{
switch(myrate)
{
case 60000:
case 50000:
case 48000:
ADM_info("Halving timebase denominator %u for field-encoded ref video.\n",myrate);
myrate/=2;
break;
default:
ADM_info("Doubling timebase numerator %u for field-encoded ref video.\n",myscale);
myscale*=2;
break;
}
}
continue;
}
/* FIXME properly reduce fractions when checking timebase */
checkStdTimeBase(info.timebase_num,info.timebase_den);
if(false==checkStdTimeBase(info.timebase_num,info.timebase_den))
return false;
if(vid->fieldEncoded && !copyMode)
{
switch(info.timebase_den)
{
case 60000:
case 50000:
case 48000:
ADM_info("Halving timebase denominator %u for appended field-encoded ref video.\n",info.timebase_den);
info.timebase_den/=2;
break;
default:
ADM_info("Doubling timebase numerator %u for appended field-encoded video.\n",info.timebase_num);
info.timebase_num*=2;
break;
}
}
if(info.timebase_den == myrate)
{
if(info.timebase_num < myscale)
Expand Down Expand Up @@ -770,10 +805,26 @@ uint32_t ADM_Composer::getPARHeight()
/**
\fn getFrameIncrement
*/
uint64_t ADM_Composer::getFrameIncrement(void)
uint64_t ADM_Composer::getFrameIncrement(bool copyMode)
{
if (!_segments.getNbSegments()) return 0;
return _segments.getRefVideo(0)->timeIncrementInUs;
uint32_t nb = _segments.getNbSegments();
if(!nb) return 0;
uint64_t minIncrement = 0;
for(uint32_t i=0; i<nb; i++)
{
_VIDEOS *vid = _segments.getRefVideo(i);
ADM_assert(vid);
uint64_t inc = vid->timeIncrementInUs;
if(!inc) continue;
if(!copyMode && vid->fieldEncoded)
{
ADM_info("Doubling frame increment for field-encoded ref video %u\n",i);
inc *= 2;
}
if(!minIncrement | (inc < minIncrement))
minIncrement = inc;
}
return minIncrement;
}
/**
Set decoder settings (post process/swap u&v...)
Expand Down
12 changes: 10 additions & 2 deletions avidemux/common/ADM_editor/src/ADM_segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,18 @@ bool ADM_EditorSegment::addReferenceVideo(_VIDEOS *ref)
ADM_info("Original frame increment %s = %" PRIu64" us\n",ADM_us2plain(ref->timeIncrementInUs),ref->timeIncrementInUs);
uint64_t minDelta=100000;
uint64_t maxDelta=0;
uint32_t fmin=0,fmax=0;
uint32_t flags,fmin=0,fmax=0;
for (uint32_t frame=0; frame<info.nb_frames; frame++)
{
if(!ref->fieldEncoded)
{
demuxer->getFlags(frame,&flags);
if(flags & AVI_FIELD_STRUCTURE)
{
ADM_info("Ref video is field-encoded.\n");
ref->fieldEncoded=true;
}
}
if (demuxer->getPtsDts(frame,&pts,&dts) && dts!=ADM_NO_PTS && dts!=0)
{
if (firstNonZeroDts==ADM_NO_PTS)
Expand Down Expand Up @@ -180,7 +189,6 @@ bool ADM_EditorSegment::addReferenceVideo(_VIDEOS *ref)
seg._durationUs=demuxer->getVideoDuration();

// Set the default startTime to the pts of first Pic
uint32_t flags;
demuxer->getFlags(0,&flags);
demuxer->getPtsDts(0,&pts,&dts);
ref->firstFramePts=0;
Expand Down
4 changes: 2 additions & 2 deletions avidemux/common/ADM_muxerGate/src/ADM_videoCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ ADM_videoStreamCopy::ADM_videoStreamCopy(uint64_t startTime,uint64_t endTime)
height=info.height;
fourCC=info.fcc;
averageFps1000=info.fps1000;
video_body->getTimeBase(&timeBaseNum,&timeBaseDen);
frameIncrement=video_body->getFrameIncrement();
video_body->getTimeBase(&timeBaseNum,&timeBaseDen,true);
frameIncrement=video_body->getFrameIncrement(true);
isCFR=false;
// Estimate start frame
if(false==video_body->getPKFramePTS(&ptsStart))
Expand Down

0 comments on commit 4341938

Please sign in to comment.