commit 87158e065540afb086080170a7675b82969e2bca
Author: Richard Shaw <hobbes1069(a)gmail.com>
Date: Wed Mar 27 14:49:13 2019 -0500
Add new patches.
avidemux-2.7.3-ad_lav.patch | 41 +++++++
avidemux-2.7.3-frame_matching.patch | 223 ++++++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+)
---
diff --git a/avidemux-2.7.3-ad_lav.patch b/avidemux-2.7.3-ad_lav.patch
new file mode 100644
index 0000000..9e8af8e
--- /dev/null
+++ b/avidemux-2.7.3-ad_lav.patch
@@ -0,0 +1,41 @@
+From 1d714aacd5eeb47898ad6f4ce31993e1671e8722 Mon Sep 17 00:00:00 2001
+From: eumagga0x2a <eumagga0x2a(a)users.noreply.github.com>
+Date: Mon, 25 Mar 2019 20:23:26 +0100
+Subject: [PATCH] [ad_lav] Do not skip channel mapping on decoding error
+
+---
+ .../ADM_audioDecoders/ADM_ad_lav/ADM_ad_lav.cpp | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/avidemux_plugins/ADM_audioDecoders/ADM_ad_lav/ADM_ad_lav.cpp
b/avidemux_plugins/ADM_audioDecoders/ADM_ad_lav/ADM_ad_lav.cpp
+index 21db257f8..cb69710b9 100644
+--- a/avidemux_plugins/ADM_audioDecoders/ADM_ad_lav/ADM_ad_lav.cpp
++++ b/avidemux_plugins/ADM_audioDecoders/ADM_ad_lav/ADM_ad_lav.cpp
+@@ -442,7 +442,8 @@ uint8_t ADM_AudiocoderLavcodec::run(uint8_t *inptr, uint32_t nbIn,
float *outptr
+ AVPacket pkt;
+ av_init_packet(&pkt);
+ int nbChunk,res=0;
+- while(_tail-_head>=_blockalign)
++ bool eof=false;
++ while(_tail-_head>=_blockalign && !eof)
+ {
+ nbChunk=(_tail-_head)/_blockalign;
+ pkt.size=nbChunk*_blockalign;
+@@ -458,14 +459,15 @@ uint8_t ADM_AudiocoderLavcodec::run(uint8_t *inptr, uint32_t nbIn,
float *outptr
+ if(res==AVERROR(EAGAIN)) break; // we need to send more input
+ if(res==AVERROR_EOF)
+ {
+- return 1;
++ eof=true;
++ break;
+ }
+ if(res<0)
+ {
+ char er[2048]={0};
+ av_make_error_string(er, sizeof(er)-1, res);
+ ADM_warning("[ADM_ad_lav] decoding error: %s\n",er);
+- return 1;
++ break;
+ }
+
+ bool invalid=false;
diff --git a/avidemux-2.7.3-frame_matching.patch b/avidemux-2.7.3-frame_matching.patch
new file mode 100644
index 0000000..9e07660
--- /dev/null
+++ b/avidemux-2.7.3-frame_matching.patch
@@ -0,0 +1,223 @@
+From 0ec83347e268236109049fd038feeb2b07e20862 Mon Sep 17 00:00:00 2001
+From: eumagga0x2a <eumagga0x2a(a)users.noreply.github.com>
+Date: Mon, 25 Mar 2019 21:27:41 +0100
+Subject: [PATCH] [editor] Rework how we find a frame matching given PTS,
+ optimize search for the next keyframe, fix hang seeking to the end with some
+ videos, remove unused variables
+
+This patch addresses two issues in ADM_Composer::getFrameNumFromPtsOrBefore:
+
+1) An insufficient bounds check for tmpFrame not exceeding the total number of frames in
the ref video could result in loop continuing until uint32_t has wrapped around, freezing
the application;
+
+2) Trying to identify the matching frame purely by bisect is not guaranteed to succeed
with frame reordering.
+---
+ .../common/ADM_editor/src/ADM_edSearch.cpp | 140 +++++++++++-------
+ 1 file changed, 88 insertions(+), 52 deletions(-)
+
+diff --git a/avidemux/common/ADM_editor/src/ADM_edSearch.cpp
b/avidemux/common/ADM_editor/src/ADM_edSearch.cpp
+index 4ea2ac96d..6243d5ca4 100644
+--- a/avidemux/common/ADM_editor/src/ADM_edSearch.cpp
++++ b/avidemux/common/ADM_editor/src/ADM_edSearch.cpp
+@@ -208,13 +208,19 @@ bool r;
+ */
+ bool ADM_Composer::searchNextKeyFrameInRef(int ref,uint64_t refTime,uint64_t *nkTime)
+ {
+- // Search from the end till we get a keyframe
++ int curFrame=0;
+ _VIDEOS *v=_segments.getRefVideo(ref);
++ // look up the frame we are starting from...
++ if(!getFrameNumFromPtsOrBefore(v,refTime,curFrame))
++ {
++ ADM_warning("Cannot identify the frame for time %s in
reference.\n",ADM_us2plain(refTime));
++ }
+ uint32_t nbFrame=v->_nb_video_frames;
+ uint64_t pts,dts;
+- for(int i=0;i<nbFrame;i++)
++ curFrame -= 16; // safety margin to deal with early B-frames
++ if(curFrame < 0) curFrame = 0;
++ for(int i=curFrame;i<nbFrame;i++)
+ {
+- uint64_t p;
+ uint32_t flags;
+ v->_aviheader->getFlags(i,&flags);
+ if(!(flags & AVI_KEY_FRAME)) continue;
+@@ -243,18 +249,27 @@ bool ADM_Composer::searchNextKeyFrameInRef(int ref,uint64_t
refTime,uint64_t *nk
+ */
+ bool ADM_Composer::getFrameNumFromPtsOrBefore(_VIDEOS *v,uint64_t refTime,int
&frameNumber)
+ {
++ if(refTime == ADM_NO_PTS)
++ return false;
++ if(refTime <= v->firstFramePts)
++ {
++ frameNumber = 0;
++ return true;
++ }
++
+ uint32_t nbFrame = v->_nb_video_frames;
+- uint64_t pts, dts;
++ uint64_t pts, dts, margin = v->timeIncrementInUs * 16;
++ const uint64_t rangeBegin = (refTime < margin)? 0 : (refTime - margin);
++ const uint64_t rangeEnd = refTime + margin;
+ uint32_t curFrame = nbFrame >> 1;
+ uint32_t splitMoval = (curFrame + 1) >> 1;
+ uint32_t minFrame = 0;
++ bool worked = false;
+ pivotPrintf("Looking for frame with pts %" PRIu64" us
(%s)\n",refTime,ADM_us2plain(refTime));
+ // Try to find the frame that as the timestamp close enough to refTime, while being
smaller
+ do
+ {
+ // seems like the pts determination, not always works -> retry if necessary
+- bool worked;
+- uint32_t skipped = 0;
+ uint32_t tmpFrame = curFrame;
+ do
+ {
+@@ -262,54 +277,47 @@ bool ADM_Composer::getFrameNumFromPtsOrBefore(_VIDEOS *v,uint64_t
refTime,int &f
+ worked = v->_aviheader->getPtsDts(tmpFrame,&pts,&dts);
+ if(worked && pts != ADM_NO_PTS)
+ break; // found
+- if(!tmpFrame)
++ if(tmpFrame <= minFrame)
+ {
+- ADM_warning("The whole segment is corrupted. Aborting the
search\n");
+- return false;
++ ADM_warning("Frames between %" PRIu32" and %"
PRIu32" have no PTS.\n",minFrame,curFrame);
++ break;
+ }
+ tmpFrame--;
+- skipped++;
+ } while(true);
+- if(pts == refTime)
+- break;
+- if(skipped && pts < refTime)
+- { // if we slid past the target frame...
+- pivotPrintf("skipped %" PRIu32" frames seeking
back\n",skipped);
+- skipped = 0;
+- tmpFrame = curFrame + 1; // ...go back to the frame where we first
encountered corrupted video...
++ if(pts == ADM_NO_PTS)
++ {
++ tmpFrame = curFrame + 1;
+ do
+- { // ...and seek forward until we get a valid pts
+- pts = ADM_NO_PTS;
+- worked = v->_aviheader->getPtsDts(tmpFrame,&pts,&dts);
+- if(worked && pts != ADM_NO_PTS)
+- break; // found
+- tmpFrame++;
+- if(tmpFrame == nbFrame)
+- {
+- ADM_warning("The whole segment is corrupted. Aborting the
search\n");
+- return false;
+- }
+- skipped++;
+- } while(true);
+- if(skipped)
+ {
+- pivotPrintf("skipped %" PRIu32" frames seeking
forward\n",skipped);
+- if(pts > refTime)
++ if(tmpFrame >= nbFrame)
+ {
+- ADM_warning("The video at the specified time in ref is
corrupted. Aborting seek\n");
++ ADM_warning("The whole segment is corrupted, aborting
seek.\n");
+ return false;
+- }else
+- {
+- minFrame = tmpFrame;
+ }
+- }
+- curFrame = tmpFrame;
++ minFrame = tmpFrame;
++ worked = v->_aviheader->getPtsDts(tmpFrame,&pts,&dts);
++ if(worked && pts != ADM_NO_PTS)
++ break; // found
++ tmpFrame++;
++ } while(true);
+ }
++ curFrame = tmpFrame; // resync
++ // are we lucky?
++ if(pts == refTime)
++ {
++ pivotPrintf("Perfect match for frame %"
PRIu32"\n",curFrame);
++ frameNumber = curFrame;
++ return true;
++ }
++ // nope, are we at least close enough?
++ if(pts != ADM_NO_PTS && pts >= rangeBegin && pts <=
rangeEnd)
++ break; // switch to linear search
++ // nope, continue to bisect
+ pivotPrintf("SplitMoval=%d\n",splitMoval);
+- if(!splitMoval)
+- break;
++ if(splitMoval < 16)
++ break;
+ pivotPrintf("Pivot frame is %" PRIu32" at
%s\n",curFrame,ADM_us2plain(pts));
+- if (pts >= refTime)
++ if (pts > refTime)
+ {
+ if (curFrame <= splitMoval + minFrame)
+ {
+@@ -324,18 +332,47 @@ bool ADM_Composer::getFrameNumFromPtsOrBefore(_VIDEOS *v,uint64_t
refTime,int &f
+ if(curFrame >= nbFrame)
+ curFrame = nbFrame - 1;
+ }
+- if(splitMoval > 1)
+- splitMoval++;
++ splitMoval++;
+ splitMoval >>= 1;
+- pivotPrintf("Split=%d\n",splitMoval);
+ } while(refTime != pts);
+
+- pivotPrintf("Matching frame is %" PRIu32" at
%s\n",curFrame,ADM_us2plain(pts));
+- if(pts > refTime && curFrame)
+- curFrame--;
+- pivotPrintf("Our target frame is %" PRIu32"\n",curFrame);
+- frameNumber = curFrame;
+- return true;
++ // linear search with a generous safety margin
++ curFrame = (curFrame < 32)? 0 : curFrame - 32;
++ pivotPrintf("Starting linear search at frame %" PRIu32", total
frames: %" PRIu32"\n",curFrame,nbFrame);
++ int candidate = -1;
++ uint64_t last = 0;
++ for(int i = 0; i < 65; i++)
++ {
++ if(curFrame >= nbFrame) break;
++ pts = ADM_NO_PTS;
++ worked = v->_aviheader->getPtsDts(curFrame,&pts,&dts);
++ if(!worked || pts == ADM_NO_PTS)
++ {
++ pivotPrintf("Linear search, skipping frame %"
PRIu32"\n",curFrame);
++ curFrame++;
++ continue;
++ }
++ if(pts == refTime)
++ {
++ pivotPrintf("Perfect match for frame %"
PRIu32"\n",curFrame);
++ frameNumber = curFrame;
++ return true;
++ }
++ if(pts >= rangeBegin && pts > last && pts < refTime)
++ {
++ candidate = curFrame;
++ last = pts;
++ }
++ curFrame++;
++ }
++ if(candidate >= 0)
++ {
++ ADM_info("Best candidate for time %s in reference is frame %"
PRIu32"\n",ADM_us2plain(refTime),candidate);
++ frameNumber = candidate;
++ return true;
++ }
++ ADM_warning("Search for frame matching time %s in reference
failed.\n",ADM_us2plain(refTime));
++ return false;
+ }
+ /**
+ \fn searchPreviousKeyFrameInRef
+@@ -365,7 +402,6 @@ bool ADM_Composer::searchPreviousKeyFrameInRef(int ref,uint64_t
refTime,uint64_t
+ // rewind until we find a keyframe
+ for (int i=curFrame; i>=0; i--)
+ {
+- uint64_t p;
+ uint32_t flags;
+ v->_aviheader->getFlags(i,&flags);
+ if(!(flags & AVI_KEY_FRAME))