Avidemux Forum

Avidemux => Main version 2.6 => Topic started by: KoolAidMan on December 29, 2012, 08:56:27 PM

Title: Investigating a source of audio drift
Post by: KoolAidMan on December 29, 2012, 08:56:27 PM
I have a video file which encodes fine in 2.5, but in 2.6 I am seeing a significant amount of audio drift whenever there are null frames. I believe the drift is due to a bug in the MuxerAvi. Here is the log:

 [setAudioStreamInfo]  [ODML] Audio track 0, using ODML placeholder of size 16384 bytes, odmltrack=1, pos=0x4142
[ODML]write dummy chunk at file position 33098 with data size 260
 [saveBegin]  SuperIndex position so far 0 : 212
 [saveBegin]  SuperIndex position so far 1 : 16706
 [saveBegin]  SuperIndex position so far 2 : 0
[AviMuxer] Saving
 [save]  [AviMuxer]avg fps=59941
 [initUI]  Muxer, creating UI, video duration is  02:27:06,705
 [startThread]  Starting thread...
 [startThread]  Thread created and started
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
 [encode]  [x264] Null frame
[ODML]write dummy chunk at file position 33386 with data size 131072
 [goToTime]   go to time 0.28 secs
 [goToTime]  => seg 0, rel time 0.28 secs
 [resetAfterSeek]   flushing after seek
 [fillAudio]  [AviMuxer] Audio skew!
[audioClock] Drift detected :0 vs 414097, delta=414097
Percent:0
[ODML]write dummy chunk at file position 261416 with data size 131072
 [fillAudio]  [AviMuxer] Audio skew!
[audioClock] Drift detected :446097 vs 414097, delta=-32000
Percent:0
Title: Re: Investigating a source of audio drift
Post by: KoolAidMan on December 29, 2012, 08:59:50 PM
I believe this bug may be related to a warning in the MuxerAvi.


bool muxerAvi::fillAudio(uint64_t targetDts)
{
// Now send audio until they all have DTS > lastVideoDts+increment
            for(int audioIndex=0;audioIndex<nbAStreams;audioIndex++)
            {
                ADM_audioStream*a=aStreams[audioIndex];
                uint32_t fq=a->getInfo()->frequency;
                int nb=0;
                audioClock *clk=clocks[audioIndex];
                aviAudioPacket *aPacket=audioPackets+audioIndex;
                if(true==aPacket->eos) return true;
                while(1)
                {
                    if(false==aPacket->present)
                    {
                        if(!a->getPacket(aPacket->buffer,
                                         &(aPacket->sizeInBytes),
                                         AUDIO_BUFFER_SIZE,
                                         &(aPacket->nbSamples),
                                         &(aPacket->dts)))
                        {
                                ADM_warning("Cannot get audio packet for stream %d\n",audioIndex);
                                aPacket->eos=true;
                                break;
                        }
                            if(aPacket->dts!=ADM_NO_PTS)
                            {
                                aPacket->dts+=audioDelay;
                            }
                            aprintf("[Audio] Packet size %"PRIu32" sample:%"PRIu32" dts:%"PRIu64" target :%"PRIu64"\n",
                                            aPacket->sizeInBytes,aPacket->nbSamples,aPacket->dts,targetDts);
                            if(aPacket->dts!=ADM_NO_PTS)
                                if( abs(aPacket->dts-clk->getTimeUs())>32000)
                                {
                                    ADM_warning("[AviMuxer] Audio skew!\n");
                                    clk->setTimeUs(aPacket->dts);
#warning FIXME add padding
                                }
                            aPacket->present=true;
                    }
                    // We now have a packet stored
                    if(aPacket->dts!=ADM_NO_PTS)
                        if(aPacket->dts>targetDts) break; // this one is in the future
                    nb=writter.saveAudioFrame(audioIndex,aPacket->sizeInBytes,aPacket->buffer) ;
                    encoding->pushAudioFrame(aPacket->sizeInBytes);
                    clk->advanceBySample(aPacket->nbSamples);
                    aPacket->present=false;
                    //printf("%u vs %u\n",audioDts/1000,(lastVideoDts+videoIncrement)/1000);
                }
            }

            return true;
}


Seeing if there's a change I can make to stop the audio drift...
Title: Re: Investigating a source of audio drift
Post by: mean on December 29, 2012, 09:01:00 PM
The delta is the difference between the expected DTS and the actual DTS
If the audio is in copy mode, it could mean the source is discontinuous or a bug in the reader part
(or you played with DTS :) )

The #warning says there should be some audio frame duplication going on to fill the gap
Title: Re: Investigating a source of audio drift
Post by: KoolAidMan on December 29, 2012, 09:17:08 PM
This drift is happening in 2.6.1-- without any modifications from me. I didn't play with the dts this time ;). I'll see if adding the frame duplication resolves the drifting issue.
Title: Re: Investigating a source of audio drift
Post by: KoolAidMan on December 30, 2012, 10:18:05 AM
This patch fixes the audio drift for my video in 2.6. Of course, the dts is now non-monotonic, so I need to make some adjustments to the patch tomorrow before I submit it to the patch gallery.


Index: avidemux/common/ADM_audioFilter/src/audiocopy.cpp
===================================================================
--- avidemux/common/ADM_audioFilter/src/audiocopy.cpp (revision 8341)
+++ avidemux/common/ADM_audioFilter/src/audiocopy.cpp (working copy)
@@ -34,12 +34,13 @@
                         ADM_audioStream *in;
                         uint64_t        startTime;
                         int64_t         shift;
+                        bool            dupe;
         public:

                        ADM_audioStreamCopy(ADM_audioStream *input,uint64_t startTime, int64_t shift); 
virtual                 WAVHeader                *getInfo(void) {return in->getInfo();};
virtual uint8_t         getPacket(uint8_t *buffer,uint32_t *size, uint32_t sizeMax,uint32_t *nbSample,uint64_t *dts);
-//virtual bool            goToTime(uint64_t nbUs);
+virtual bool            goToTime(uint64_t nbUs);
virtual bool             getExtraData(uint32_t *l, uint8_t **d);
          uint64_t        getDurationInUs(void);
          bool            isCBR();
@@ -53,8 +54,14 @@
     this->startTime=startTime;
     in->goToTime(startTime);
     this->shift=shift;
+    this->dupe=false;
}

+bool  ADM_audioStreamCopy::goToTime(uint64_t nbUs)
+{
+    return this->in->goToTime(nbUs);
+}
+
bool ADM_audioStreamCopy::isCBR()
{
     return in->isCBR();
@@ -74,14 +81,29 @@
     if(false==in->getPacket(buffer,size,sizeMax,nbSample,dts)) return false;
     if(*dts!=ADM_NO_PTS)
     {
-       
         int64_t corrected=*dts;
         corrected+=shift;
-        if(corrected<startTime) goto again; // cant have <0 dts
-        *dts=corrected-startTime;
+
+        if(corrected<0)
+        {
+            dupe=true;
+        }
+        else if(dupe)
+        {
+            shift=*dts;
+            in->goToTime(corrected);
+            dupe=false;
+        }
+        else if(corrected<startTime)
+        {
+            goto again;
+        }
+        else
+        {
+            *dts=corrected-startTime;
+        }
     }
     return true;
-
}
/**
         \fn audioCreateCopyStream
Index: avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.h
===================================================================
--- avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.h (revision 8341)
+++ avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.h (working copy)
@@ -58,6 +58,8 @@
         uint8_t         *videoBuffer;
         audioClock      **clocks;
         uint64_t        audioDelay;
+        int64_t         *padding;
+        uint64_t        *setTimeDts;
public:
                 muxerAvi();
         virtual ~muxerAvi();
Index: avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.cpp
===================================================================
--- avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.cpp (revision 8341)
+++ avidemux_plugins/ADM_muxers/muxerAvi/muxerAvi.cpp (working copy)
@@ -40,6 +40,8 @@
     audioPackets=NULL;
     videoBuffer=NULL;
     clocks=NULL;
+    padding=NULL;
+    setTimeDts=NULL;
};
/**
     \fn     muxerAVI
@@ -56,6 +58,9 @@
         delete [] clocks;
         clocks=NULL;
     }
+   
+    delete [] padding;
+    delete [] setTimeDts;
}

/**
@@ -79,9 +84,16 @@
         vStream=s;
         nbAStreams=nbAudioTrack;
         aStreams=a;
-        clocks=new audioClock*[nbAStreams];
+        clocks=new audioClock*[nbAStreams];       
+        padding=new int64_t[nbAStreams];
+        setTimeDts=new uint64_t[nbAStreams];
+       
         for(int i=0;i<nbAStreams;i++)
+        {
             clocks[i]=new audioClock(a[i]->getInfo()->frequency);
+            padding[i]=0;
+            setTimeDts[i]=0;
+        }
         
         return true;
}
@@ -121,12 +133,43 @@
                             aprintf("[Audio] Packet size %"PRIu32" sample:%"PRIu32" dts:%"PRIu64" target :%"PRIu64"\n",
                                             aPacket->sizeInBytes,aPacket->nbSamples,aPacket->dts,targetDts);
                             if(aPacket->dts!=ADM_NO_PTS)
-                                if( abs(aPacket->dts-clk->getTimeUs())>32000)
+                            {
+                                int64_t delta=aPacket->dts-clk->getTimeUs();
+                               
+                                if(delta>32000||delta<0)
                                 {
                                     ADM_warning("[AviMuxer] Audio skew!\n");
                                     clk->setTimeUs(aPacket->dts);
-#warning FIXME add padding
+                                    padding[audioIndex]+=delta-32000;
+                                   
+                                    if(setTimeDts[audioIndex])
+                                    {
+                                        setTimeDts[audioIndex]+=delta;
+                                    }
+                                    else if(padding[audioIndex]>32000)
+                                    {
+                                        setTimeDts[audioIndex]=aPacket->dts;
+                                    }
                                 }
+                            }
+                           
+                            if(padding[audioIndex]>=32000)
+                            {
+                                padding[audioIndex]-=32000;
+                            }
+                            else if(setTimeDts[audioIndex])
+                            {
+                                ADM_info("[AviMuxer] Rewinding audio stream\n");
+                                a->goToTime(setTimeDts[audioIndex]);
+                                clk->setTimeUs(setTimeDts[audioIndex]);
+                                setTimeDts[audioIndex]=0;
+                            }
+                           
                             aPacket->present=true;
                     }
                     // We now have a packet stored
Title: Re: Investigating a source of audio drift
Post by: KoolAidMan on December 30, 2012, 09:39:43 PM
Patch has been submitted to the patch gallery. It is slightly different from the patch above.