Ticket #6974: play-to-end.patch

File play-to-end.patch, 13.9 KB (added by Mark Spieth, 10 years ago)
  • mythtv/libs/libmyth/audiooutput.h

    play media to end when eof detected
    
    From:  <mspieth@digivation.com.au>
    
    
    ---
    
     mythtv/libs/libmyth/audiooutput.h           |    1 
     mythtv/libs/libmyth/audiooutputbase.cpp     |   29 ++++++++++++
     mythtv/libs/libmyth/audiooutputbase.h       |    2 +
     mythtv/libs/libmythtv/NuppelVideoPlayer.cpp |   63 +++++++++++++++++----------
     mythtv/libs/libmythtv/NuppelVideoPlayer.h   |   14 +++++-
     mythtv/programs/mythtranscode/transcode.cpp |    1 
     6 files changed, 83 insertions(+), 27 deletions(-)
    
    
    diff --git a/mythtv/libs/libmyth/audiooutput.h b/mythtv/libs/libmyth/audiooutput.h
    index 943bd77..f410032 100644
    a b class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners 
    3333
    3434    // do AddSamples calls block?
    3535    virtual void SetBlocking(bool blocking) = 0;
     36    virtual void SetTimedBlocking(bool blocking) = 0;
    3637   
    3738    // dsprate is in 100 * samples/second
    3839    virtual void SetEffDsp(int dsprate) = 0;
  • mythtv/libs/libmyth/audiooutputbase.cpp

    diff --git a/mythtv/libs/libmyth/audiooutputbase.cpp b/mythtv/libs/libmyth/audiooutputbase.cpp
    index ef2f3d5..5a1b687 100644
    a b AudioOutputBase::AudioOutputBase(const AudioSettings &settings) : 
    5353    surround_mode(FreeSurround::SurroundModePassive),
    5454
    5555    blocking(false),
     56    timed_blocking(false),
    5657
    5758    lastaudiolen(0),            samples_buffered(0),
    5859
    void AudioOutputBase::SetBlocking(bool blocking) 
    511512    this->blocking = blocking;
    512513}
    513514
     515void AudioOutputBase::SetTimedBlocking(bool blocking)
     516{
     517    VERBOSE(VB_AUDIO, LOC + QString("Timed blocking: %1").arg(blocking));
     518    this->timed_blocking = blocking;
     519}
     520
    514521int AudioOutputBase::audiolen(bool use_lock)
    515522{
    516523    /* Thread safe, returns the number of valid bytes in the audio buffer */
    bool AudioOutputBase::AddSamples(char *buffers[], int samples, 
    671678        len += (pSoundStretch->numUnprocessedSamples() +
    672679                (int)(pSoundStretch->numSamples()/audio_stretchfactor))*abps;
    673680
     681    if ((len > afree) && !blocking && timed_blocking && !pauseaudio)
     682    {
     683        int time_to_sleep = ((len - afree) * 1000000LL) / (abps * audio_samplerate);
     684        VERBOSE(VB_AUDIO, LOC + QString("timed block %1 %2").arg(len - afree).arg(time_to_sleep));
     685        if (time_to_sleep > 0)
     686        {
     687            usleep(time_to_sleep + 50000);
     688            afree = audiofree(true);
     689        }
     690    }
     691
    674692    if ((len > afree) && !blocking)
    675693    {
    676694        VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + QString(
    bool AudioOutputBase::AddSamples(char *buffer, int samples, long long timecode) 
    740758                (int)(pSoundStretch->numSamples()/audio_stretchfactor))*abps;
    741759    }
    742760
     761    if ((len > afree) && !blocking && timed_blocking && !pauseaudio)
     762    {
     763        int time_to_sleep = ((len - afree) * 1000000LL) / (abps * audio_samplerate);
     764        VERBOSE(VB_AUDIO, LOC + QString("timed block %1 %2").arg(len - afree).arg(time_to_sleep));
     765        if (time_to_sleep > 0)
     766        {
     767            usleep(time_to_sleep + 50000);
     768            afree = audiofree(true);
     769        }
     770    }
     771
    743772    if ((len > afree) && !blocking)
    744773    {
    745774        VERBOSE(VB_AUDIO+VB_TIMESTAMP, LOC + QString(
  • mythtv/libs/libmyth/audiooutputbase.h

    diff --git a/mythtv/libs/libmyth/audiooutputbase.h b/mythtv/libs/libmyth/audiooutputbase.h
    index 1f636e2..4575e91 100644
    a b class AudioOutputBase : public AudioOutput, public QThread 
    3737
    3838    // do AddSamples calls block?
    3939    virtual void SetBlocking(bool blocking);
     40    virtual void SetTimedBlocking(bool blocking);
    4041
    4142    // dsprate is in 100 * samples/second
    4243    virtual void SetEffDsp(int dsprate);
    class AudioOutputBase : public AudioOutput, public QThread 
    161162    int surround_mode;
    162163
    163164    bool blocking; // do AddSamples calls block?
     165    bool timed_blocking; // do AddSamples calls block?
    164166
    165167    int lastaudiolen;
    166168    long long samples_buffered;
  • mythtv/libs/libmythtv/NuppelVideoPlayer.cpp

    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp b/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp
    index 84e013d..36dc49d 100644
    a b NuppelVideoPlayer::NuppelVideoPlayer() 
    162162      parentWidget(NULL), embedid(0),
    163163      embx(-1), emby(-1), embw(-1), embh(-1),
    164164      // State
    165       eof(false),
     165      eof(kEofStateNone),
    166166      m_double_framerate(false),    m_double_process(false),
    167167      m_can_double(false),          m_deint_possible(true),
    168168      paused(false),
    void NuppelVideoPlayer::PauseDecoder(void) 
    491491    QMutex mutex;
    492492    mutex.lock();
    493493
    494     while (!eof && !actuallypaused &&
    495            !decoderThreadPaused.wait(&mutex, 100) &&
    496            !eof && !actuallypaused)
     494    while ((eof == kEofStateNone) && !actuallypaused &&
     495           !decoderThreadPaused.wait(&mutex, 100))
    497496    {
    498497        VERBOSE(VB_IMPORTANT, LOC_WARN +
    499498                "Waited too long for decoder to pause");
    void NuppelVideoPlayer::PauseVideo(bool wait) 
    590589    {
    591590        videoThreadPaused.wait(&pauseUnpauseLock, 250);
    592591
    593         if (video_actually_paused || eof)
     592        if (video_actually_paused || (eof != kEofStateNone))
    594593            break;
    595594
    596595        if ((i % 10) == 9)
    void NuppelVideoPlayer::UnpauseVideo(bool wait) 
    607606    {
    608607        videoThreadUnpaused.wait(&pauseUnpauseLock, 250);
    609608
    610         if (!video_actually_paused || eof)
     609        if (!video_actually_paused || (eof != kEofStateNone))
    611610            break;
    612611
    613612        if ((i % 10) == 9)
    QString NuppelVideoPlayer::ReinitAudio(void) 
    928927        if (!audioOutput)
    929928            errMsg = QObject::tr("Unable to create AudioOutput.");
    930929        else
     930        {
    931931            errMsg = audioOutput->GetError();
     932            audioOutput->SetTimedBlocking(true);
     933        }
    932934
    933935        if (!errMsg.isEmpty())
    934936        {
    int NuppelVideoPlayer::OpenFile(bool skipDsp, uint retries, 
    12961298    GetDecoder()->setTranscoding(transcoding);
    12971299    CheckExtraAudioDecode();
    12981300
    1299     eof = false;
     1301    eof = kEofStateNone;
    13001302
    13011303    // Set 'no_video_decode' to true for audio only decodeing
    13021304    bool no_video_decode = false;
    void NuppelVideoPlayer::SwitchToProgram(void) 
    32733275        OpenDummy();
    32743276        ResetPlaying();
    32753277        DoPause();
    3276         eof = false;
     3278        eof = kEofStateNone;
    32773279        delete pginfo;
    32783280        return;
    32793281    }
    void NuppelVideoPlayer::SwitchToProgram(void) 
    32843286    if (!player_ctx->buffer->IsOpen())
    32853287    {
    32863288        VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram's OpenFile failed.");
    3287         eof = true;
     3289        eof = kEofStateImmediate;
    32883290        SetErrored(QObject::tr("Error opening switch program buffer"));
    32893291        delete pginfo;
    32903292        return;
    32913293    }
    32923294
    3293     if (eof)
     3295    if (eof != kEofStateNone)
    32943296    {
    32953297        discontinuity = true;
    32963298        ClearSubtitles();
    void NuppelVideoPlayer::SwitchToProgram(void) 
    33263328    if (IsErrored())
    33273329    {
    33283330        VERBOSE(VB_IMPORTANT, LOC_ERR + "SwitchToProgram failed.");
    3329         eof = true;
     3331        eof = kEofStateDelayed;
    33303332        return;
    33313333    }
    33323334
    void NuppelVideoPlayer::SwitchToProgram(void) 
    33413343        GetDecoder()->SyncPositionMap();
    33423344    }
    33433345
    3344     eof = false;
     3346    eof = kEofStateNone;
    33453347}
    33463348
    33473349void NuppelVideoPlayer::FileChangedCallback(void)
    void NuppelVideoPlayer::FileChangedCallback(void) 
    33583360
    33593361    player_ctx->buffer->Unpause();
    33603362
    3361     eof = false;
     3363    eof = kEofStateNone;
    33623364
    33633365    player_ctx->SetNVPChangingBuffers(false);
    33643366
    void NuppelVideoPlayer::JumpToProgram(void) 
    34003402        OpenDummy();
    34013403        ResetPlaying();
    34023404        DoPause();
    3403         eof = false;
     3405        eof = kEofStateNone;
    34043406        delete pginfo;
    34053407        return;
    34063408    }
    void NuppelVideoPlayer::JumpToProgram(void) 
    34093411    if (!player_ctx->buffer->IsOpen())
    34103412    {
    34113413        VERBOSE(VB_IMPORTANT, LOC_ERR + "JumpToProgram's OpenFile failed.");
    3412         eof = true;
     3414        eof = kEofStateImmediate;
    34133415        SetErrored(QObject::tr("Error opening jump program file buffer"));
    34143416        delete pginfo;
    34153417        return;
    void NuppelVideoPlayer::JumpToProgram(void) 
    34633465        GetDecoder()->setExactSeeks(seeks);
    34643466    }
    34653467
    3466     eof = false;
     3468    eof = kEofStateNone;
    34673469    player_ctx->SetNVPChangingBuffers(false);
    34683470}
    34693471
    bool NuppelVideoPlayer::StartPlaying(bool openfile) 
    36453647            player_ctx->tvchain->JumpToNext(true, 1);
    36463648            JumpToProgram();
    36473649        }
    3648         else if ((!paused || eof) && player_ctx->tvchain &&
     3650        else if ((!paused || (eof != kEofStateNone)) && player_ctx->tvchain &&
    36493651                 !GetDecoder()->GetWaitForChange())
    36503652        {
    36513653            if (player_ctx->tvchain->NeedsToSwitch())
    bool NuppelVideoPlayer::StartPlaying(bool openfile) 
    36973699            continue;
    36983700        }
    36993701
    3700         if (eof)
     3702        if (eof != kEofStateNone)
    37013703        {
    37023704            if (player_ctx->tvchain)
    37033705            {
    bool NuppelVideoPlayer::StartPlaying(bool openfile) 
    37113713                    VERBOSE(VB_PLAYBACK, "Ignoring livetv eof in decoder loop");
    37123714                usleep(50000);
    37133715            }
    3714             else
     3716            else if (eof == kEofStateImmediate)
     3717            {
    37153718                break;
     3719            }
     3720            else
     3721            {
     3722                VERBOSE(VB_PLAYBACK, "waiting for no video frames " << videoOutput->ValidVideoFrames());
     3723                if (videoOutput && videoOutput->ValidVideoFrames() < 3)
     3724                {
     3725                    eof = kEofStateImmediate;
     3726                    break;
     3727                }
     3728                else
     3729                    usleep(50000);
     3730            }
    37163731        }
    37173732
    37183733        if (isDummy)
    bool NuppelVideoPlayer::StartPlaying(bool openfile) 
    37993814                if (fftime >= 5)
    38003815                    DoFastForward();
    38013816
    3802                 if (eof)
     3817                if (eof != kEofStateNone)
    38033818                    continue;
    38043819
    38053820                UnpauseVideo(true);
    bool NuppelVideoPlayer::StartPlaying(bool openfile) 
    38543869                      && !player_ctx->IsPIP() &&
    38553870                      player_ctx->GetState() == kState_WatchingPreRecorded))
    38563871                {
    3857                     eof = true;
     3872                    eof = kEofStateImmediate;
    38583873                }
    38593874            }
    38603875            else
    bool NuppelVideoPlayer::TranscodeGetNextFrame(QMap<long long, int>::Iterator &dm 
    61506165
    61516166    if (!GetDecoder()->GetFrame(0))
    61526167        return false;
    6153     if (eof)
     6168    if (eof != kEofStateNone)
    61546169        return false;
    61556170
    61566171    if (honorCutList && (!deleteMap.isEmpty()))
    bool NuppelVideoPlayer::TranscodeGetNextFrame(QMap<long long, int>::Iterator &dm 
    61846199            }
    61856200        }
    61866201    }
    6187     if (eof)
     6202    if (eof != kEofStateNone)
    61886203      return false;
    61896204    *is_key = GetDecoder()->isLastFrameKey();
    61906205    return true;
    bool NuppelVideoPlayer::RebuildSeekTable(bool showPercentage, StatusCallback cb, 
    62766291        fflush( stdout );
    62776292    }
    62786293
    6279     while (!eof)
     6294    while (eof == kEofStateNone)
    62806295    {
    62816296        looped = true;
    62826297        myFramesPlayed++;
  • mythtv/libs/libmythtv/NuppelVideoPlayer.h

    diff --git a/mythtv/libs/libmythtv/NuppelVideoPlayer.h b/mythtv/libs/libmythtv/NuppelVideoPlayer.h
    index f930f02..f5e3907 100644
    a b enum 
    9999    kDisplayTeletextMenu        = 0x40,
    100100};
    101101
     102// Eof States
     103typedef enum
     104{
     105    kEofStateNone,
     106    kEofStateDelayed,
     107    kEofStateImmediate
     108} EofState;
     109
    102110class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader
    103111{
    104112    friend class PlayerContext;
    class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    146154    void SetLength(int len)                   { totalLength = len; }
    147155    void SetVideoFilters(const QString &override);
    148156    void SetFramesPlayed(long long played)    { framesPlayed = played; }
    149     void SetEof(void)                         { eof = true; }
     157    void SetEof(void)                         { eof = kEofStateDelayed; }
    150158    void SetPIPActive(bool is_active)         { pip_active = is_active; }
    151159    void SetPIPVisible(bool is_visible)       { pip_visible = is_visible; }
    152160    bool AddPIPPlayer(NuppelVideoPlayer *pip, PIPLocation loc, uint timeout);
    class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    214222    // Bool Gets
    215223    bool    GetRawAudioState(void) const;
    216224    bool    GetLimitKeyRepeat(void) const     { return limitKeyRepeat; }
    217     bool    GetEof(void) const                { return eof; }
     225    bool    GetEof(void) const                { return eof != kEofStateNone; }
    218226    bool    IsErrored(void) const;
    219227    bool    IsPlaying(uint wait_ms = 0, bool wait_for = true) const;
    220228    bool    AtNormalSpeed(void) const         { return next_normal_speed; }
    class MPUBLIC NuppelVideoPlayer : public CC608Reader, public CC708Reader 
    569577    mutable QMutex pauseUnpauseLock;
    570578    mutable QMutex internalPauseLock;
    571579    mutable QMutex playingLock;
    572     bool    eof;             ///< At end of file/ringbuffer
     580    EofState eof;             ///< At end of file/ringbuffer
    573581    bool     m_double_framerate;///< Output fps is double Video (input) rate
    574582    bool     m_double_process;///< Output filter must processed at double rate
    575583    bool     m_can_double;    ///< VideoOutput capable of doubling frame rate
  • mythtv/programs/mythtranscode/transcode.cpp

    diff --git a/mythtv/programs/mythtranscode/transcode.cpp b/mythtv/programs/mythtranscode/transcode.cpp
    index ff8eb54..ed909c8 100644
    a b class AudioReencodeBuffer : public AudioOutput 
    8383    }
    8484
    8585    virtual void SetBlocking(bool block) { (void)block; }
     86    virtual void SetTimedBlocking(bool block) { (void)block; }
    8687    virtual void Reset(void)
    8788    {
    8889        audiobuffer_len = 0;