Ticket #7964: mythtv_smoothsync.11.patch

File mythtv_smoothsync.11.patch, 53.2 KB (added by Mark Spieth, 14 years ago)

updated for r25575

  • mythtv/libs/libmyth/audiooutput.h

    smoother vsync with predictive frame skipping
    
    From: Mark Spieth <mspieth@digivation.com.au>
    
    
    ---
     mythtv/libs/libmyth/audiooutput.h                |    9 +
     mythtv/libs/libmyth/audiooutputbase.cpp          |  177 ++++++++++++++++------
     mythtv/libs/libmyth/audiooutputbase.h            |   35 +++-
     mythtv/libs/libmythfreesurround/freesurround.cpp |   54 ++-----
     mythtv/libs/libmythtv/avformatdecoder.cpp        |   23 +++
     mythtv/libs/libmythtv/avformatdecoder.h          |    2 
     mythtv/libs/libmythtv/mythplayer.cpp             |  160 ++++++++++++++++----
     mythtv/libs/libmythtv/mythplayer.h               |    5 +
     mythtv/libs/libmythtv/vsync.cpp                  |  147 ++++++++++++------
     mythtv/libs/libmythtv/vsync.h                    |   19 +-
     mythtv/programs/mythtranscode/transcode.cpp      |    6 -
     11 files changed, 451 insertions(+), 186 deletions(-)
    
    diff --git a/mythtv/libs/libmyth/audiooutput.h b/mythtv/libs/libmyth/audiooutput.h
    index 62cdda0..a532519 100644
    a b  
    44#include <QString>
    55#include <QVector>
    66
     7#include "compat.h"
    78#include "audiosettings.h"
    89#include "audiooutputsettings.h"
    910#include "mythcorecontext.h"
    class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    7172
    7273    virtual void Reset(void) = 0;
    7374
    74     virtual bool AddFrames(void *buffer, int samples, long long timecode) = 0;
     75    virtual bool AddFrames(void *buffer, int samples, int64_t timecode) = 0;
    7576
    76     virtual void SetTimecode(long long timecode) = 0;
     77    virtual void SetTimecode(int64_t timecode) = 0;
    7778    virtual bool IsPaused(void) const = 0;
    7879    virtual void Pause(bool paused) = 0;
    7980    virtual void PauseUntilBuffered(void) = 0;
    class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    8182    // Wait for all data to finish playing
    8283    virtual void Drain(void) = 0;
    8384
    84     virtual int GetAudiotime(void) = 0;
     85    virtual int64_t GetAudiotime(void) = 0;
    8586
    8687    /// report amount of audio buffered in milliseconds.
    87     virtual int GetAudioBufferedTime(void) { return 0; }
     88    virtual int64_t GetAudioBufferedTime(void) { return 0; }
    8889
    8990    virtual void SetSourceBitrate(int ) { }
    9091
  • mythtv/libs/libmyth/audiooutputbase.cpp

    diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
    index a0040e9..0a84ab1 100644
    a b AudioOutputBase::AudioOutputBase(const AudioSettings &settings) : 
    5656    passthru(false),
    5757    enc(false),                 reenc(false),
    5858    stretchfactor(1.0f),
     59    eff_stretchfactor(100000),
    5960
    6061    source(settings.source),    killaudio(false),
    6162
    void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor) 
    231232        return;
    232233
    233234    stretchfactor = lstretchfactor;
     235    eff_stretchfactor = (int)(100000.0f * lstretchfactor + 0.5);
    234236    if (pSoundStretch)
    235237    {
    236238        VBGENERAL(QString("Changing time stretch to %1").arg(stretchfactor));
    void AudioOutputBase::SetStretchFactorLocked(float lstretchfactor) 
    254256            bytes_per_frame = source_channels *
    255257                              AudioOutputSettings::SampleSize(FORMAT_FLT);
    256258            waud = raud = 0;
     259            reset_active.Ref();
    257260        }
    258261    }
    259262}
    bool AudioOutputBase::ToggleUpmix(void) 
    285288        return false;
    286289
    287290    upmix_default = !upmix_default;
     291    reset_active.Ref();
    288292
    289293    const AudioSettings settings(format, source_channels, codec,
    290294                                 source_samplerate, passthru);
    void AudioOutputBase::Reconfigure(const AudioSettings &orig_settings) 
    379383    QMutexLocker lockav(&avsync_lock);
    380384
    381385    waud = raud = 0;
     386    reset_active.Clear();
    382387    actually_paused = processing = false;
    383388
    384389    channels               = settings.channels;
    void AudioOutputBase::Reset() 
    651656    QMutexLocker lock(&audio_buflock);
    652657    QMutexLocker lockav(&avsync_lock);
    653658
    654     raud = waud = audbuf_timecode = audiotime = frames_buffered = 0;
     659    audbuf_timecode = audiotime = frames_buffered = 0;
     660    waud = raud;    // empty ring buffer
     661    reset_active.Ref();
    655662    current_seconds = -1;
    656663    was_paused = !pauseaudio;
    657664
    void AudioOutputBase::Reset() 
    665672 * Used by mythmusic for seeking since it doesn't provide timecodes to
    666673 * AddFrames()
    667674 */
    668 void AudioOutputBase::SetTimecode(long long timecode)
     675void AudioOutputBase::SetTimecode(int64_t timecode)
    669676{
    670677    audbuf_timecode = audiotime = timecode;
    671     frames_buffered = (long long)((timecode * source_samplerate) / 1000);
     678    frames_buffered = (int64_t)((timecode * source_samplerate) / 1000);
    672679}
    673680
    674681/**
    int AudioOutputBase::audioready() 
    723730/**
    724731 * Calculate the timecode of the samples that are about to become audible
    725732 */
    726 int AudioOutputBase::GetAudiotime(void)
     733int64_t AudioOutputBase::GetAudiotime(void)
    727734{
    728735    if (audbuf_timecode == 0)
    729736        return 0;
    730737
    731     int soundcard_buffer = 0;
    732738    int obpf = output_bytes_per_frame;
    733     int totalbuffer;
    734     long long oldaudiotime;
     739    int64_t oldaudiotime;
    735740
    736741    /* We want to calculate 'audiotime', which is the timestamp of the audio
    737        which is leaving the sound card at this instant.
     742       Which is leaving the sound card at this instant.
    738743
    739744       We use these variables:
    740745
    int AudioOutputBase::GetAudiotime(void) 
    746751       'totalbuffer' is the total # of bytes in our audio buffer, and the
    747752       sound card's buffer. */
    748753
    749     soundcard_buffer = GetBufferedOnSoundcard(); // bytes
    750754
    751755    QMutexLocker lockav(&avsync_lock);
    752756
     757    int64_t soundcard_buffer = GetBufferedOnSoundcard(); // bytes
     758    int64_t main_buffer = audioready();
     759
    753760    /* audioready tells us how many bytes are in audiobuffer
    754761       scaled appropriately if output format != internal format */
    755     totalbuffer = audioready() + soundcard_buffer;
    756 
    757     if (needs_upmix && upmixer)
    758         totalbuffer += upmixer->frameLatency() * obpf;
    759 
    760     if (pSoundStretch)
    761     {
    762         totalbuffer += pSoundStretch->numUnprocessedSamples() * obpf /
    763                        stretchfactor;
    764         totalbuffer += pSoundStretch->numSamples() * obpf;
    765     }
    766 
    767     if (encoder)
    768         totalbuffer += encoder->Buffered();
    769762
    770763    oldaudiotime = audiotime;
    771764
    772     audiotime = audbuf_timecode - (long long)(totalbuffer) * 100000 *
    773                                         stretchfactor / (obpf * effdsp);
     765    // timecode is the stretch adjusted version
     766    // of major post-stretched buffer contents
     767    // processing latencies are catered for in AddSamples/SetAudiotime to eliminate
     768    // race
     769    audiotime = audbuf_timecode - (( (main_buffer + soundcard_buffer) * eff_stretchfactor ) / (effdsp * obpf));
    774770
    775771    /* audiotime should never go backwards, but we might get a negative
    776772       value if GetBufferedOnSoundcard() isn't updated by the driver very
    int AudioOutputBase::GetAudiotime(void) 
    778774    if (audiotime < oldaudiotime)
    779775        audiotime = oldaudiotime;
    780776
    781     VBAUDIOTS(QString("GetAudiotime audt=%3 atc=%4 tb=%5 sb=%6 "
    782                       "sr=%7 obpf=%8 sf=%9")
     777    VBAUDIOTS(QString("GetAudiotime audt=%1 atc=%2 mb=%3 sb=%4 tb=%5 "
     778                      "sr=%6 obpf=%7 bpf=%8 sf=%9 %10 %11")
    783779              .arg(audiotime).arg(audbuf_timecode)
    784               .arg(totalbuffer).arg(soundcard_buffer)
    785               .arg(samplerate).arg(obpf).arg(stretchfactor));
     780              .arg(main_buffer)
     781              .arg(soundcard_buffer)
     782              .arg(main_buffer+soundcard_buffer)
     783              .arg(samplerate).arg(obpf).arg(bytes_per_frame).arg(stretchfactor)
     784              .arg((main_buffer + soundcard_buffer) * eff_stretchfactor)
     785              .arg(( (main_buffer + soundcard_buffer) * eff_stretchfactor ) / (effdsp * obpf))
     786              );
     787
     788    return audiotime;
     789}
     790
     791/**
     792 * Set the timecode of the top of the ringbuffer
     793 * Exclude all other processing elements as they dont vary
     794 * between AddSamples calls
     795 */
     796void AudioOutputBase::SetAudiotime(int frames, int64_t timecode)
     797{
     798    int64_t processframes_stretched = 0;
     799    int64_t processframes_unstretched = 0;
     800
     801    if (needs_upmix && upmixer)
     802        processframes_unstretched -= upmixer->frameLatency();
    786803
    787     return (int)audiotime;
     804    if (pSoundStretch)
     805    {
     806        processframes_unstretched -= pSoundStretch->numUnprocessedSamples();
     807        processframes_stretched -= pSoundStretch->numSamples();
     808    }
     809
     810    if (encoder)
     811        // the input buffered data is still in audio_bytes_per_sample format
     812        processframes_stretched -= encoder->Buffered() / output_bytes_per_frame;
     813
     814    int64_t old_audbuf_timecode = audbuf_timecode;
     815
     816    audbuf_timecode = timecode +
     817                (((frames + processframes_unstretched) * 100000) +
     818                  (processframes_stretched * eff_stretchfactor )) / effdsp;
     819
     820    // check for timecode wrap and reset audiotime if detected
     821    // timecode will always be monotonic asc if not seeked and reset
     822    // happens if seek or pause happens
     823    if (audbuf_timecode < old_audbuf_timecode)
     824        audiotime = 0;
     825
     826    VBAUDIOTS(QString("SetAudiotime atc=%1 tc=%2 f=%3 pfu=%4 pfs=%5")
     827              .arg(audbuf_timecode)
     828              .arg(timecode)
     829              .arg(frames)
     830              .arg(processframes_unstretched)
     831              .arg(processframes_stretched));
     832#ifdef AUDIOTSTESTING
     833    GetAudiotime();
     834#endif
    788835}
    789836
    790837/**
    int AudioOutputBase::GetAudiotime(void) 
    792839 * audible and the samples most recently added to the audiobuffer, i.e. the
    793840 * time in ms representing the sum total of buffered samples
    794841 */
    795 int AudioOutputBase::GetAudioBufferedTime(void)
     842int64_t AudioOutputBase::GetAudioBufferedTime(void)
    796843{
    797844    int ret = audbuf_timecode - GetAudiotime();
    798845    // Pulse can give us values that make this -ve
    int AudioOutputBase::CopyWithUpmix(char *buffer, int frames, int &org_waud) 
    938985 *
    939986 * Returns false if there's not enough space right now
    940987 */
    941 bool AudioOutputBase::AddFrames(void *buffer, int frames, long long timecode)
     988bool AudioOutputBase::AddFrames(void *buffer, int in_frames, int64_t timecode)
    942989{
    943990    int org_waud = waud,               afree = audiofree();
    944     int bpf      = bytes_per_frame,    len   = frames * source_bytes_per_frame;
     991    int frames = in_frames;
     992    int bpf      = bytes_per_frame,    len   = in_frames * source_bytes_per_frame;
    945993    int used     = kAudioRingBufferSize - afree;
    946994    bool music   = false;
     995    int bdiff;
    947996
    948997    VBAUDIOTS(QString("AddFrames frames=%1, bytes=%2, used=%3, free=%4, "
    949998                      "timecode=%5 needsupmix=%6")
    bool AudioOutputBase::AddFrames(void *buffer, int frames, long long timecode) 
    9651014    if (timecode < 0)
    9661015    {
    9671016        // Send original samples to mythmusic visualisation
    968         timecode = (long long)(frames_buffered) * 1000 / source_samplerate;
     1017        timecode = (int64_t)(frames_buffered) * 1000 / source_samplerate;
    9691018        frames_buffered += frames;
    9701019        dispatchVisual((uchar *)buffer, len, timecode, source_channels,
    9711020                       output_settings->FormatToBits(format));
    bool AudioOutputBase::AddFrames(void *buffer, int frames, long long timecode) 
    10181067                    .arg(src_strerror(error)));
    10191068
    10201069        buffer = src_out;
    1021         frames = src_data.output_frames_gen;
     1070        in_frames = frames = src_data.output_frames_gen;
    10221071    }
    10231072    else if (processing)
    10241073        buffer = src_in;
    bool AudioOutputBase::AddFrames(void *buffer, int frames, long long timecode) 
    10261075    /* we want the timecode of the last sample added but we are given the
    10271076       timecode of the first - add the time in ms that the frames added
    10281077       represent */
    1029     audbuf_timecode = timecode + ((long long)(frames) * 100000 / effdsp);
    10301078
    10311079    // Copy samples into audiobuffer, with upmix if necessary
    10321080    if ((len = CopyWithUpmix((char *)buffer, frames, org_waud)) <= 0)
    1033         return true;
     1081    {
     1082        //return true;
     1083        goto done;
     1084    }
    10341085
    10351086    frames = len / bpf;
    10361087
    1037     int bdiff = kAudioRingBufferSize - waud;
     1088    bdiff = kAudioRingBufferSize - waud;
    10381089
    10391090    if (pSoundStretch)
    10401091    {
    bool AudioOutputBase::AddFrames(void *buffer, int frames, long long timecode) 
    11121163
    11131164    waud = org_waud;
    11141165
     1166done:
     1167    SetAudiotime(in_frames, timecode);
     1168
    11151169    return true;
    11161170}
    11171171
    void AudioOutputBase::OutputAudioLoop(void) 
    11591213    uchar *fragment_buf = new uchar[fragment_size + 16];
    11601214    uchar *fragment     = (uchar *)AOALIGN(fragment_buf[0]);
    11611215
     1216    // to reduce startup latency, write silence in 8ms chunks
     1217    int zero_fragment_size = (int)(0.008*samplerate/channels);
     1218    zero_fragment_size *= bytes_per_frame;   // make sure its a multiple of bytes_per_frame
     1219    if (zero_fragment_size > fragment_size)
     1220        zero_fragment_size = fragment_size;
     1221
    11621222    bzero(zeros, fragment_size);
    11631223
    11641224    while (!killaudio)
    void AudioOutputBase::OutputAudioLoop(void) 
    12071267            continue;
    12081268        }
    12091269
     1270#ifdef AUDIOTSTESTING
     1271        VBAUDIOTS("WriteAudio Start");
     1272#endif
    12101273        Status();
    12111274
    1212         if (GetAudioData(fragment, fragment_size, true))
    1213             WriteAudio(fragment, fragment_size);
     1275        // delay setting raud until after phys buffer is filled
     1276        // so GetAudiotime will be accurate without locking
     1277        reset_active.TestAndDeref();
     1278        int next_raud = raud;
     1279        if (GetAudioData(fragment, fragment_size, true, &next_raud))
     1280        {
     1281            if (!reset_active.TestAndDeref())
     1282            {
     1283                WriteAudio(fragment, fragment_size);
     1284                if (!reset_active.TestAndDeref())
     1285                    raud = next_raud;
     1286            }
     1287        }
     1288#ifdef AUDIOTSTESTING
     1289        GetAudiotime();
     1290        VBAUDIOTS("WriteAudio Done");
     1291#endif
     1292
    12141293    }
    12151294
    12161295    delete[] zeros;
    void AudioOutputBase::OutputAudioLoop(void) 
    12271306 * nothing. Otherwise, we'll copy less than 'size' bytes if that's all that's
    12281307 * available. Returns the number of bytes copied.
    12291308 */
    1230 int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer)
     1309int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer, int *local_raud)
    12311310{
    12321311
     1312#define LRPOS audiobuffer + *local_raud
    12331313    // re-check audioready() in case things changed.
    12341314    // for example, ClearAfterSeek() might have run
    12351315    int avail_size   = audioready();
    12361316    int frag_size    = size;
    12371317    int written_size = size;
    12381318
     1319    if (local_raud == NULL)
     1320        local_raud = &raud;
     1321
    12391322    if (!full_buffer && (size > avail_size))
    12401323    {
    12411324        // when full_buffer is false, return any available data
    int AudioOutputBase::GetAudioData(uchar *buffer, int size, bool full_buffer) 
    12611344    {
    12621345        if (fromFloats)
    12631346            off = AudioOutputUtil::fromFloat(output_format, buffer,
    1264                                              RPOS, bdiff);
     1347                                             LRPOS, bdiff);
    12651348        else
    12661349        {
    1267             memcpy(buffer, RPOS, bdiff);
     1350            memcpy(buffer, LRPOS, bdiff);
    12681351            off = bdiff;
    12691352        }
    12701353
    12711354        frag_size -= bdiff;
    1272         raud = 0;
     1355        *local_raud = 0;
    12731356    }
    12741357    if (frag_size > 0)
    12751358    {
    12761359        if (fromFloats)
    12771360            AudioOutputUtil::fromFloat(output_format, buffer + off,
    1278                                        RPOS, frag_size);
     1361                                       LRPOS, frag_size);
    12791362        else
    1280             memcpy(buffer + off, RPOS, frag_size);
     1363            memcpy(buffer + off, LRPOS, frag_size);
    12811364    }
    12821365
    1283     raud += frag_size;
     1366    *local_raud += frag_size;
    12841367
    12851368    // Mute individual channels through mono->stereo duplication
    12861369    MuteState mute_state = GetMuteState();
  • mythtv/libs/libmyth/audiooutputbase.h

    diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
    index 78fe44d..20cb9db 100644
    a b class FreeSurround; 
    3131class AudioOutputDigitalEncoder;
    3232struct AVCodecContext;
    3333
     34class AsyncLooseLock
     35{
     36public:
     37    AsyncLooseLock() { head = tail = 0; }
     38    void Clear() { head = tail = 0; }
     39    void Ref() { head++; }
     40    bool TestAndDeref() { bool r; if ((r=(head != tail))) tail++; return r; }
     41private:
     42    int head;
     43    int tail;
     44};
     45
    3446class AudioOutputBase : public AudioOutput, public QThread
    3547{
    3648 public:
    class AudioOutputBase : public AudioOutput, public QThread 
    5971    int GetSWVolume(void);
    6072
    6173    // timecode is in milliseconds.
    62     virtual bool AddFrames(void *buffer, int frames, long long timecode);
     74    virtual bool AddFrames(void *buffer, int frames, int64_t timecode);
    6375
    64     virtual void SetTimecode(long long timecode);
     76    virtual void SetTimecode(int64_t timecode);
    6577    virtual bool IsPaused(void) const { return actually_paused; }
    6678    virtual void Pause(bool paused);
    6779    void PauseUntilBuffered(void);
    class AudioOutputBase : public AudioOutput, public QThread 
    6981    // Wait for all data to finish playing
    7082    virtual void Drain(void);
    7183
    72     virtual int GetAudiotime(void);
    73     virtual int GetAudioBufferedTime(void);
     84    virtual int64_t GetAudiotime(void);
     85    virtual int64_t GetAudioBufferedTime(void);
    7486
    7587    // Send output events showing current progress
    7688    virtual void Status(void);
    class AudioOutputBase : public AudioOutput, public QThread 
    8597
    8698    static const uint kAudioSRCInputSize  = 16384<<1;
    8799    static const uint kAudioSRCOutputSize = 16384<<3;
    88     /// Audio Buffer Size -- should be divisible by 12,10,8,6,4,2..
    89     static const uint kAudioRingBufferSize   = 1536000;
     100    /// Audio Buffer Size -- should be divisible by 32,24,16,12,10,8,6,4,2..
     101    static const uint kAudioRingBufferSize   = 3072000;
    90102
    91103 protected:
    92104    // Following function must be called from subclass constructor
    class AudioOutputBase : public AudioOutput, public QThread 
    107119    virtual bool StartOutputThread(void);
    108120    virtual void StopOutputThread(void);
    109121
    110     int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer);
     122    int GetAudioData(uchar *buffer, int buf_size, bool fill_buffer, int *local_raud = NULL);
    111123
    112124    void OutputAudioLoop(void);
    113125
    class AudioOutputBase : public AudioOutput, public QThread 
    142154    bool passthru, enc, reenc;
    143155
    144156    float stretchfactor;
     157    int  eff_stretchfactor;     // scaled to 100000 as effdsp is
    145158    AudioOutputSource source;
    146159
    147160    bool killaudio;
    class AudioOutputBase : public AudioOutput, public QThread 
    157170 private:
    158171    int CopyWithUpmix(char *buffer, int frames, int &org_waud);
    159172    AudioOutputSettings *output_settingsraw;
     173    void SetAudiotime(int frames, int64_t timecode);
    160174    AudioOutputSettings *output_settings;
    161175    bool need_resampler;
    162176    SRC_STATE *src_ctx;
    class AudioOutputBase : public AudioOutput, public QThread 
    177191
    178192    bool processing;
    179193
    180     long long frames_buffered;
     194    int64_t frames_buffered;
    181195
    182196    bool audio_thread_exists;
    183197
    class AudioOutputBase : public AudioOutput, public QThread 
    190204    QMutex avsync_lock;
    191205
    192206    // timecode of audio leaving the soundcard (same units as timecodes)
    193     long long audiotime;
     207    int64_t audiotime;
    194208
    195209    /* Audio circular buffer */
    196210    int raud, waud;     /* read and write positions */
    197211    // timecode of audio most recently placed into buffer
    198     long long audbuf_timecode;
     212    int64_t audbuf_timecode;
     213    AsyncLooseLock reset_active;
    199214
    200215    QMutex killAudioLock;
    201216
  • 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/avformatdecoder.cpp

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
    index 260c361..a751f4f 100644
    a b AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, 
    232232      start_code_state(0xffffffff),
    233233      lastvpts(0),                  lastapts(0),
    234234      lastccptsu(0),
     235      firstvpts(0),                 firstvptsinuse(false),
    235236      using_null_videoout(use_null_videoout),
    236237      video_codec_id(kCodec_NONE),
    237238      no_hardware_decoders(no_hardware_decode),
    void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames, 
    672673        if (decoded_video_frame)
    673674            GetPlayer()->DiscardVideoFrame(decoded_video_frame);
    674675    }
     676
     677    if (doflush)
     678    {
     679        firstvpts = 0;
     680        firstvptsinuse = true;
     681    }
    675682}
    676683
    677684void AvFormatDecoder::Reset(bool reset_video_data, bool seek_reset)
    void AvFormatDecoder::MpegPreProcessPkt(AVStream *stream, AVPacket *pkt) 
    26562663
    26572664                gopset = false;
    26582665                prevgoppos = 0;
     2666                firstvpts =
    26592667                lastapts = lastvpts = lastccptsu = 0;
     2668                firstvptsinuse = true;
    26602669
    26612670                // fps debugging info
    26622671                float avFPS = normalized_fps(stream, context);
    bool AvFormatDecoder::H264PreProcessPkt(AVStream *stream, AVPacket *pkt) 
    27662775
    27672776            gopset = false;
    27682777            prevgoppos = 0;
     2778            firstvpts =
    27692779            lastapts = lastvpts = lastccptsu = 0;
     2780            firstvptsinuse = true;
    27702781
    27712782            // fps debugging info
    27722783            float avFPS = normalized_fps(stream, context);
    bool AvFormatDecoder::ProcessVideoPacket(AVStream *curstream, AVPacket *pkt) 
    29953006    framesPlayed++;
    29963007
    29973008    lastvpts = temppts;
     3009    if (!firstvpts && firstvptsinuse)
     3010        firstvpts = temppts;
    29983011
    29993012    return true;
    30003013}
    bool AvFormatDecoder::ProcessAudioPacket(AVStream *curstream, AVPacket *pkt, 
    37453758                skipaudio = false;
    37463759        }
    37473760
     3761        // skip any audio frames preceding first video frame
     3762        if (firstvptsinuse && firstvpts && (lastapts < firstvpts))
     3763        {
     3764            VERBOSE(VB_PLAYBACK+VB_TIMESTAMP,
     3765                LOC + QString("discarding early audio timecode %1 %2 %3")
     3766                .arg(pkt->pts).arg(pkt->dts).arg(lastapts));
     3767            break;
     3768        }
     3769        firstvptsinuse = false;
     3770
    37483771        avcodeclock->lock();
    37493772        data_size = 0;
    37503773
  • mythtv/libs/libmythtv/avformatdecoder.h

    diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h
    index 23d990b..3bff3b3 100644
    a b class AvFormatDecoder : public DecoderBase 
    262262    long long lastvpts;
    263263    long long lastapts;
    264264    long long lastccptsu;
     265    long long firstvpts;
     266    bool      firstvptsinuse;
    265267
    266268    bool using_null_videoout;
    267269    MythCodecID video_codec_id;
  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 0c0f50b..7e9b12d 100644
    a b MythPlayer::MythPlayer(bool muted) 
    235235      // Audio and video synchronization stuff
    236236      videosync(NULL),              avsync_delay(0),
    237237      avsync_adjustment(0),         avsync_avg(0),
     238      avsync_predictor(0),          avsync_predictor_enabled(false),
    238239      refreshrate(0),
    239240      lastsync(false),              repeat_delay(0),
    240241      // Time Code stuff
    void MythPlayer::SetVideoParams(int width, int height, double fps, 
    870871        video_frame_rate = fps;
    871872        float temp_speed = (play_speed == 0.0f) ?
    872873            audio.GetStretchFactor() : play_speed;
    873         frame_interval = (int)(1000000.0f / video_frame_rate / temp_speed);
     874        SetFrameInterval(kScan_Progressive, 1.0 / (video_frame_rate * temp_speed));
    874875    }
    875876
    876877    if (videoOutput)
    int MythPlayer::NextCaptionTrack(int mode) 
    15641565    return NextCaptionTrack(nextmode);
    15651566}
    15661567
     1568void MythPlayer::SetFrameInterval(FrameScanType scan, double frame_period)
     1569{
     1570    frame_interval = (int)(1000000.0f * frame_period + 0.5f);
     1571    if (!avsync_predictor_enabled)
     1572        avsync_predictor = 0;
     1573    avsync_predictor_enabled = false;
     1574
     1575    VERBOSE(VB_PLAYBACK, LOC + QString("SetFrameInterval ps:%1 scan:%2")
     1576            .arg(play_speed).arg(scan)
     1577           );
     1578    if (play_speed < 1 || play_speed > 2 || refreshrate <= 0)
     1579        return;
     1580
     1581    avsync_predictor_enabled = ((frame_interval-(frame_interval/200)) < refreshrate);
     1582}
     1583
     1584void MythPlayer::ResetAVSync(void)
     1585{
     1586    avsync_avg = 0;
     1587    if (!avsync_predictor_enabled || avsync_predictor >= refreshrate)
     1588        avsync_predictor = 0;
     1589    prevtc = 0;
     1590    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V sync reset");
     1591}
     1592
    15671593void MythPlayer::InitAVSync(void)
    15681594{
    15691595    videosync->Start();
    void MythPlayer::InitAVSync(void) 
    15861612                       .arg(refreshrate).arg(frame_interval);
    15871613        VERBOSE(VB_PLAYBACK, LOC + msg);
    15881614
     1615        SetFrameInterval(m_scan, 1.0 / (video_frame_rate * play_speed));
     1616
    15891617        // try to get preferential scheduling, but ignore if we fail to.
    15901618        myth_nice(-19);
    15911619    }
    15921620}
    15931621
     1622int64_t MythPlayer::AVSyncGetAudiotime(void)
     1623{
     1624    int64_t currentaudiotime = 0;
     1625    if (normal_speed)
     1626    {
     1627        currentaudiotime = audio.GetAudioTime();
     1628    }
     1629    return currentaudiotime;
     1630}
     1631
    15941632#define MAXDIVERGE  3.0f
    15951633#define DIVERGELIMIT 30.0f
    15961634void MythPlayer::AVSync(bool limit_delay)
    15971635{
    15981636    float diverge = 0.0f;
    15991637    int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
     1638    int vsync_delay_clock = 0;
     1639    int64_t currentaudiotime = 0;
     1640
    16001641    // attempt to reduce fps for standalone PIP
    16011642    if (player_ctx->IsPIP() && framesPlayed % 2)
    16021643    {
    void MythPlayer::AVSync(bool limit_delay) 
    16311672    if (kScan_Detect == m_scan || kScan_Ignore == m_scan)
    16321673        ps = kScan_Progressive;
    16331674
     1675    bool dropframe = false;
     1676    QString dbg;
     1677
     1678    if (avsync_predictor_enabled) // && !prebuffering)
     1679    {
     1680        avsync_predictor += frame_interval;
     1681        if (avsync_predictor >= refreshrate)
     1682        {
     1683            int refreshperiodsinframe = avsync_predictor/refreshrate;
     1684            avsync_predictor -= refreshrate * refreshperiodsinframe;
     1685        }
     1686        else
     1687        {
     1688            dropframe = true;
     1689            dbg = "A/V predict drop frame, ";
     1690        }
     1691    }
     1692
    16341693    if (diverge < -MAXDIVERGE)
    16351694    {
     1695        dropframe = true;
    16361696        // If video is way behind of audio, adjust for it...
    1637         QString dbg = QString("Video is %1 frames behind audio (too slow), ")
     1697        dbg = QString("Video is %1 frames behind audio (too slow), ")
    16381698            .arg(-diverge);
     1699    }
    16391700
     1701    if (dropframe)
     1702    {
    16401703        // Reset A/V Sync
    16411704        lastsync = true;
    16421705
     1706        currentaudiotime = AVSyncGetAudiotime();
     1707
    16431708        if (buffer && !using_null_videoout &&
    16441709            videoOutput->hasHWAcceleration() &&
    16451710           !videoOutput->IsSyncLocked())
    void MythPlayer::AVSync(bool limit_delay) 
    16641729        if (buffer)
    16651730            videoOutput->PrepareFrame(buffer, ps, osd);
    16661731
    1667         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
     1732        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("AVSync waitforframe %1 %2")
    16681733                .arg(avsync_adjustment).arg(m_double_framerate));
    1669         videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
    1670         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
     1734        vsync_delay_clock = videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
     1735        currentaudiotime = AVSyncGetAudiotime();
     1736        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + "AVSync show");
    16711737        videoOutput->Show(ps);
    16721738
    16731739        if (videoOutput->IsErrored())
    void MythPlayer::AVSync(bool limit_delay) 
    16961762                videoOutput->PrepareFrame(buffer, ps, osd);
    16971763
    16981764            // Display the second field
    1699             videosync->WaitForFrame(frameDelay + avsync_adjustment);
     1765            //videosync->AdvanceTrigger();
     1766            vsync_delay_clock = videosync->WaitForFrame(frameDelay + avsync_adjustment);
    17001767            videoOutput->Show(ps);
    17011768        }
    17021769
    17031770        repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
    17041771
    17051772        if (repeat_delay)
    1706             VERBOSE(VB_TIMESTAMP, QString("A/V repeat_pict, adding %1 repeat "
     1773            VERBOSE(VB_TIMESTAMP, LOC + QString("A/V repeat_pict, adding %1 repeat "
    17071774                    "delay").arg(repeat_delay));
    17081775    }
    17091776    else
    17101777    {
    1711         videosync->WaitForFrame(frameDelay);
     1778        vsync_delay_clock = videosync->WaitForFrame(frameDelay);
     1779        currentaudiotime = AVSyncGetAudiotime();
    17121780    }
    17131781
    17141782    if (output_jmeter)
    1715         output_jmeter->RecordCycleTime();
     1783    {
     1784        if (output_jmeter->RecordCycleTime())
     1785        {
     1786            VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V avsync_delay: %1, "
     1787                    "avsync_avg: %2")
     1788                    .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
     1789                    );
     1790        }
     1791    }
    17161792
    17171793    avsync_adjustment = 0;
    17181794
    void MythPlayer::AVSync(bool limit_delay) 
    17201796    {
    17211797        // If audio is way behind of video, adjust for it...
    17221798        // by cutting the frame rate in half for the length of this frame
    1723         avsync_adjustment = refreshrate;
     1799        //avsync_adjustment = refreshrate;
     1800        avsync_adjustment = frame_interval;
    17241801        lastsync = true;
    17251802        VERBOSE(VB_PLAYBACK, LOC +
    17261803                QString("Video is %1 frames ahead of audio,\n"
    void MythPlayer::AVSync(bool limit_delay) 
    17301807    if (audio.HasAudioOut() && normal_speed)
    17311808    {
    17321809        long long currentaudiotime = audio.GetAudioTime();
    1733         VERBOSE(VB_TIMESTAMP, QString(
     1810        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString(
    17341811                    "A/V timecodes audio %1 video %2 frameinterval %3 "
    1735                     "avdel %4 avg %5 tcoffset %6")
     1812                    "avdel %4 avg %5 tcoffset %6"
     1813                    " avp %7 avpen %8"
     1814                    " avdc %9"
     1815                    )
    17361816                .arg(currentaudiotime)
    17371817                .arg(buffer->timecode)
    17381818                .arg(frame_interval)
    1739                 .arg(buffer->timecode - currentaudiotime)
     1819                .arg(buffer->timecode - currentaudiotime - (int)(vsync_delay_clock*audio.GetStretchFactor()+500)/1000)
    17401820                .arg(avsync_avg)
    17411821                .arg(tc_wrap[TC_AUDIO])
     1822                .arg(avsync_predictor)
     1823                .arg(avsync_predictor_enabled)
     1824                .arg(vsync_delay_clock)
    17421825                 );
    17431826        if (currentaudiotime != 0 && buffer->timecode != 0)
    17441827        { // currentaudiotime == 0 after a seek
    17451828            // The time at the start of this frame (ie, now) is given by
    17461829            // last->timecode
    1747             int delta = (int)((buffer->timecode - prevtc)/play_speed) - (frame_interval / 1000);
    1748             prevtc = buffer->timecode;
    1749             //cerr << delta << " ";
    1750 
    1751             // If the timecode is off by a frame (dropped frame) wait to sync
    1752             if (delta > (int) frame_interval / 1200 &&
    1753                 delta < (int) frame_interval / 1000 * 3 &&
    1754                 prevrp == 0)
     1830            if (prevtc != 0)
    17551831            {
    1756                 // wait an extra frame interval
    1757                 avsync_adjustment += frame_interval;
     1832                int delta = (int)((buffer->timecode - prevtc)/play_speed) - (frame_interval / 1000);
     1833                // If the timecode is off by a frame (dropped frame) wait to sync
     1834                if (delta > (int) frame_interval / 1200 &&
     1835                    delta < (int) frame_interval / 1000 * 3 &&
     1836                    prevrp == 0)
     1837                {
     1838                    // wait an extra frame interval
     1839                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V delay %1").arg(delta));
     1840                    avsync_adjustment += frame_interval;
     1841                    //videosync->AdvanceTrigger();
     1842                    //if (m_double_framerate)
     1843                    //    videosync->AdvanceTrigger();
     1844                }
    17581845            }
     1846            prevtc = buffer->timecode;
    17591847            prevrp = buffer->repeat_pict;
    17601848
    1761             avsync_delay = (buffer->timecode - currentaudiotime) * 1000;//usec
     1849            avsync_delay = (buffer->timecode - currentaudiotime) * 1000 - (int)(vsync_delay_clock*audio.GetStretchFactor());  //usec
    17621850            // prevents major jitter when pts resets during dvd title
    17631851            if (avsync_delay > 2000000 && limit_delay)
    17641852                avsync_delay = 90000;
    17651853            avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
    17661854
     1855            int avsync_used = avsync_avg;
     1856            if (labs(avsync_used) > labs(avsync_delay))
     1857                avsync_used = avsync_delay;
     1858
    17671859            /* If the audio time codes and video diverge, shift
    17681860               the video by one interlaced field (1/2 frame) */
    17691861            if (!lastsync)
    17701862            {
    1771                 if (avsync_avg > frame_interval * 3 / 2)
     1863                if (avsync_used > refreshrate)
    17721864                {
    17731865                    avsync_adjustment += refreshrate;
    1774                     lastsync = true;
     1866                    //lastsync = true;
     1867                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high extend");
    17751868                }
    1776                 else if (avsync_avg < 0 - frame_interval * 3 / 2)
     1869                else if (avsync_used < 0 - refreshrate)
    17771870                {
    17781871                    avsync_adjustment -= refreshrate;
    1779                     lastsync = true;
     1872                    //lastsync = true;
     1873                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high skip");
    17801874                }
    17811875            }
    17821876            else
    void MythPlayer::AVSync(bool limit_delay) 
    17841878        }
    17851879        else
    17861880        {
    1787             avsync_avg = 0;
     1881            ResetAVSync();
    17881882        }
    17891883    }
     1884    else
     1885    {
     1886        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V no sync proc ns:%1").arg(normal_speed));
     1887    }
    17901888}
    17911889
    17921890void MythPlayer::DisplayPauseFrame(void)
    void MythPlayer::ChangeSpeed(void) 
    30183116    }
    30193117
    30203118    float temp_speed = (play_speed == 0.0) ? audio.GetStretchFactor() : play_speed;
    3021     frame_interval = (int) (1000000.0f * ffrew_skip / video_frame_rate /
    3022                             temp_speed);
     3119    SetFrameInterval(m_scan, ffrew_skip / (video_frame_rate * temp_speed));
    30233120
    30243121    VERBOSE(VB_PLAYBACK, LOC + "Play speed: " +
    30253122            QString("rate: %1 speed: %2 skip: %3 => new interval %4")
    void MythPlayer::ClearAfterSeek(bool clearvideobuffers) 
    33313428    commBreakMap.SetTracker(framesPlayed);
    33323429    commBreakMap.ResetLastSkip();
    33333430    needNewPauseFrame = true;
     3431    ResetAVSync();
    33343432}
    33353433
    33363434void MythPlayer::SetPlayerInfo(
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 5b662c2..8495402 100644
    a b class MPUBLIC MythPlayer 
    475475    void  WrapTimecode(long long &timecode, TCTypes tc_type);
    476476    void  InitAVSync(void);
    477477    virtual void AVSync(bool limit_delay = false);
     478    void  ResetAVSync(void);
     479    int64_t AVSyncGetAudiotime(void);
     480    void  SetFrameInterval(FrameScanType scan, double speed);
    478481    void  FallbackDeint(void);
    479482    void  CheckExtraAudioDecode(void);
    480483
    class MPUBLIC MythPlayer 
    656659    int        avsync_delay;
    657660    int        avsync_adjustment;
    658661    int        avsync_avg;
     662    int        avsync_predictor;
     663    bool       avsync_predictor_enabled;
    659664    int        refreshrate;
    660665    bool       lastsync;
    661666    bool       decode_extra_audio;
  • mythtv/libs/libmythtv/vsync.cpp

    diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
    index fb6d017..6123cd1 100644
    a b VideoSync::VideoSync(VideoOutput *video_output, 
    128128                     bool halve_frame_interval) :
    129129    m_video_output(video_output),   m_frame_interval(frameint),
    130130    m_refresh_interval(refreshint), m_interlaced(halve_frame_interval),
    131     m_delay(-1)
     131    m_nexttrigger(0),
     132    m_delay(-1),
     133    m_synchronous(false)
    132134{
    133     bzero(&m_nexttrigger, sizeof(m_nexttrigger));
     135    int fieldint = frameint;
     136    if (halve_frame_interval)
     137        fieldint /= 2;
     138    double sync_factor = fieldint * 2.0f / refreshint;
     139    sync_factor = sync_factor - round(sync_factor);
     140    m_synchronous = (sync_factor >= -0.005) && (sync_factor <= 0.005);
     141    VERBOSE(VB_PLAYBACK, LOC + QString("Set video sync frame interval to %1 (synced:%2)")
     142                                 .arg(m_frame_interval).arg(m_synchronous));
    134143}
    135144
    136 void VideoSync::Start(void)
     145int64_t GetTime(void)
    137146{
    138     gettimeofday(&m_nexttrigger, NULL); // now
     147    struct timeval now_tv;
     148    gettimeofday(&now_tv, NULL); // now
     149    return now_tv.tv_sec * 1000000LL + now_tv.tv_usec;
    139150}
    140151
    141 void VideoSync::OffsetTimeval(struct timeval& tv, int offset)
     152void VideoSync::Start(void)
    142153{
    143     tv.tv_usec += offset;
    144     while (tv.tv_usec > 999999)
    145     {
    146         tv.tv_sec++;
    147         tv.tv_usec -= 1000000;
    148     }
    149     while (tv.tv_usec < 0)
    150     {
    151         tv.tv_sec--;
    152         tv.tv_usec += 1000000;
    153     }
     154    m_nexttrigger = GetTime();
    154155}
    155156
    156157/** \fn VideoSync::CalcDelay()
    void VideoSync::OffsetTimeval(struct timeval& tv, int offset) 
    166167 */
    167168int VideoSync::CalcDelay()
    168169{
    169     struct timeval now;
    170     gettimeofday(&now, NULL);
     170    int64_t now = GetTime();
    171171    //cout << "CalcDelay: next: " << timeval_str(m_nexttrigger) << " now "
    172172    // << timeval_str(now) << endl;
    173173
    174     int ret_val = (m_nexttrigger.tv_sec - now.tv_sec) * 1000000 +
    175                   (m_nexttrigger.tv_usec - now.tv_usec);
     174    int ret_val = m_nexttrigger - now;
    176175
    177176    //cout << "delay " << ret_val << endl;
    178177
    int VideoSync::CalcDelay() 
    184183            ret_val = m_frame_interval * 4;
    185184
    186185        // set nexttrigger to our new target time
    187         m_nexttrigger.tv_sec = now.tv_sec;
    188         m_nexttrigger.tv_usec = now.tv_usec;
    189         OffsetTimeval(m_nexttrigger, ret_val);
     186        m_nexttrigger = now;
     187        m_nexttrigger += ret_val;
    190188    }
    191189
    192     if (ret_val < -m_frame_interval)
     190    if ((ret_val < -m_frame_interval) && (m_frame_interval >= m_refresh_interval))
    193191    {
    194192        ret_val = -m_frame_interval;
    195193
    196194        // set nexttrigger to our new target time
    197         m_nexttrigger.tv_sec = now.tv_sec;
    198         m_nexttrigger.tv_usec = now.tv_usec;
    199         OffsetTimeval(m_nexttrigger, ret_val);
     195        m_nexttrigger = now;
     196        m_nexttrigger += ret_val;
    200197    }
    201198
    202199    return ret_val;
    int VideoSync::CalcDelay() 
    213210void VideoSync::KeepPhase()
    214211{
    215212    // cerr << m_delay << endl;
    216     if (m_delay < -(m_refresh_interval/2))
    217         OffsetTimeval(m_nexttrigger, 200);
    218     else if (m_delay > -500)
    219         OffsetTimeval(m_nexttrigger, -2000);
     213    if (m_synchronous)
     214    {
     215        if (m_delay < -(m_refresh_interval - 500))
     216            m_nexttrigger += 200;
     217        else if (m_delay > -500)
     218            m_nexttrigger += -2000;
     219    }
     220    else
     221    {
     222        if (m_delay < -(m_refresh_interval + 500))
     223            m_nexttrigger += 200;
     224        else if (m_delay >= 0)
     225            m_nexttrigger += -2000;
     226    }
    220227}
    221228
    222229#ifndef _WIN32
    void DRMVideoSync::Start(void) 
    306313    VideoSync::Start();
    307314}
    308315
    309 void DRMVideoSync::WaitForFrame(int sync_delay)
     316int DRMVideoSync::WaitForFrame(int sync_delay)
    310317{
    311318    // Offset for externally-provided A/V sync delay
    312     OffsetTimeval(m_nexttrigger, sync_delay);
     319    m_nexttrigger += sync_delay;
    313320
    314321    m_delay = CalcDelay();
    315322    //cerr << "WaitForFrame at : " << m_delay;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    329336    if (m_delay > 0)
    330337    {
    331338        // Wait for any remaining retrace intervals in one pass.
    332         int n = m_delay / m_refresh_interval + 1;
     339        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    333340
    334341        drm_wait_vblank_t blank;
    335342        blank.request.type = DRM_VBLANK_RELATIVE;
    void DRMVideoSync::WaitForFrame(int sync_delay) 
    339346        //cerr << "Wait " << n << " intervals. Count " << blank.request.sequence;
    340347        //cerr  << " Delay " << m_delay << endl;
    341348    }
     349    return m_delay;
    342350
    343351    KeepPhase();
    344352}
    void OpenGLVideoSync::Start(void) 
    409417#endif /* USING_OPENGL_VSYNC */
    410418}
    411419
    412 void OpenGLVideoSync::WaitForFrame(int sync_delay)
     420int OpenGLVideoSync::WaitForFrame(int sync_delay)
    413421{
    414422    (void) sync_delay;
    415423#ifdef USING_OPENGL_VSYNC
     424//#define GLVSYNCDEBUG
     425#ifdef GLVSYNCDEBUG
     426    int refreshcount = 0;
     427#endif
    416428    const QString msg1("First A/V Sync"), msg2("Second A/V Sync");
    417     OffsetTimeval(m_nexttrigger, sync_delay);
     429    m_nexttrigger += sync_delay;
    418430
    419431    if (m_video_output && m_video_output->IsEmbedding())
    420432    {
    421433        m_delay = CalcDelay();
    422434        if (m_delay > 0)
    423435            usleep(m_delay);
    424         return;
     436        return 0;
    425437    }
    426438
    427439    if (!m_context)
    428         return;
     440        return 0;
    429441
    430442    unsigned int frameNum = m_context->GetVideoSyncCount();
    431443
     444#ifdef GLVSYNCDEBUG
     445    int delay1 = m_delay;
     446    int delay2;
     447#endif
    432448    // Always sync to the next retrace execpt when we are very late.
    433449    if ((m_delay = CalcDelay()) > -(m_refresh_interval/2))
    434450    {
     451#ifdef GLVSYNCDEBUG
     452        delay2 = m_delay;
     453#endif
    435454        m_context->WaitForVideoSync(2, (frameNum+1)%2 ,&frameNum);
    436455        m_delay = CalcDelay();
     456#ifdef GLVSYNCDEBUG
     457        refreshcount++;
     458#endif
    437459    }
     460#ifdef GLVSYNCDEBUG
     461    else
     462        delay2 = m_delay;
     463#endif
    438464
     465#ifdef GLVSYNCDEBUG
     466    int delay3 = m_delay;
     467#endif
    439468    // Wait for any remaining retrace intervals in one pass.
    440469    if (m_delay > 0)
    441470    {
    442         uint n = m_delay / m_refresh_interval + 1;
     471        //uint n = m_delay / m_refresh_interval + 1;
     472        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
    443473        m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
     474#ifdef GLVSYNCDEBUG
     475        refreshcount += (int)n;
     476#endif
    444477        m_delay = CalcDelay();
    445478    }
     479#ifdef GLVSYNCDEBUG
     480    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("VS: WFF: ri:%1 fi:%2 delay1:%3 delay2:%4 delay3:%5 skip:%6 finaldelay:%7")
     481            .arg(m_refresh_interval)
     482            .arg(m_frame_interval)
     483            .arg(delay1)
     484            .arg(delay2)
     485            .arg(delay3)
     486            .arg(refreshcount)
     487            .arg(m_delay)
     488           );
     489#endif
     490
     491    return m_delay;
    446492
    447493    KeepPhase();
     494#ifdef GLVSYNCDEBUG
     495    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, "VS: AdvanceTrigger");
     496#endif
    448497#endif /* USING_OPENGL_VSYNC */
    449498}
    450499#endif /* !_WIN32 */
    bool RTCVideoSync::TryInit(void) 
    491540    return true;
    492541}
    493542
    494 void RTCVideoSync::WaitForFrame(int sync_delay)
     543int RTCVideoSync::WaitForFrame(int sync_delay)
    495544{
    496     OffsetTimeval(m_nexttrigger, sync_delay);
     545    m_nexttrigger += sync_delay;
    497546
    498547    m_delay = CalcDelay();
    499548
    void RTCVideoSync::WaitForFrame(int sync_delay) 
    506555        if ((val < 0) && (m_delay > 0))
    507556            usleep(m_delay);
    508557    }
     558    return 0;
    509559}
    510560#endif /* __linux__ */
    511561
    bool VDPAUVideoSync::TryInit(void) 
    529579    return true;
    530580}
    531581
    532 void VDPAUVideoSync::WaitForFrame(int sync_delay)
     582int VDPAUVideoSync::WaitForFrame(int sync_delay)
    533583{
    534584    // Offset for externally-provided A/V sync delay
    535     OffsetTimeval(m_nexttrigger, sync_delay);
     585    m_nexttrigger += sync_delay;
    536586    m_delay = CalcDelay();
    537587
    538588    if (m_delay < 0)
    void VDPAUVideoSync::WaitForFrame(int sync_delay) 
    540590
    541591    VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
    542592    vo->SetNextFrameDisplayTimeOffset(m_delay);
     593    return 0;
    543594}
    544595#endif
    545596
    bool BusyWaitVideoSync::TryInit(void) 
    560611    return true;
    561612}
    562613
    563 void BusyWaitVideoSync::WaitForFrame(int sync_delay)
     614int BusyWaitVideoSync::WaitForFrame(int sync_delay)
    564615{
    565616    // Offset for externally-provided A/V sync delay
    566     OffsetTimeval(m_nexttrigger, sync_delay);
     617    m_nexttrigger += sync_delay;
    567618
    568619    m_delay = CalcDelay();
    569620
    void BusyWaitVideoSync::WaitForFrame(int sync_delay) 
    589640        if (cnt > 1)
    590641            m_cheat -= 200;
    591642    }
     643    return 0;
    592644}
    593645
    594646USleepVideoSync::USleepVideoSync(VideoOutput *vo,
    bool USleepVideoSync::TryInit(void) 
    606658    return true;
    607659}
    608660
    609 void USleepVideoSync::WaitForFrame(int sync_delay)
     661int USleepVideoSync::WaitForFrame(int sync_delay)
    610662{
    611663    // Offset for externally-provided A/V sync delay
    612     OffsetTimeval(m_nexttrigger, sync_delay);
     664    m_nexttrigger += sync_delay;
    613665
    614666    m_delay = CalcDelay();
    615667    if (m_delay > 0)
    616668        usleep(m_delay);
     669    return 0;
    617670}
    618671
  • mythtv/libs/libmythtv/vsync.h

    diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
    index d506ada..92d1fb9 100644
    a b class VideoSync 
    6464    virtual void Start(void);
    6565
    6666    /** \brief Waits for next a frame or field.
     67     *   Returns delay to real frame timing in usec
    6768     *
    6869     *   Start(void), WaitForFrame(void), and Stop(void) should
    6970     *   always be called from same thread, to prevent bad
    class VideoSync 
    7273     *  \param sync_delay time until the desired frame or field
    7374     *  \sa CalcDelay(void), KeepPhase(void)
    7475     */
    75     virtual void WaitForFrame(int sync_delay) = 0;
     76    virtual int WaitForFrame(int sync_delay) = 0;
    7677
    7778    /// \brief Returns the (minimum) refresh interval of the output device.
    7879    int getRefreshInterval(void) const { return m_refresh_interval; }
    class VideoSync 
    9091                                 uint frame_interval, uint refresh_interval,
    9192                                 bool interlaced);
    9293  protected:
    93     static void OffsetTimeval(struct timeval& tv, int offset);
    9494    int CalcDelay(void);
    9595    void KeepPhase(void);
    9696
    class VideoSync 
    9898    int m_frame_interval; // of video
    9999    int m_refresh_interval; // of display
    100100    bool m_interlaced;
    101     struct timeval m_nexttrigger;
     101    int64_t m_nexttrigger;
    102102    int m_delay;
     103    bool m_synchronous;
    103104   
    104105    static int m_forceskip;
    105106};
    class DRMVideoSync : public VideoSync 
    121122    QString getName(void) const { return QString("DRM"); }
    122123    bool TryInit(void);
    123124    void Start(void);
    124     void WaitForFrame(int sync_delay);
     125    int WaitForFrame(int sync_delay);
    125126
    126127  private:
    127128    int m_dri_fd;
    class OpenGLVideoSync : public VideoSync 
    162163    QString getName(void) const { return QString("SGI OpenGL"); }
    163164    bool TryInit(void);
    164165    void Start(void);
    165     void WaitForFrame(int sync_delay);
     166    int WaitForFrame(int sync_delay);
    166167
    167168  private:
    168169    MythRenderOpenGL  *m_context;
    class RTCVideoSync : public VideoSync 
    190191
    191192    QString getName(void) const { return QString("RTC"); }
    192193    bool TryInit(void);
    193     void WaitForFrame(int sync_delay);
     194    int WaitForFrame(int sync_delay);
    194195
    195196  private:
    196197    int m_rtcfd;
    class VDPAUVideoSync : public VideoSync 
    210211
    211212    QString getName(void) const { return QString("VDPAU"); }
    212213    bool TryInit(void);
    213     void WaitForFrame(int sync_delay);
     214    int WaitForFrame(int sync_delay);
    214215
    215216  private:
    216217};
    class BusyWaitVideoSync : public VideoSync 
    237238
    238239    QString getName(void) const { return QString("USleep with busy wait"); }
    239240    bool TryInit(void);
    240     void WaitForFrame(int sync_delay);
     241    int WaitForFrame(int sync_delay);
    241242
    242243  private:
    243244    int m_cheat;
    class USleepVideoSync : public VideoSync 
    264265
    265266    QString getName(void) const { return QString("USleep"); }
    266267    bool TryInit(void);
    267     void WaitForFrame(int sync_delay);
     268    int WaitForFrame(int sync_delay);
    268269};
    269270#endif /* VSYNC_H_INCLUDED */
  • mythtv/programs/mythtranscode/transcode.cpp

    diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp
    index a2105eb..468f714 100644
    a b class AudioReencodeBuffer : public AudioOutput 
    8282    }
    8383
    8484    // timecode is in milliseconds.
    85     virtual bool AddFrames(void *buffer, int frames, long long timecode)
     85    virtual bool AddFrames(void *buffer, int frames, int64_t timecode)
    8686    {
    8787        int freebuf = bufsize - audiobuffer_len;
    8888
    class AudioReencodeBuffer : public AudioOutput 
    111111        return true;
    112112    }
    113113
    114     virtual void SetTimecode(long long timecode)
     114    virtual void SetTimecode(int64_t timecode)
    115115    {
    116116        last_audiotime = timecode;
    117117    }
    class AudioReencodeBuffer : public AudioOutput 
    132132        // Do nothing
    133133    }
    134134
    135     virtual int GetAudiotime(void)
     135    virtual int64_t GetAudiotime(void)
    136136    {
    137137        return last_audiotime;
    138138    }