Ticket #7964: mythtv_smoothsync.8.patch

File mythtv_smoothsync.8.patch, 54.4 KB (added by Mark Spieth, 14 years ago)

for post hdaudio

  • mythtv/libs/libmyth/audiooutput.h

    commit 8ef87b6b0534a2656ec4307819e0749f6c49d4e5
    Author: Mark Spieth <mspieth@digivation.com.au>
    Date:   Tue Apr 27 07:51:51 2010 +1000
    
        smoother vsync with predictive frame skipping
    
    diff --git a/mythtv/libs/libmyth/audiooutput.h b/mythtv/libs/libmyth/audiooutput.h
    index 8947981..4fe5b8f 100644
    a b  
    33
    44#include <QString>
    55
     6#include "compat.h"
    67#include "audiosettings.h"
    78#include "mythcorecontext.h"
    89#include "volumebase.h"
    class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    4142
    4243    virtual void Reset(void) = 0;
    4344
    44     virtual bool AddSamples(void *buffer, int samples, long long timecode) = 0;
     45    virtual bool AddSamples(void *buffer, int samples, int64_t timecode) = 0;
    4546
    46     virtual void SetTimecode(long long timecode) = 0;
     47    virtual void SetTimecode(int64_t timecode) = 0;
    4748    virtual bool IsPaused(void) const = 0;
    4849    virtual void Pause(bool paused) = 0;
    4950    virtual void PauseUntilBuffered(void) = 0;
    class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    5152    // Wait for all data to finish playing
    5253    virtual void Drain(void) = 0;
    5354
    54     virtual int GetAudiotime(void) = 0;
     55    virtual int64_t GetAudiotime(void) = 0;
    5556
    5657    /// report amount of audio buffered in milliseconds.
    57     virtual int GetAudioBufferedTime(void) { return 0; }
     58    virtual int64_t GetAudioBufferedTime(void) { return 0; }
    5859
    5960    virtual void SetSourceBitrate(int ) { }
    6061
  • mythtv/libs/libmyth/audiooutputbase.cpp

    diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
    index 9213adf..dbb3815 100644
    a b AudioOutputBase::AudioOutputBase(const AudioSettings &settings) : 
    5656    passthru(false),            enc(false),
    5757    reenc(false),
    5858    stretchfactor(1.0f),
     59    eff_stretchfactor(100000),
    5960
    6061    source(settings.source),    killaudio(false),
    6162
    void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor) 
    179180        return;
    180181
    181182    stretchfactor = lstretchfactor;
     183    eff_stretchfactor = (int)(100000.0f * lstretchfactor + 0.5);
    182184    if (pSoundStretch)
    183185    {
    184186        VBGENERAL(QString("Changing time stretch to %1").arg(stretchfactor));
    void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor) 
    202204            bytes_per_frame = source_channels *
    203205                              AudioOutputSettings::SampleSize(FORMAT_FLT);
    204206            waud = raud = 0;
     207            reset_active.Ref();
    205208        }
    206209    }
    207210}
    bool AudioOutputBase::ToggleUpmix(void) 
    236239    audio_buflock.lock();
    237240    avsync_lock.lock();
    238241    waud = raud = 0;
     242    reset_active.Ref();
    239243
    240244    configured_channels =
    241245        configured_channels == max_channels ? 2 : max_channels;
    void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings) 
    311315    QMutexLocker lockav(&avsync_lock);
    312316
    313317    waud = raud = 0;
     318    reset_active.Clear();
    314319    actually_paused = processing = false;
    315320
    316321    channels               = settings.channels;
    void AudioOutputBase::Reset() 
    582587    QMutexLocker lock(&audio_buflock);
    583588    QMutexLocker lockav(&avsync_lock);
    584589
    585     raud = waud = audbuf_timecode = audiotime = frames_buffered = 0;
     590    audbuf_timecode = audiotime = frames_buffered = 0;
     591    waud = raud;    // empty ring buffer
     592    reset_active.Ref();
    586593    current_seconds = -1;
    587594    was_paused = !pauseaudio;
    588595
    void AudioOutputBase::Reset() 
    596603 * Used by mythmusic for seeking since it doesn't provide timecodes to
    597604 * AddSamples()
    598605 */
    599 void AudioOutputBase::SetTimecode(long long timecode)
     606void AudioOutputBase::SetTimecode(int64_t timecode)
    600607{
    601608    audbuf_timecode = audiotime = timecode;
    602     frames_buffered = (long long)((timecode * source_samplerate) / 1000);
     609    frames_buffered = (int64_t)((timecode * source_samplerate) / 1000);
    603610}
    604611
    605612/**
    int AudioOutputBase::audioready() 
    654661/**
    655662 * Calculate the timecode of the samples that are about to become audible
    656663 */
    657 int AudioOutputBase::GetAudiotime(void)
     664int64_t AudioOutputBase::GetAudiotime(void)
    658665{
    659666    if (audbuf_timecode == 0)
    660667        return 0;
    661668
    662     int soundcard_buffer = 0;
    663669    int obpf = output_bytes_per_frame;
    664     int totalbuffer;
    665     long long oldaudiotime;
     670    int64_t oldaudiotime;
    666671
    667672    /* We want to calculate 'audiotime', which is the timestamp of the audio
    668        which is leaving the sound card at this instant.
     673       Which is leaving the sound card at this instant.
    669674
    670675       We use these variables:
    671676
    int AudioOutputBase::GetAudiotime(void) 
    677682       'totalbuffer' is the total # of bytes in our audio buffer, and the
    678683       sound card's buffer. */
    679684
    680     soundcard_buffer = GetBufferedOnSoundcard(); // bytes
    681685
    682686    QMutexLocker lockav(&avsync_lock);
    683687
     688    int64_t soundcard_buffer = GetBufferedOnSoundcard(); // bytes
     689    int64_t main_buffer = audioready();
     690
    684691    /* audioready tells us how many bytes are in audiobuffer
    685692       scaled appropriately if output format != internal format */
    686     totalbuffer = audioready() + soundcard_buffer;
    687 
    688     if (needs_upmix && upmixer)
    689         totalbuffer += upmixer->frameLatency() * obpf;
    690 
    691     if (pSoundStretch)
    692     {
    693         totalbuffer += pSoundStretch->numUnprocessedSamples() * obpf /
    694                        stretchfactor;
    695         totalbuffer += pSoundStretch->numSamples() * obpf;
    696     }
    697 
    698     if (encoder)
    699         totalbuffer += encoder->Buffered();
    700693
    701694    oldaudiotime = audiotime;
    702695
    703     audiotime = audbuf_timecode - (long long)(totalbuffer) * 100000 *
    704                                         stretchfactor / (obpf * effdsp);
     696    // timecode is the stretch adjusted version
     697    // of major post-stretched buffer contents
     698    // processing latencies are catered for in AddSamples/SetAudiotime to eliminate
     699    // race
     700    audiotime = audbuf_timecode - (( (main_buffer + soundcard_buffer) * eff_stretchfactor ) / (effdsp * obpf));
    705701
    706702    /* audiotime should never go backwards, but we might get a negative
    707703       value if GetBufferedOnSoundcard() isn't updated by the driver very
    int AudioOutputBase::GetAudiotime(void) 
    709705    if (audiotime < oldaudiotime)
    710706        audiotime = oldaudiotime;
    711707
    712     VBAUDIOTS(QString("GetAudiotime audt=%3 atc=%4 tb=%5 sb=%6 "
    713                       "sr=%7 obpf=%8 sf=%9")
     708    VBAUDIOTS(QString("GetAudiotime audt=%1 atc=%2 mb=%3 sb=%4 tb=%5 "
     709                      "sr=%6 obpf=%7 bpf=%8 sf=%9 %10 %11")
    714710              .arg(audiotime).arg(audbuf_timecode)
    715               .arg(totalbuffer).arg(soundcard_buffer)
    716               .arg(samplerate).arg(obpf).arg(stretchfactor));
     711              .arg(main_buffer)
     712              .arg(soundcard_buffer)
     713              .arg(main_buffer+soundcard_buffer)
     714              .arg(samplerate).arg(obpf).arg(bytes_per_frame).arg(stretchfactor)
     715              .arg((main_buffer + soundcard_buffer) * eff_stretchfactor)
     716              .arg(( (main_buffer + soundcard_buffer) * eff_stretchfactor ) / (effdsp * obpf))
     717              );
     718
     719    return audiotime;
     720}
     721
     722/**
     723 * Set the timecode of the top of the ringbuffer
     724 * Exclude all other processing elements as they dont vary
     725 * between AddSamples calls
     726 */
     727void AudioOutputBase::SetAudiotime(int frames, int64_t timecode)
     728{
     729    int64_t processframes_stretched = 0;
     730    int64_t processframes_unstretched = 0;
     731
     732    if (needs_upmix && upmixer)
     733        processframes_unstretched -= upmixer->frameLatency();
    717734
    718     return (int)audiotime;
     735    if (pSoundStretch)
     736    {
     737        processframes_unstretched -= pSoundStretch->numUnprocessedSamples();
     738        processframes_stretched -= pSoundStretch->numSamples();
     739    }
     740
     741    if (encoder)
     742        // the input buffered data is still in audio_bytes_per_sample format
     743        processframes_stretched -= encoder->Buffered() / output_bytes_per_frame;
     744
     745    audbuf_timecode = timecode +
     746                (((frames + processframes_unstretched) * 100000) +
     747                  (processframes_stretched * eff_stretchfactor )) / effdsp;
     748
     749    VBAUDIOTS(QString("SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
     750              .arg(audbuf_timecode)
     751              .arg(timecode)
     752              .arg(frames)
     753              .arg(processframes_unstretched)
     754              .arg(processframes_stretched));
     755#ifdef AUDIOTSTESTING
     756    GetAudiotime();
     757#endif
    719758}
    720759
    721760/**
    int AudioOutputBase::GetAudiotime(void) 
    723762 * audible and the samples most recently added to the audiobuffer, i.e. the
    724763 * time in ms representing the sum total of buffered samples
    725764 */
    726 int AudioOutputBase::GetAudioBufferedTime(void)
     765int64_t AudioOutputBase::GetAudioBufferedTime(void)
    727766{
    728767    int ret = audbuf_timecode - GetAudiotime();
    729768    // Pulse can give us values that make this -ve
    int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud) 
    869908 *
    870909 * Returns false if there's not enough space right now
    871910 */
    872 bool AudioOutputBase::AddSamples(void *buffer, int frames, long long timecode)
     911bool AudioOutputBase::AddSamples(void *buffer, int in_frames, int64_t timecode)
    873912{
    874913    int org_waud = waud,               afree = audiofree();
    875     int bpf      = bytes_per_frame,    len   = frames * source_bytes_per_frame;
     914    int frames = in_frames;
     915    int bpf      = bytes_per_frame,    len   = in_frames * source_bytes_per_frame;
    876916    int used     = kAudioRingBufferSize - afree;
    877917    bool music   = false;
     918    int bdiff;
    878919
    879920    VBAUDIOTS(QString("AddSamples frames=%1, bytes=%2, used=%3, free=%4, "
    880921                      "timecode=%5 needsupmix=%6")
    bool AudioOutputBase::AddSamples(void *buffer, int frames, long long timecode) 
    896937    if (timecode < 0)
    897938    {
    898939        // Send original samples to mythmusic visualisation
    899         timecode = (long long)(frames_buffered) * 1000 / source_samplerate;
     940        timecode = (int64_t)(frames_buffered) * 1000 / source_samplerate;
    900941        frames_buffered += frames;
    901942        dispatchVisual((uchar *)buffer, len, timecode, source_channels,
    902943                       output_settings->FormatToBits(format));
    bool AudioOutputBase::AddSamples(void *buffer, int frames, long long timecode) 
    949990                    .arg(src_strerror(error)));
    950991
    951992        buffer = src_out;
    952         frames = src_data.output_frames_gen;
     993        in_frames = frames = src_data.output_frames_gen;
    953994    }
    954995    else if (processing)
    955996        buffer = src_in;
    bool AudioOutputBase::AddSamples(void *buffer, int frames, long long timecode) 
    957998    /* we want the timecode of the last sample added but we are given the
    958999       timecode of the first - add the time in ms that the frames added
    9591000       represent */
    960     audbuf_timecode = timecode + ((long long)(frames) * 100000 / effdsp);
     1001    //audbuf_timecode = timecode + ((int64_t)((frames) * 100000) / effdsp);
    9611002
    9621003    // Copy samples into audiobuffer, with upmix if necessary
    9631004    if ((len = CopyWithUpmix((char *)buffer, frames, org_waud)) <= 0)
    964         return true;
     1005    {
     1006        //return true;
     1007        goto done;
     1008    }
    9651009
    9661010    frames = len / bpf;
    9671011
    968     int bdiff = kAudioRingBufferSize - waud;
     1012    bdiff = kAudioRingBufferSize - waud;
    9691013
    9701014    if (pSoundStretch)
    9711015    {
    bool AudioOutputBase::AddSamples(void *buffer, int frames, long long timecode) 
    10431087
    10441088    waud = org_waud;
    10451089
     1090done:
     1091    SetAudiotime(in_frames, timecode);
     1092
    10461093    return true;
    10471094}
    10481095
    void AudioOutputBase::OutputAudioLoop(void) 
    10901137    uchar *fragment_buf = new uchar[fragment_size + 16];
    10911138    uchar *fragment     = (uchar *)AOALIGN(fragment_buf[0]);
    10921139
     1140    // to reduce startup latency, write silence in 8ms chunks
     1141    int zero_fragment_size = (int)(0.008*samplerate/channels);
     1142    zero_fragment_size *= bytes_per_frame;   // make sure its a multiple of bytes_per_frame
     1143    if (zero_fragment_size > fragment_size)
     1144        zero_fragment_size = fragment_size;
     1145
    10931146    bzero(zeros, fragment_size);
    10941147
    10951148    while (!killaudio)
    void AudioOutputBase::OutputAudioLoop(void) 
    11381191            continue;
    11391192        }
    11401193
     1194#ifdef AUDIOTSTESTING
     1195        VBAUDIOTS("WriteAudio Start");
     1196#endif
    11411197        Status();
    11421198
    1143         if (GetAudioData(fragment, fragment_size, true))
    1144             WriteAudio(fragment, fragment_size);
     1199        // delay setting raud until after phys buffer is filled
     1200        // so GetAudiotime will be accurate without locking
     1201        reset_active.TestAndDeref();
     1202        int next_raud = raud;
     1203        if (GetAudioData(fragment, fragment_size, true, &next_raud))
     1204        {
     1205            if (!reset_active.TestAndDeref())
     1206            {
     1207                WriteAudio(fragment, fragment_size);
     1208                if (!reset_active.TestAndDeref())
     1209                    raud = next_raud;
     1210            }
     1211        }
     1212#ifdef AUDIOTSTESTING
     1213        GetAudiotime();
     1214        VBAUDIOTS("WriteAudio Done");
     1215#endif
     1216
    11451217    }
    11461218
    11471219    delete[] zeros;
    void AudioOutputBase::OutputAudioLoop(void) 
    11581230 * nothing. Otherwise, we'll copy less than 'size' bytes if that's all that's
    11591231 * available. Returns the number of bytes copied.
    11601232 */
    1161 int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer)
     1233int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer, int *local_raud)
    11621234{
    11631235
     1236#define LRPOS audiobuffer + *local_raud
    11641237    // re-check audioready() in case things changed.
    11651238    // for example, ClearAfterSeek() might have run
    11661239    int avail_size   = audioready();
    11671240    int frag_size    = size;
    11681241    int written_size = size;
    11691242
     1243    if (local_raud == NULL)
     1244        local_raud = &raud;
     1245
    11701246    if (!full_buffer && (size > avail_size))
    11711247    {
    11721248        // when full_buffer is false, return any available data
    int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer) 
    11921268    {
    11931269        if (fromFloats)
    11941270            off = AudioOutputUtil::fromFloat(output_format, buffer,
    1195                                              RPOS, bdiff);
     1271                                             LRPOS, bdiff);
    11961272        else
    11971273        {
    1198             memcpy(buffer, RPOS, bdiff);
     1274            memcpy(buffer, LRPOS, bdiff);
    11991275            off = bdiff;
    12001276        }
    12011277
    12021278        frag_size -= bdiff;
    1203         raud = 0;
     1279        *local_raud = 0;
    12041280    }
    12051281    if (frag_size > 0)
    12061282    {
    12071283        if (fromFloats)
    12081284            AudioOutputUtil::fromFloat(output_format, buffer + off,
    1209                                        RPOS, frag_size);
     1285                                       LRPOS, frag_size);
    12101286        else
    1211             memcpy(buffer + off, RPOS, frag_size);
     1287            memcpy(buffer + off, LRPOS, frag_size);
    12121288    }
    12131289
    1214     raud += frag_size;
     1290    *local_raud += frag_size;
    12151291
    12161292    // Mute individual channels through mono->stereo duplication
    12171293    MuteState mute_state = GetMuteState();
  • mythtv/libs/libmyth/audiooutputbase.h

    diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
    index 51e9be6..84e709d 100644
    a b class FreeSurround; 
    3232class AudioOutputDigitalEncoder;
    3333struct AVCodecContext;
    3434
     35class AsyncLooseLock
     36{
     37public:
     38    AsyncLooseLock() { head = tail = 0; }
     39    void Clear() { head = tail = 0; }
     40    void Ref() { head++; }
     41    bool TestAndDeref() { bool r; if ((r=(head != tail))) tail++; return r; }
     42private:
     43    int head;
     44    int tail;
     45};
     46
    3547class AudioOutputBase : public AudioOutput, public QThread
    3648{
    3749 public:
    class AudioOutputBase : public AudioOutput, public QThread 
    5769    int GetSWVolume(void);
    5870
    5971    // timecode is in milliseconds.
    60     virtual bool AddSamples(void *buffer, int frames, long long timecode);
     72    virtual bool AddSamples(void *buffer, int frames, int64_t timecode);
    6173
    62     virtual void SetTimecode(long long timecode);
     74    virtual void SetTimecode(int64_t timecode);
    6375    virtual bool IsPaused(void) const { return actually_paused; }
    6476    virtual void Pause(bool paused);
    6577    void PauseUntilBuffered(void);
    class AudioOutputBase : public AudioOutput, public QThread 
    6779    // Wait for all data to finish playing
    6880    virtual void Drain(void);
    6981
    70     virtual int GetAudiotime(void);
    71     virtual int GetAudioBufferedTime(void);
     82    virtual int64_t GetAudiotime(void);
     83    virtual int64_t GetAudioBufferedTime(void);
    7284
    7385    // Send output events showing current progress
    7486    virtual void Status(void);
    class AudioOutputBase : public AudioOutput, public QThread 
    8395
    8496    static const uint kAudioSRCInputSize  = 16384<<1;
    8597    static const uint kAudioSRCOutputSize = 16384<<3;
    86     /// Audio Buffer Size -- should be divisible by 12,10,8,6,4,2..
    87     static const uint kAudioRingBufferSize   = 1536000;
     98    /// Audio Buffer Size -- should be divisible by 32,24,16,12,10,8,6,4,2..
     99    static const uint kAudioRingBufferSize   = 3072000;
    88100
    89101 protected:
    90102    // You need to implement the following functions
    class AudioOutputBase : public AudioOutput, public QThread 
    102114    virtual bool StartOutputThread(void);
    103115    virtual void StopOutputThread(void);
    104116
    105     int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer);
     117    int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer, int *local_raud = NULL);
    106118
    107119    void OutputAudioLoop(void);
    108120
    class AudioOutputBase : public AudioOutput, public QThread 
    138150    bool passthru, enc, reenc;
    139151
    140152    float stretchfactor;
     153    int  eff_stretchfactor;     // scaled to 100000 as effdsp is
    141154    AudioOutputSource source;
    142155
    143156    bool killaudio;
    class AudioOutputBase : public AudioOutput, public QThread 
    153166
    154167 private:
    155168    int CopyWithUpmix(char *buffer, int frames, int &org_waud);
     169    void SetAudiotime(int frames, int64_t timecode);
    156170    AudioOutputSettings *output_settings;
    157171    bool need_resampler;
    158172    SRC_STATE *src_ctx;
    class AudioOutputBase : public AudioOutput, public QThread 
    173187
    174188    bool processing;
    175189
    176     long long frames_buffered;
     190    int64_t frames_buffered;
    177191
    178192    bool audio_thread_exists;
    179193
    class AudioOutputBase : public AudioOutput, public QThread 
    186200    QMutex avsync_lock;
    187201
    188202    // timecode of audio leaving the soundcard (same units as timecodes)
    189     long long audiotime;
     203    int64_t audiotime;
    190204
    191205    /* Audio circular buffer */
    192206    int raud, waud;     /* read and write positions */
    193207    // timecode of audio most recently placed into buffer
    194     long long audbuf_timecode;
     208    int64_t audbuf_timecode;
     209    AsyncLooseLock reset_active;
    195210
    196211    QMutex killAudioLock;
    197212
  • mythtv/libs/libmythfreesurround/freesurround.cpp

    diff --git a/mythtv/libs/libmythfreesurround/freesurround.cpp b/mythtv/libs/libmythfreesurround/freesurround.cpp
    index 5e8b1f5..aef65a3 100644
    a b Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
    2929using namespace std;
    3030
    3131#include "compat.h"
     32#include "mythverbose.h"
    3233#include "freesurround.h"
    3334#include "el_processor.h"
    3435
    3536#include <QString>
    3637#include <QDateTime>
    3738
    38 #if 0
    39 #define VERBOSE(args...) \
    40     do { \
    41         QDateTime dtmp = QDateTime::currentDateTime(); \
    42         QString dtime = dtmp.toString("yyyy-MM-dd hh:mm:ss.zzz"); \
    43         std::cout << dtime.toLocal8Bit().constData() << " " \
    44             << QString(args).toLocal8Bit().constData() << std::endl; \
    45     } while (0)
    46 #else
    47 #define VERBOSE(args...)
    48 #endif
    49 #if 0
    50 #define VERBOSE1(args...) \
    51     do { \
    52         QDateTime dtmp = QDateTime::currentDateTime(); \
    53         QString dtime = dtmp.toString("yyyy-MM-dd hh:mm:ss.zzz"); \
    54         std::cout << dtime.toLocal8Bit().constData() << " " \
    55             << QString(args).toLocal8Bit().constData() << std::endl; \
    56     } while (0)
    57 #else
    58 #define VERBOSE1(args...)
    59 #endif
    60 
    6139// our default internal block size, in floats
    6240static const unsigned default_block_size = 8192;
    6341// Gain of center and lfe channels in passive mode (sqrt 0.5)
    FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) : 
    161139    processed_size(0),
    162140    surround_mode(smode)
    163141{
    164     VERBOSE(QString("FreeSurround::FreeSurround rate %1 moviemode %2")
     142    VERBOSE(VB_AUDIO+VB_EXTRA, QString("FreeSurround::FreeSurround rate %1 moviemode %2")
    165143            .arg(srate).arg(moviemode));
    166144
    167145    if (moviemode)
    FreeSurround::FreeSurround(uint srate, bool moviemode, SurroundMode smode) : 
    193171    channel_select++;
    194172    if (channel_select>=6)
    195173        channel_select = 0;
    196     VERBOSE(QString("FreeSurround::FreeSurround channel_select %1")
     174    VERBOSE(VB_AUDIO+VB_EXTRA, QString("FreeSurround::FreeSurround channel_select %1")
    197175            .arg(channel_select));
    198176#endif
    199     VERBOSE(QString("FreeSurround::FreeSurround done"));
     177    VERBOSE(VB_AUDIO+VB_EXTRA, QString("FreeSurround::FreeSurround done"));
    200178}
    201179
    202180void FreeSurround::SetParams()
    FreeSurround::fsurround_params::fsurround_params(int32_t center_width, 
    224202
    225203FreeSurround::~FreeSurround()
    226204{
    227     VERBOSE(QString("FreeSurround::~FreeSurround"));
     205    VERBOSE(VB_AUDIO+VB_EXTRA, QString("FreeSurround::~FreeSurround"));
    228206    close();
    229207    if (bufs)
    230208    {
    231209        bp.release((void*)1);
    232210        bufs = NULL;
    233211    }
    234     VERBOSE(QString("FreeSurround::~FreeSurround done"));
     212    VERBOSE(VB_AUDIO+VB_EXTRA, QString("FreeSurround::~FreeSurround done"));
    235213}
    236214
    237215uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels)
    uint FreeSurround::putFrames(void* buffer, uint numFrames, uint numChannels) 
    289267                    break;
    290268            }
    291269            ic += numFrames;
    292             in_count = ic;
    293270            processed = process;
    294271            if (ic != bs)
     272            {
     273                // dont modify unless no processing is to be done
     274                // for audiotime consistency
     275                in_count = ic;
    295276                break;
    296             in_count = 0;
     277            }
     278            // process_block takes some time so dont update in and out count
     279            // before its finished so that Audiotime is correctly calculated
    297280            if (process)
    298281                process_block();
     282            in_count = 0;
    299283            out_count = bs;
    300284            processed_size = bs;
    301285            break;
    302286    }
    303287
    304     VERBOSE1(QString("FreeSurround::putFrames %1 %2 used %4 generated %5")
     288    VERBOSE(VB_AUDIO+VB_TIMESTAMP+VB_EXTRA, QString("FreeSurround::putFrames %1 #ch %2 used %4 generated %5")
    305289            .arg(numFrames).arg(numChannels).arg(i).arg(out_count));
    306290
    307291    return i;
    uint FreeSurround::receiveFrames(void *buffer, uint maxFrames) 
    318302    switch (surround_mode)
    319303    {
    320304        case SurroundModePassive:
    321             for (uint i = 0; i < maxFrames; i++)
     305            for (i = 0; i < maxFrames; i++)
    322306            {
    323307                *output++ = bufs->l[outindex];
    324308                *output++ = bufs->r[outindex];
    uint FreeSurround::receiveFrames(void *buffer, uint maxFrames) 
    341325                float *ls  = &outputs[3][outindex];
    342326                float *rs  = &outputs[4][outindex];
    343327                float *lfe = &outputs[5][outindex];
    344                 for (uint i = 0; i < maxFrames; i++)
     328                for (i = 0; i < maxFrames; i++)
    345329                {
    346330                    *output++ = *l++;
    347331                    *output++ = *r++;
    uint FreeSurround::receiveFrames(void *buffer, uint maxFrames) 
    361345                float *ls  = &bufs->ls[outindex];
    362346                float *rs  = &bufs->rs[outindex];
    363347                float *lfe = &bufs->lfe[outindex];
    364                 for (uint i = 0; i < maxFrames; i++)
     348                for (i = 0; i < maxFrames; i++)
    365349                {
    366350                    *output++ = *l++;
    367351                    *output++ = *r++;
    uint FreeSurround::receiveFrames(void *buffer, uint maxFrames) 
    376360            break;
    377361    }
    378362    out_count = oc;
    379     VERBOSE1(QString("FreeSurround::receiveFrames %1").arg(maxFrames));
     363    VERBOSE(VB_AUDIO+VB_TIMESTAMP+VB_EXTRA, QString("FreeSurround::receiveFrames %1").arg(maxFrames));
    380364    return maxFrames;
    381365}
    382366
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
    index 78b048e..b8ff202 100644
    a b NuppelVideoPlayer::NuppelVideoPlayer(bool muted) 
    208208      videosync(NULL),              delay(0),
    209209      vsynctol(30/4),               avsync_delay(0),
    210210      avsync_adjustment(0),         avsync_avg(0),
    211       avsync_oldavg(0),             refreshrate(0),
     211      avsync_oldavg(0),             
     212      avsync_predictor(0),          avsync_predictor_enabled(false),
     213      refreshrate(0),
    212214      lastsync(false),              m_playing_slower(false),
    213215      m_stored_audio_stretchfactor(1.0),
    214216      audio_paused(false),
    void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps, 
    11411143        video_frame_rate = fps;
    11421144        float temp_speed = (play_speed == 0.0f) ?
    11431145            audio_stretchfactor : play_speed;
    1144         frame_interval = (int)(1000000.0f / video_frame_rate / temp_speed);
     1146        SetFrameInterval(kScan_Progressive, 1.0 / (video_frame_rate * temp_speed));
    11451147    }
    11461148
    11471149    if (videoOutput)
    float NuppelVideoPlayer::WarpFactor(void) 
    23582360    return divergence;
    23592361}
    23602362
     2363void NuppelVideoPlayer::SetFrameInterval(FrameScanType scan, double frame_period)
     2364{
     2365    frame_interval = (int)(1000000.0f * frame_period + 0.5f);
     2366    if (!avsync_predictor_enabled)
     2367        avsync_predictor = 0;
     2368    avsync_predictor_enabled = false;
     2369
     2370    VERBOSE(VB_PLAYBACK, LOC + QString("SetFrameInterval ps:%1 scan:%2")
     2371            .arg(play_speed).arg(scan)
     2372           );
     2373    if (play_speed < 1 || play_speed > 2 || refreshrate <= 0)
     2374        return;
     2375
     2376    avsync_predictor_enabled = ((frame_interval-(frame_interval/200)) < refreshrate);
     2377}
     2378
     2379void NuppelVideoPlayer::ResetAVSync(void)
     2380{
     2381    avsync_avg = 0;
     2382    avsync_oldavg = 0;
     2383    if (!avsync_predictor_enabled || avsync_predictor >= refreshrate)
     2384        avsync_predictor = 0;
     2385    prevtc = 0;
     2386    warpfactor = 1.0f;
     2387    warpfactor_avg = 1.0f;
     2388    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V sync reset");
     2389}
     2390
    23612391void NuppelVideoPlayer::InitAVSync(void)
    23622392{
    23632393    videosync->Start();
    void NuppelVideoPlayer::InitAVSync(void) 
    23792409        VERBOSE(VB_GENERAL, msg);
    23802410        msg = QString("Refresh rate: %1, frame interval: %2")
    23812411                       .arg(refreshrate).arg(frame_interval);
    2382         VERBOSE(VB_PLAYBACK, msg);
     2412        VERBOSE(VB_PLAYBACK, LOC + msg);
     2413
     2414        SetFrameInterval(m_scan, 1.0 / (video_frame_rate * play_speed));
    23832415
    23842416        // try to get preferential scheduling, but ignore if we fail to.
    23852417        myth_nice(-19);
    23862418    }
    23872419}
    23882420
     2421int64_t NuppelVideoPlayer::AVSyncGetAudiotime(void)
     2422{
     2423    int64_t currentaudiotime = 0;
     2424    audio_lock.lock();
     2425    if (audioOutput && normal_speed)
     2426    {
     2427        currentaudiotime = audioOutput->GetAudiotime();
     2428    }
     2429    audio_lock.unlock();
     2430    return currentaudiotime;
     2431}
     2432
    23892433void NuppelVideoPlayer::AVSync(void)
    23902434{
    23912435    float diverge = 0.0f;
     2436    int vsync_delay_clock = 0;
     2437    int64_t currentaudiotime = 0;
     2438
    23922439    // attempt to reduce fps for standalone PIP
    23932440    if (player_ctx->IsPIP() && framesPlayed % 2)
    23942441    {
    void NuppelVideoPlayer::AVSync(void) 
    24282475        ps = kScan_Progressive;
    24292476
    24302477    bool dropframe = false;
     2478    QString dbg;
     2479
     2480    if (avsync_predictor_enabled && !prebuffering)
     2481    {
     2482        avsync_predictor += frame_interval;
     2483        if (avsync_predictor >= refreshrate)
     2484        {
     2485            int refreshperiodsinframe = avsync_predictor/refreshrate;
     2486            avsync_predictor -= refreshrate * refreshperiodsinframe;
     2487        }
     2488        else
     2489        {
     2490            dropframe = true;
     2491            dbg = "A/V predict drop frame, ";
     2492        }
     2493    }
     2494
    24312495    if (diverge < -MAXDIVERGE)
    24322496    {
    24332497        dropframe = true;
    24342498        // If video is way behind of audio, adjust for it...
    2435         QString dbg = QString("Video is %1 frames behind audio (too slow), ")
     2499        dbg = QString("Video is %1 frames behind audio (too slow), ")
    24362500            .arg(-diverge);
     2501    }
    24372502
     2503    if (dropframe)
     2504    {
    24382505        // Reset A/V Sync
    24392506        lastsync = true;
    24402507
     2508        currentaudiotime = AVSyncGetAudiotime();
     2509
    24412510        if (buffer && !using_null_videoout &&
    24422511            videoOutput->hasHWAcceleration() &&
    24432512           !videoOutput->IsSyncLocked())
    void NuppelVideoPlayer::AVSync(void) 
    24622531        if (buffer)
    24632532            videoOutput->PrepareFrame(buffer, ps);
    24642533
    2465         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
     2534        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("AVSync waitforframe %1 %2")
    24662535                .arg(avsync_adjustment).arg(m_double_framerate));
    2467         videosync->WaitForFrame(avsync_adjustment + repeat_delay);
    2468         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
     2536        vsync_delay_clock = videosync->WaitForFrame(avsync_adjustment + repeat_delay);
     2537        currentaudiotime = AVSyncGetAudiotime();
     2538        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + "AVSync show");
    24692539        if (!resetvideo)
    24702540            videoOutput->Show(ps);
    24712541
    24722542        if (videoOutput->IsErrored())
    24732543        {
    2474             VERBOSE(VB_IMPORTANT, "NVP: Error condition detected "
     2544            VERBOSE(VB_IMPORTANT, LOC + "Error condition detected "
    24752545                    "in videoOutput after Show(), aborting playback.");
    24762546            SetErrored(QObject::tr("Serious error detected in Video Output"));
    24772547            return;
    void NuppelVideoPlayer::AVSync(void) 
    25072577            // Display the second field
    25082578            videosync->AdvanceTrigger();
    25092579#ifdef NEW_AVSYNC
    2510             videosync->WaitForFrame(avsync_adjustment);
     2580            vsync_delay_clock = videosync->WaitForFrame(avsync_adjustment);
    25112581#else
    2512             videosync->WaitForFrame(0);
     2582            vsync_delay_clock = videosync->WaitForFrame(0);
    25132583#endif
    25142584            if (!resetvideo)
    25152585            {
    void NuppelVideoPlayer::AVSync(void) 
    25202590        repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
    25212591
    25222592        if (repeat_delay)
    2523             VERBOSE(VB_TIMESTAMP, QString("A/V repeat_pict, adding %1 repeat "
     2593            VERBOSE(VB_TIMESTAMP, LOC + QString("A/V repeat_pict, adding %1 repeat "
    25242594                    "delay").arg(repeat_delay));
    25252595    }
    25262596    else
    25272597    {
    2528         videosync->WaitForFrame(0);
     2598        vsync_delay_clock = videosync->WaitForFrame(0);
     2599        currentaudiotime = AVSyncGetAudiotime();
    25292600    }
    25302601
    25312602    if (output_jmeter && output_jmeter->RecordCycleTime())
    25322603    {
    2533         VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("A/V avsync_delay: %1, "
     2604        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V avsync_delay: %1, "
    25342605                "avsync_avg: %2, warpfactor: %3, warpfactor_avg: %4")
    25352606                .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
    25362607                .arg(warpfactor).arg(warpfactor_avg));
    void NuppelVideoPlayer::AVSync(void) 
    25462617        // by cutting the frame rate in half for the length of this frame
    25472618
    25482619#ifdef NEW_AVSYNC
    2549         avsync_adjustment = refreshrate;
     2620        //avsync_adjustment = refreshrate;
     2621        avsync_adjustment = frame_interval;
     2622        //avsync_adjustment = frame_interval*(((int)MAXDIVERGE)-1);
    25502623#else
    25512624        avsync_adjustment = frame_interval;
    25522625#endif
    void NuppelVideoPlayer::AVSync(void) 
    25562629                        "\t\t\tdoubling video frame interval to slow down.").arg(diverge));
    25572630    }
    25582631
    2559     audio_lock.lock();
    25602632    if (audioOutput && normal_speed)
    25612633    {
    2562         long long currentaudiotime = audioOutput->GetAudiotime();
    2563         audio_lock.unlock();
    25642634#if 0
    2565         VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString(
     2635        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString(
    25662636                    "A/V timecodes audio %1 video %2 frameinterval %3 "
    2567                     "avdel %4 avg %5 tcoffset %6")
     2637                    "avdel %4 avg %5 tcoffset %6"
     2638                    " avp %7 avpen %8"
     2639                    " avdc %9"
     2640                    )
    25682641                .arg(currentaudiotime)
    25692642                .arg(buffer->timecode)
    25702643                .arg(frame_interval)
    2571                 .arg(buffer->timecode - currentaudiotime)
     2644                .arg(buffer->timecode - currentaudiotime - (int)(vsync_delay_clock*audio_stretchfactor+500)/1000)
    25722645                .arg(avsync_avg)
    25732646                .arg(tc_wrap[TC_AUDIO])
     2647                .arg(avsync_predictor)
     2648                .arg(avsync_predictor_enabled)
     2649                .arg(vsync_delay_clock)
    25742650                 );
    25752651#endif
    25762652        if (currentaudiotime != 0 && buffer->timecode != 0)
    25772653        { // currentaudiotime == 0 after a seek
    25782654            // The time at the start of this frame (ie, now) is given by
    25792655            // last->timecode
    2580             int delta = (int)((buffer->timecode - prevtc)/play_speed) - (frame_interval / 1000);
    2581             prevtc = buffer->timecode;
    2582             //cerr << delta << " ";
    2583 
    2584             // If the timecode is off by a frame (dropped frame) wait to sync
    2585             if (delta > (int) frame_interval / 1200 &&
    2586                 delta < (int) frame_interval / 1000 * 3 &&
    2587                 prevrp == 0)
     2656            if (prevtc != 0)
    25882657            {
    2589                 //cerr << "+ ";
    2590                 videosync->AdvanceTrigger();
    2591                 if (m_double_framerate)
     2658                int delta = (int)((buffer->timecode - prevtc)/play_speed) - (frame_interval / 1000);
     2659                // If the timecode is off by a frame (dropped frame) wait to sync
     2660                if (delta > (int) frame_interval / 1200 &&
     2661                    delta < (int) frame_interval / 1000 * 3 &&
     2662                    prevrp == 0)
     2663                {
     2664                    //cerr << "+ ";
     2665                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V delay %1").arg(delta));
    25922666                    videosync->AdvanceTrigger();
     2667                    if (m_double_framerate)
     2668                        videosync->AdvanceTrigger();
     2669                }
    25932670            }
     2671            prevtc = buffer->timecode;
    25942672            prevrp = buffer->repeat_pict;
    25952673
    2596             avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
     2674            avsync_delay = (buffer->timecode - currentaudiotime) * 1000 - (int)(vsync_delay_clock*audio_stretchfactor);  //usec
    25972675            // prevents major jitter when pts resets during dvd title
    25982676            if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())
    25992677                avsync_delay = 90000;
    26002678            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    26012679
     2680            int avsync_used = avsync_avg;
     2681            if (labs(avsync_used) > labs(avsync_delay))
     2682                avsync_used = avsync_delay;
     2683
    26022684            /* If the audio time codes and video diverge, shift
    26032685               the video by one interlaced field (1/2 frame) */
    26042686            if (!lastsync)
    26052687            {
    2606                 if (avsync_avg > frame_interval * 3 / 2)
     2688                if (avsync_used > refreshrate)
    26072689                {
    2608                     avsync_adjustment = refreshrate;
    2609                     lastsync = true;
     2690                    avsync_adjustment += refreshrate;
     2691                    //lastsync = true;
     2692                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high extend");
    26102693                }
    2611                 else if (avsync_avg < 0 - frame_interval * 3 / 2)
     2694                else if (avsync_used < 0 - refreshrate)
    26122695                {
    2613                     avsync_adjustment = -refreshrate;
    2614                     lastsync = true;
     2696                    avsync_adjustment -= refreshrate;
     2697                    //lastsync = true;
     2698                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high skip");
    26152699                }
    26162700            }
    26172701            else
    void NuppelVideoPlayer::AVSync(void) 
    26192703        }
    26202704        else
    26212705        {
    2622             avsync_avg = 0;
    2623             avsync_oldavg = 0;
     2706            ResetAVSync();
    26242707        }
    26252708    }
    26262709    else
    2627         audio_lock.unlock();
     2710    {
     2711        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V no sync proc ns:%1 ao:%2").arg(normal_speed).arg(audioOutput != NULL));
     2712    }
    26282713}
    26292714
    26302715void NuppelVideoPlayer::DisplayPauseFrame(void)
    void NuppelVideoPlayer::DoPause(void) 
    42374322    }
    42384323
    42394324    float temp_speed = audio_stretchfactor;
    4240     frame_interval = (int)(1000000.0 * ffrew_skip / video_frame_rate / temp_speed);
     4325    SetFrameInterval(m_scan, ffrew_skip / (video_frame_rate * temp_speed));
    42414326    VERBOSE(VB_PLAYBACK, QString("rate: %1 speed: %2 skip: %3 = interval %4")
    42424327                                 .arg(video_frame_rate).arg(temp_speed)
    42434328                                 .arg(ffrew_skip).arg(frame_interval));
    void NuppelVideoPlayer::DoPlay(void) 
    42994384        ClearAfterSeek();
    43004385    }
    43014386
    4302     frame_interval = (int) (1000000.0f * ffrew_skip / video_frame_rate /
    4303                             play_speed);
     4387    SetFrameInterval(m_scan, ffrew_skip / (video_frame_rate * play_speed));
    43044388
    43054389    VERBOSE(VB_PLAYBACK, LOC + "DoPlay: " +
    43064390            QString("rate: %1 speed: %2 skip: %3 => new interval %4")
    void NuppelVideoPlayer::ClearAfterSeek(bool clearvideobuffers) 
    46984782        savedAudioTimecodeOffset = 0;
    46994783    }
    47004784
     4785    ResetAVSync();
    47014786    SetPrebuffering(true);
    47024787    ResetAudio();
    47034788
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.h b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
    index af02d21..8d4017c 100644
    a b class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    514514    float WarpFactor(void);
    515515    void  WrapTimecode(long long &timecode, TCTypes tc_type);
    516516    void  InitAVSync(void);
     517    void  ResetAVSync(void);
     518    int64_t AVSyncGetAudiotime(void);
     519    void  SetFrameInterval(FrameScanType scan, double speed);
    517520    void  AVSync(void);
    518521    void  FallbackDeint(void);
    519522    void  CheckExtraAudioDecode(void);
    class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    800803    int        avsync_adjustment;
    801804    int        avsync_avg;
    802805    int        avsync_oldavg;
     806    int        avsync_predictor;
     807    bool       avsync_predictor_enabled;
    803808    int        refreshrate;
    804809    bool       lastsync;
    805810    bool       m_playing_slower;
  • mythtv/libs/libmythtv/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index d6547c4..a5a1899 100644
    a b AvFormatDecoder::AvFormatDecoder(NuppelVideoPlayer *parent, 
    482482      start_code_state(0xffffffff),
    483483      lastvpts(0),                  lastapts(0),
    484484      lastccptsu(0),
     485      firstvpts(0),                 firstvptsinuse(false),
    485486      using_null_videoout(use_null_videoout),
    486487      video_codec_id(kCodec_NONE),
    487488      no_hardware_decoders(no_hardware_decode),
    void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 
    933934        if (decoded_video_frame)
    934935            GetNVP()->DiscardVideoFrame(decoded_video_frame);
    935936    }
     937
     938    if (doflush)
     939    {
     940        firstvpts = 0;
     941        firstvptsinuse = true;
     942    }
    936943}
    937944
    938945void AvFormatDecoder::Reset(bool reset_video_data, bool seek_reset)
    void AvFormatDecoder::MpegPreProcessPkt(AVStream *stream, AVPacket *pkt) 
    29312938
    29322939                gopset = false;
    29332940                prevgoppos = 0;
     2941                firstvpts =
    29342942                lastapts = lastvpts = lastccptsu = 0;
     2943                firstvptsinuse = true;
    29352944
    29362945                // fps debugging info
    29372946                float avFPS = normalized_fps(stream, context);
    bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt) 
    30413050
    30423051            gopset = false;
    30433052            prevgoppos = 0;
     3053            firstvpts =
    30443054            lastapts = lastvpts = lastccptsu = 0;
     3055            firstvptsinuse = true;
    30453056
    30463057            // fps debugging info
    30473058            float avFPS = normalized_fps(stream, context);
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    32703281    framesPlayed++;
    32713282
    32723283    lastvpts = temppts;
     3284    if (!firstvpts && firstvptsinuse)
     3285        firstvpts = temppts;
    32733286
    32743287    return true;
    32753288}
    bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt, 
    40444057                skipaudio = false;
    40454058        }
    40464059
     4060        // skip any audio frames preceding first video frame
     4061        if (firstvptsinuse && firstvpts && (lastapts < firstvpts))
     4062        {
     4063            VERBOSE(VB_PLAYBACK+VB_TIMESTAMP,
     4064                LOC + QString("discarding early audio timecode %1 %2 %3")
     4065                .arg(pkt->pts).arg(pkt->dts).arg(lastapts));
     4066            break;
     4067        }
     4068        firstvptsinuse = false;
     4069
    40474070        avcodeclock->lock();
    40484071        data_size = 0;
    40494072
  • mythtv/libs/libmythtv/avformatdecoder.h

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
    index 3ad2c70..1192546 100644
    a b class AvFormatDecoder : public DecoderBase 
    261261    long long lastvpts;
    262262    long long lastapts;
    263263    long long lastccptsu;
     264    long long firstvpts;
     265    bool      firstvptsinuse;
    264266
    265267    bool using_null_videoout;
    266268    MythCodecID video_codec_id;
  • mythtv/libs/libmythtv/vsync.cpp

    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index 59b5db7..728a759 100644
    a b VideoSync::VideoSync(VideoOutput *video_output, 
    123123                     bool halve_frame_interval) :
    124124    m_video_output(video_output),   m_frame_interval(frameint),
    125125    m_refresh_interval(refreshint), m_interlaced(halve_frame_interval),
    126     m_delay(-1)
     126    m_nexttrigger(0),
     127    m_delay(-1),
     128    m_synchronous(false)
    127129{
    128     bzero(&m_nexttrigger, sizeof(m_nexttrigger));
    129130
    130131    int tolerance = m_refresh_interval / 200;
    131132    if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))
    VideoSync::VideoSync(VideoOutput *video_output, 
    136137
    137138void VideoSync::Start(void)
    138139{
    139     gettimeofday(&m_nexttrigger, NULL); // now
     140    struct timeval now_tv;
     141    gettimeofday(&now_tv, NULL); // now
     142    m_nexttrigger = now_tv.tv_sec * 1000000LL + now_tv.tv_usec;
    140143}
    141144
    142145/** \fn VideoSync::SetFrameInterval(int fr, bool intr)
    void VideoSync::SetFrameInterval(int fr, bool intr) 
    147150    m_frame_interval = fr;
    148151    m_interlaced = intr;
    149152    int tolerance = m_refresh_interval / 200;
     153    double sync_factor = fr * 2.0f / intr;
     154    sync_factor = sync_factor - round(sync_factor);
     155    m_synchronous = (sync_factor >= -0.005) && (sync_factor <= 0.005);
    150156    if (m_interlaced && m_refresh_interval > ((m_frame_interval/2) + tolerance))
    151157        m_interlaced = false; // can't display both fields at 2x rate
    152158
    153     VERBOSE(VB_PLAYBACK, QString("Set video sync frame interval to %1")
    154                                  .arg(m_frame_interval));
    155 }
    156 
    157 void VideoSync::OffsetTimeval(struct timeval& tv, int offset)
    158 {
    159     tv.tv_usec += offset;
    160     while (tv.tv_usec > 999999)
    161     {
    162         tv.tv_sec++;
    163         tv.tv_usec -= 1000000;
    164     }
    165     while (tv.tv_usec < 0)
    166     {
    167         tv.tv_sec--;
    168         tv.tv_usec += 1000000;
    169     }
     159    VERBOSE(VB_PLAYBACK, QString("Set video sync frame interval to %1 (synced:%2)")
     160                                 .arg(m_frame_interval).arg(m_synchronous));
    170161}
    171162
    172163/** \fn VideoSync::UpdateNexttrigger()
    void VideoSync::UpdateNexttrigger() 
    179170    // Offset by frame interval -- if interlaced, only delay by half
    180171    // frame interval
    181172    if (m_interlaced)
    182         OffsetTimeval(m_nexttrigger, m_frame_interval/2);
     173        m_nexttrigger += m_frame_interval/2;
    183174    else
    184         OffsetTimeval(m_nexttrigger, m_frame_interval);
     175        m_nexttrigger += m_frame_interval;
    185176}
    186177
    187178/** \fn VideoSync::CalcDelay()
    void VideoSync::UpdateNexttrigger() 
    197188 */
    198189int VideoSync::CalcDelay()
    199190{
    200     struct timeval now;
    201     gettimeofday(&now, NULL);
     191    struct timeval now_tv;
     192    gettimeofday(&now_tv, NULL);
    202193    //cout << "CalcDelay: next: " << timeval_str(m_nexttrigger) << " now "
    203194    // << timeval_str(now) << endl;
     195    int64_t now = now_tv.tv_sec * 1000000LL + now_tv.tv_usec;
    204196
    205     int ret_val = (m_nexttrigger.tv_sec - now.tv_sec) * 1000000 +
    206                   (m_nexttrigger.tv_usec - now.tv_usec);
     197    int ret_val = m_nexttrigger - now;
    207198
    208199    //cout << "delay " << ret_val << endl;
    209200
    int VideoSync::CalcDelay() 
    215206            ret_val = m_frame_interval * 4;
    216207
    217208        // set nexttrigger to our new target time
    218         m_nexttrigger.tv_sec = now.tv_sec;
    219         m_nexttrigger.tv_usec = now.tv_usec;
    220         OffsetTimeval(m_nexttrigger, ret_val);
     209        m_nexttrigger = now;
     210        m_nexttrigger += ret_val;
    221211    }
    222212
    223     if (ret_val < -m_frame_interval)
     213    if ((ret_val < -m_frame_interval) && (m_frame_interval >= m_refresh_interval))
    224214    {
    225215        ret_val = -m_frame_interval;
    226216
    227217        // set nexttrigger to our new target time
    228         m_nexttrigger.tv_sec = now.tv_sec;
    229         m_nexttrigger.tv_usec = now.tv_usec;
    230         OffsetTimeval(m_nexttrigger, ret_val);
     218        m_nexttrigger = now;
     219        m_nexttrigger += ret_val;
    231220    }
    232221
    233222    return ret_val;
    int VideoSync::CalcDelay() 
    244233void VideoSync::KeepPhase()
    245234{
    246235    // cerr << m_delay << endl;
    247     if (m_delay < -(m_refresh_interval/2))
    248         OffsetTimeval(m_nexttrigger, 200);
    249     else if (m_delay > -500)
    250         OffsetTimeval(m_nexttrigger, -2000);
     236    if (m_synchronous)
     237    {
     238        if (m_delay < -(m_refresh_interval - 500))
     239            m_nexttrigger += 200;
     240        else if (m_delay > -500)
     241            m_nexttrigger += -2000;
     242    }
     243    else
     244    {
     245        if (m_delay < -(m_refresh_interval + 500))
     246            m_nexttrigger += 200;
     247        else if (m_delay >= 0)
     248            m_nexttrigger += -2000;
     249    }
    251250}
    252251
    253252#ifndef _WIN32
    void DRMVideoSync::Start(void) 
    337336    VideoSync::Start();
    338337}
    339338
    340 void DRMVideoSync::WaitForFrame(int sync_delay)
     339int DRMVideoSync::WaitForFrame(int sync_delay)
    341340{
    342341    // Offset for externally-provided A/V sync delay
    343     OffsetTimeval(m_nexttrigger, sync_delay);
     342    m_nexttrigger += sync_delay;
    344343
    345344    m_delay = CalcDelay();
    346345    //cerr << "WaitForFrame at : " << m_delay;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    360359    if (m_delay > 0)
    361360    {
    362361        // Wait for any remaining retrace intervals in one pass.
    363         int n = m_delay / m_refresh_interval + 1;
     362        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    364363
    365364        drm_wait_vblank_t blank;
    366365        blank.request.type = DRM_VBLANK_RELATIVE;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    370369        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence;
    371370        //cerr  << " Delay " << m_delay << endl;
    372371    }
     372    return m_delay;
    373373}
    374374
    375375void DRMVideoSync::AdvanceTrigger(void)
    void OpenGLVideoSync::Start(void) 
    497497#endif /* USING_OPENGL_VSYNC */
    498498}
    499499
    500 void OpenGLVideoSync::WaitForFrame(int sync_delay)
     500int OpenGLVideoSync::WaitForFrame(int sync_delay)
    501501{
    502502    (void) sync_delay;
    503503#ifdef USING_OPENGL_VSYNC
     504//#define GLVSYNCDEBUG
     505#ifdef GLVSYNCDEBUG
     506    int refreshcount = 0;
     507#endif
    504508    const QString msg1("First A/V Sync"), msg2("Second A/V Sync");
    505     OffsetTimeval(m_nexttrigger, sync_delay);
     509    m_nexttrigger += sync_delay;
    506510
    507511    VideoOutput *vo = dynamic_cast<VideoOutput*>(m_video_output);
    508512    if (vo && vo->IsEmbedding())
    void OpenGLVideoSync::WaitForFrame(int sync_delay) 
    510514        m_delay = CalcDelay();
    511515        if (m_delay > 0)
    512516            usleep(m_delay);
    513         return;
     517        return 0;
    514518    }
    515519
    516520    int err;
    517521    if (!m_context)
    518         return;
     522        return 0;
    519523    unsigned int frameNum = 0;
    520524
    521525    OpenGLContextLocker ctx_lock(m_context);
    522526    err = gMythGLXGetVideoSyncSGI(&frameNum);
    523527    checkGLSyncError("Frame Number Query", err);
    524528
     529#ifdef GLVSYNCDEBUG
     530    int delay1 = m_delay;
     531    int delay2;
     532#endif
    525533    // Always sync to the next retrace execpt when we are very late.
    526534    if ((m_delay = CalcDelay()) > -(m_refresh_interval/2))
    527535    {
     536#ifdef GLVSYNCDEBUG
     537        delay2 = m_delay;
     538#endif
    528539        err = gMythGLXWaitVideoSyncSGI(2, (frameNum+1)%2 ,&frameNum);
    529540        checkGLSyncError(msg1, err);
    530541        m_delay = CalcDelay();
     542#ifdef GLVSYNCDEBUG
     543        refreshcount++;
     544#endif
    531545    }
     546#ifdef GLVSYNCDEBUG
     547    else
     548        delay2 = m_delay;
     549#endif
    532550
     551#ifdef GLVSYNCDEBUG
     552    int delay3 = m_delay;
     553#endif
    533554    // Wait for any remaining retrace intervals in one pass.
    534555    if (m_delay > 0)
    535556    {
    536         uint n = m_delay / m_refresh_interval + 1;
     557        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
     558#ifdef GLVSYNCDEBUG
     559        refreshcount += (int)n;
     560#endif
    537561        err = gMythGLXWaitVideoSyncSGI((n+1), (frameNum+n)%(n+1), &frameNum);
    538562        checkGLSyncError(msg2, err);
    539563        m_delay = CalcDelay();
    540564    }
     565#ifdef GLVSYNCDEBUG
     566    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("VS: WFF: ri:%1 fi:%2 delay1:%3 delay2:%4 delay3:%5 skip:%6 finaldelay:%7")
     567            .arg(m_refresh_interval)
     568            .arg(m_frame_interval)
     569            .arg(delay1)
     570            .arg(delay2)
     571            .arg(delay3)
     572            .arg(refreshcount)
     573            .arg(m_delay)
     574           );
     575#endif
    541576
    542577#endif /* USING_OPENGL_VSYNC */
     578    return m_delay;
    543579}
    544580
    545581void OpenGLVideoSync::AdvanceTrigger(void)
    void OpenGLVideoSync::AdvanceTrigger(void) 
    548584
    549585    KeepPhase();
    550586    UpdateNexttrigger();
     587#ifdef GLVSYNCDEBUG
     588    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "VS: AdvanceTrigger");
     589#endif
    551590#endif /* USING_OPENGL_VSYNC */
    552591}
    553592#endif /* !_WIN32 */
    bool RTCVideoSync::TryInit(void) 
    594633    return true;
    595634}
    596635
    597 void RTCVideoSync::WaitForFrame(int sync_delay)
     636int RTCVideoSync::WaitForFrame(int sync_delay)
    598637{
    599     OffsetTimeval(m_nexttrigger, sync_delay);
     638    m_nexttrigger += sync_delay;
    600639
    601640    m_delay = CalcDelay();
    602641
    void RTCVideoSync::WaitForFrame(int sync_delay) 
    609648        if ((val < 0) && (m_delay > 0))
    610649            usleep(m_delay);
    611650    }
     651    return 0;
    612652}
    613653
    614654void RTCVideoSync::AdvanceTrigger(void)
    bool VDPAUVideoSync::TryInit(void) 
    637677    return true;
    638678}
    639679
    640 void VDPAUVideoSync::WaitForFrame(int sync_delay)
     680int VDPAUVideoSync::WaitForFrame(int sync_delay)
    641681{
    642682    // Offset for externally-provided A/V sync delay
    643     OffsetTimeval(m_nexttrigger, sync_delay);
     683    m_nexttrigger += sync_delay;
    644684    m_delay = CalcDelay();
    645685
    646686    if (m_delay < 0)
    void VDPAUVideoSync::WaitForFrame(int sync_delay) 
    648688
    649689    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    650690    vo->SetNextFrameDisplayTimeOffset(m_delay);
     691    return 0;
    651692}
    652693
    653694void VDPAUVideoSync::AdvanceTrigger(void)
    bool BusyWaitVideoSync::TryInit(void) 
    674715    return true;
    675716}
    676717
    677 void BusyWaitVideoSync::WaitForFrame(int sync_delay)
     718int BusyWaitVideoSync::WaitForFrame(int sync_delay)
    678719{
    679720    // Offset for externally-provided A/V sync delay
    680     OffsetTimeval(m_nexttrigger, sync_delay);
     721    m_nexttrigger += sync_delay;
    681722
    682723    m_delay = CalcDelay();
    683724
    void BusyWaitVideoSync::WaitForFrame(int sync_delay) 
    703744        if (cnt > 1)
    704745            m_cheat -= 200;
    705746    }
     747    return 0;
    706748}
    707749
    708750void BusyWaitVideoSync::AdvanceTrigger(void)
    bool USleepVideoSync::TryInit(void) 
    725767    return true;
    726768}
    727769
    728 void USleepVideoSync::WaitForFrame(int sync_delay)
     770int USleepVideoSync::WaitForFrame(int sync_delay)
    729771{
    730772    // Offset for externally-provided A/V sync delay
    731     OffsetTimeval(m_nexttrigger, sync_delay);
     773    m_nexttrigger += sync_delay;
    732774
    733775    m_delay = CalcDelay();
    734776    if (m_delay > 0)
    735777        usleep(m_delay);
     778    return 0;
    736779}
    737780
    738781void USleepVideoSync::AdvanceTrigger(void)
  • mythtv/libs/libmythtv/vsync.h

    diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
    index f077949..f8b1c4b 100644
    a b class VideoSync 
    7070    virtual void Start(void);
    7171
    7272    /** \brief Waits for next a frame or field.
     73     *   Returns delay to real frame timing in usec
    7374     *
    7475     *   Start(void), WaitForFrame(void), and Stop(void) should
    7576     *   always be called from same thread, to prevent bad
    class VideoSync 
    7879     *  \param sync_delay time until the desired frame or field
    7980     *  \sa CalcDelay(void), KeepPhase(void)
    8081     */
    81     virtual void WaitForFrame(int sync_delay) = 0;
     82    virtual int WaitForFrame(int sync_delay) = 0;
    8283
    8384    /// \brief Use the next frame or field for CalcDelay(void)
    8485    ///        and WaitForFrame(int).
    class VideoSync 
    104105                                 uint frame_interval, uint refresh_interval,
    105106                                 bool interlaced);
    106107  protected:
    107     static void OffsetTimeval(struct timeval& tv, int offset);
    108108    void UpdateNexttrigger(void);
    109109    int CalcDelay(void);
    110110    void KeepPhase(void);
    class VideoSync 
    113113    int m_frame_interval; // of video
    114114    int m_refresh_interval; // of display
    115115    bool m_interlaced;
    116     struct timeval m_nexttrigger;
     116    int64_t m_nexttrigger;
    117117    int m_delay;
     118    bool m_synchronous;
    118119   
    119120    static int m_forceskip;
    120121};
    class DRMVideoSync : public VideoSync 
    136137    QString getName(void) const { return QString("DRM"); }
    137138    bool TryInit(void);
    138139    void Start(void);
    139     void WaitForFrame(int sync_delay);
     140    int WaitForFrame(int sync_delay);
    140141    void AdvanceTrigger(void);
    141142
    142143  private:
    class OpenGLVideoSync : public VideoSync 
    178179    QString getName(void) const { return QString("SGI OpenGL"); }
    179180    bool TryInit(void);
    180181    void Start(void);
    181     void WaitForFrame(int sync_delay);
     182    int WaitForFrame(int sync_delay);
    182183    void AdvanceTrigger(void);
    183184
    184185  private:
    class RTCVideoSync : public VideoSync 
    207208
    208209    QString getName(void) const { return QString("RTC"); }
    209210    bool TryInit(void);
    210     void WaitForFrame(int sync_delay);
     211    int WaitForFrame(int sync_delay);
    211212    void AdvanceTrigger(void);
    212213
    213214  private:
    class VDPAUVideoSync : public VideoSync 
    228229
    229230    QString getName(void) const { return QString("VDPAU"); }
    230231    bool TryInit(void);
    231     void WaitForFrame(int sync_delay);
     232    int WaitForFrame(int sync_delay);
    232233    void AdvanceTrigger(void);
    233234
    234235  private:
    class BusyWaitVideoSync : public VideoSync 
    256257
    257258    QString getName(void) const { return QString("USleep with busy wait"); }
    258259    bool TryInit(void);
    259     void WaitForFrame(int sync_delay);
     260    int WaitForFrame(int sync_delay);
    260261    void AdvanceTrigger(void);
    261262
    262263  private:
    class USleepVideoSync : public VideoSync 
    284285
    285286    QString getName(void) const { return QString("USleep"); }
    286287    bool TryInit(void);
    287     void WaitForFrame(int sync_delay);
     288    int WaitForFrame(int sync_delay);
    288289    void AdvanceTrigger(void);
    289290};
    290291#endif /* VSYNC_H_INCLUDED */