Ticket #9287: 9287-v1.patch

File 9287-v1.patch, 165.7 KB (added by danielk, 10 years ago)

initial patch

  • libs/libmythtv/mythiowrapper.cpp

     
    130130        else
    131131        {
    132132            if (flags & O_WRONLY)
    133                 rb = new RingBuffer(pathname, true, false, -1); // Writeable
     133                rb = RingBuffer::Create(
     134                    pathname, true, false,
     135                    RingBuffer::kDefaultOpenTimeout, true); // Writeable
    134136            else
    135                 rb = new RingBuffer(pathname, false, true, -1); // Read-Only
     137                rb = RingBuffer::Create(
     138                    pathname, false, true,
     139                    RingBuffer::kDefaultOpenTimeout, true); // Read-Only
    136140
    137141            if (!rb)
    138142                return -1;
    139143
    140             rb->SetStreamOnly(true);
    141             rb->OpenFile(pathname);
    142144            rb->Start();
    143145        }
    144146
  • libs/libmythtv/NuppelVideoRecorder.cpp

     
    731731    if (!ringBuffer)
    732732    {
    733733        VERBOSE(VB_IMPORTANT, LOC + "Warning, old RingBuffer creation");
    734         ringBuffer = new RingBuffer("output.nuv", true);
     734        ringBuffer = RingBuffer::Create("output.nuv", true);
    735735        weMadeBuffer = true;
    736736        livetv = false;
    737737        if (!ringBuffer->IsOpen())
  • libs/libmythtv/importrecorder.cpp

     
    103103    if (_import_fd && _request_recording && !_error)
    104104    {
    105105        MythCommFlagPlayer *cfp = new MythCommFlagPlayer();
    106         RingBuffer *rb = new RingBuffer(
     106        RingBuffer *rb = RingBuffer::Create(
    107107            ringBuffer->GetFilename(), false, true, 6000);
    108108
    109109        PlayerContext *ctx = new PlayerContext(kImportRecorderInUseID);
  • libs/libmythtv/avformatdecoder.cpp

     
    652652void AvFormatDecoder::SeekReset(long long newKey, uint skipFrames,
    653653                                bool doflush, bool discardFrames)
    654654{
    655     if (ringBuffer->isDVD())
    656     {
    657         if (ringBuffer->InDiscMenuOrStillFrame() ||
    658             newKey == 0)
    659             return;
    660     }
     655    if (ringBuffer->IsInDiscMenuOrStillFrame() || newKey == 0)
     656        return;
    661657
    662658    VERBOSE(VB_PLAYBACK, LOC +
    663659            QString("SeekReset(%1, %2, %3 flush, %4 discard)")
     
    717713
    718714        prevgoppos = 0;
    719715        gopset = false;
    720         if (!ringBuffer->isDVD())
     716        if (!ringBuffer->IsDVD())
    721717        {
    722718            if (!no_dts_hack)
    723719            {
     
    759755{
    760756    DecoderBase::Reset();
    761757
    762     if (ringBuffer->isDVD())
     758    if (ringBuffer->IsDVD())
    763759        SyncPositionMap();
    764760}
    765761
     
    800796    int streamed = 0;
    801797    int buffer_size = 32768;
    802798
    803     if (ringBuffer->isDVD()) {
     799    if (ringBuffer->IsDVD())
     800    {
    804801        streamed = 1;
    805802        buffer_size = 2048;
    806803    }
     
    920917        QMutexLocker locker(avcodeclock);
    921918        ret = av_find_stream_info(ic);
    922919    }
    923     if (ringBuffer->isDVD())
     920    if (ringBuffer->IsDVD())
    924921    {
    925922        if (!ringBuffer->DVD()->StartFromBeginning())
    926923            return -1;
     
    935932        return -1;
    936933    }
    937934    ic->streams_changed = HandleStreamChange;
    938     if (ringBuffer->isDVD())
     935    if (ringBuffer->IsDVD())
    939936        ic->streams_changed = HandleDVDStreamChange;
    940937    ic->stream_change_data = this;
    941938
    942939    fmt->flags &= ~AVFMT_NOFILE;
    943940
    944     if (!ringBuffer->isDVD() && !livetv)
     941    if (!ringBuffer->IsDVD() && !livetv)
    945942        av_estimate_timings(ic, 0);
    946943
    947944    // Scan for the initial A/V streams
     
    12191216            <<") type ("<<ff_codec_type_string(enc->codec_type)
    12201217            <<").");
    12211218
    1222     if (ringBuffer && ringBuffer->isDVD())
     1219    if (ringBuffer && ringBuffer->IsDVD())
    12231220        directrendering = false;
    12241221
    12251222    enc->opaque = (void *)this;
     
    17211718    map<int,uint> lang_aud_cnt;
    17221719    uint audioStreamCount = 0;
    17231720
    1724     if (ringBuffer && ringBuffer->isDVD() &&
     1721    if (ringBuffer && ringBuffer->IsDVD() &&
    17251722        ringBuffer->DVD()->AudioStreamsChanged())
    17261723    {
    17271724        ringBuffer->DVD()->AudioStreamsChanged(false);
     
    18171814#ifdef USING_XVMC
    18181815
    18191816                    bool force_xv = no_hardware_decoders;
    1820                     if (ringBuffer && ringBuffer->isDVD())
     1817                    if (ringBuffer && ringBuffer->IsDVD())
    18211818                    {
    18221819                        if (dec.left(4) == "xvmc")
    18231820                            dvd_xvmc_enabled = true;
    18241821
    1825                         if (ringBuffer->InDiscMenuOrStillFrame() &&
     1822                        if (ringBuffer->IsInDiscMenuOrStillFrame() &&
    18261823                            dvd_xvmc_enabled)
    18271824                        {
    18281825                            force_xv = true;
     
    18451842                        enc->codec_id = (CodecID)
    18461843                            myth2av_codecid(mcid, vcd, idct, mc, vdpau);
    18471844
    1848                         if (ringBuffer && ringBuffer->isDVD() &&
     1845                        if (ringBuffer && ringBuffer->IsDVD() &&
    18491846                            (mcid == video_codec_id) &&
    18501847                            dvd_video_codec_changed)
    18511848                        {
     
    20712068        if (enc->codec_type == CODEC_TYPE_SUBTITLE)
    20722069        {
    20732070            int lang;
    2074             if (ringBuffer && ringBuffer->isBD())
    2075                 lang = ringBuffer->BD()->GetSubtitleLanguage(subtitleStreamCount);
     2071            if (ringBuffer && ringBuffer->IsBD())
     2072            {
     2073                lang = ringBuffer->BD()->
     2074                    GetSubtitleLanguage(subtitleStreamCount);
     2075            }
    20762076            else
    20772077            {
    20782078                AVMetadataTag *metatag = av_metadata_get(ic->streams[i]->metadata,
     
    20962096        if (enc->codec_type == CODEC_TYPE_AUDIO)
    20972097        {
    20982098            int lang;
    2099             if (ringBuffer && ringBuffer->isDVD())
     2099            if (ringBuffer && ringBuffer->IsDVD())
     2100            {
    21002101                lang = ringBuffer->DVD()->GetAudioLanguage(
    21012102                    ringBuffer->DVD()->GetAudioTrackNum(ic->streams[i]->id));
    2102             else if (ringBuffer && ringBuffer->isBD())
     2103            }
     2104            else if (ringBuffer && ringBuffer->IsBD())
     2105            {
    21032106                lang = ringBuffer->BD()->GetAudioLanguage(audioStreamCount);
     2107            }
    21042108            else
    21052109            {
    2106                 AVMetadataTag *metatag = av_metadata_get(ic->streams[i]->metadata,
    2107                                                          "language", NULL, 0);
    2108                 lang = metatag ? get_canonical_lang(metatag->value) : iso639_str3_to_key("und");
     2110                AVMetadataTag *metatag = av_metadata_get(
     2111                    ic->streams[i]->metadata,
     2112                    "language", NULL, 0);
     2113                lang = metatag ? get_canonical_lang(metatag->value) :
     2114                    iso639_str3_to_key("und");
    21092115            }
    21102116
    21112117            int channels  = ic->streams[i]->codec->channels;
     
    21232129            else
    21242130            {
    21252131                int logical_stream_id;
    2126                 if (ringBuffer && ringBuffer->isDVD())
    2127                     logical_stream_id = ringBuffer->DVD()->GetAudioTrackNum(ic->streams[i]->id);
     2132                if (ringBuffer && ringBuffer->IsDVD())
     2133                    logical_stream_id =
     2134                        ringBuffer->DVD()->GetAudioTrackNum(ic->streams[i]->id);
    21282135                else
    21292136                    logical_stream_id = ic->streams[i]->id;
    21302137
     
    21482155            ringBuffer->UpdateRawBitrate(bitrate);
    21492156    }
    21502157
    2151     if (ringBuffer && ringBuffer->isDVD())
     2158    if (ringBuffer && ringBuffer->IsDVD())
    21522159    {
    21532160        if (tracks[kTrackTypeAudio].size() > 1)
    21542161        {
     
    21912198                m_parent->EnableSubtitles(false);
    21922199            }
    21932200            else if (trackNo >= 0 && trackNo < trackcount &&
    2194                     !ringBuffer->InDiscMenuOrStillFrame())
     2201                    !ringBuffer->IsInDiscMenuOrStillFrame())
    21952202            {
    21962203                    SetTrack(kTrackTypeSubtitle, trackNo);
    21972204                    m_parent->EnableSubtitles(true);
     
    22082215    {
    22092216        m_audio->SetAudioParams(FORMAT_NONE, -1, -1, CODEC_ID_NONE, -1, false);
    22102217        m_audio->ReinitAudio();
    2211         if (ringBuffer && ringBuffer->isDVD())
     2218        if (ringBuffer && ringBuffer->IsDVD())
    22122219            audioIn = AudioInfo();
    22132220    }
    22142221
     
    27542761    {
    27552762        bufptr = ff_find_start_code(bufptr, bufend, &start_code_state);
    27562763
    2757         if (ringBuffer->isDVD() && (start_code_state == SEQ_END_CODE))
     2764        if (ringBuffer->IsDVD() && (start_code_state == SEQ_END_CODE))
    27582765            ringBuffer->DVD()->NewSequence(true);
    27592766
    27602767        if (start_code_state >= SLICE_MIN && start_code_state <= SLICE_MAX)
     
    29983005        context->reordered_opaque = pkt->pts;
    29993006        ret = avcodec_decode_video2(context, &mpa_pic, &gotpicture, pkt);
    30003007        // Reparse it to not drop the DVD still frame
    3001         if (ringBuffer->isDVD() && ringBuffer->DVD()->NeedsStillFrame())
     3008        if (ringBuffer->IsDVD() && ringBuffer->DVD()->NeedsStillFrame())
    30023009            ret = avcodec_decode_video2(context, &mpa_pic, &gotpicture, pkt);
    30033010    }
    30043011    avcodeclock->unlock();
     
    30333040    // the DTS timestamp is missing. Also use fixups for missing PTS instead of
    30343041    // DTS to avoid oscillating between PTS and DTS. Only select DTS if PTS is
    30353042    // more faulty or never detected.
    3036     if (ringBuffer->isDVD())
     3043    if (ringBuffer->IsDVD())
    30373044    {
    30383045        if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
    30393046            pts = pkt->dts;
     
    31353142    // Validate the video pts against the last pts. If it's
    31363143    // a little bit smaller, equal or missing, compute
    31373144    // it from the last. Otherwise assume a wraparound.
    3138     if (!ringBuffer->isDVD() &&
     3145    if (!ringBuffer->IsDVD() &&
    31393146        temppts <= lastvpts &&
    31403147        (temppts + 10000 > lastvpts || temppts <= 0))
    31413148    {
     
    33493356    AVSubtitle subtitle;
    33503357    memset(&subtitle, 0, sizeof(AVSubtitle));
    33513358
    3352     if (ringBuffer->isDVD())
     3359    if (ringBuffer->IsDVD())
    33533360    {
    33543361        if (ringBuffer->DVD()->NumMenuButtons() > 0)
    33553362        {
     
    34603467    int lang_key = tracks[type][trackNo].language;
    34613468    if (kTrackTypeAudio == type)
    34623469    {
    3463         if (ringBuffer->isDVD())
     3470        if (ringBuffer->IsDVD())
    34643471            lang_key = ringBuffer->DVD()->GetAudioLanguage(trackNo);
    34653472
    34663473        QString msg = iso639_key_toName(lang_key);
     
    34773484            msg += QString(" %1").arg(s->codec->codec->name).toUpper();
    34783485
    34793486        int channels = 0;
    3480         if (ringBuffer->isDVD())
     3487        if (ringBuffer->IsDVD())
    34813488            channels = ringBuffer->DVD()->GetNumAudioChannels(trackNo);
    34823489        else if (s->codec->channels)
    34833490            channels = tracks[kTrackTypeAudio][trackNo].orig_num_channels;
     
    34933500    }
    34943501    else if (kTrackTypeSubtitle == type)
    34953502    {
    3496         if (ringBuffer->isDVD())
     3503        if (ringBuffer->IsDVD())
    34973504            lang_key = ringBuffer->DVD()->GetSubtitleLanguage(trackNo);
    34983505
    34993506        return QObject::tr("Subtitle") + QString(" %1: %2")
     
    35613568    if (kTrackTypeAudio == type)
    35623569        return AutoSelectAudioTrack();
    35633570
    3564     if (ringBuffer->InDiscMenuOrStillFrame())
     3571    if (ringBuffer->IsInDiscMenuOrStillFrame())
    35653572        return -1;
    35663573
    35673574    return DecoderBase::AutoSelectTrack(type);
     
    40164023
    40174024        total_decoded_audio += data_size;
    40184025
    4019         allowedquit |= ringBuffer->InDiscMenuOrStillFrame();
     4026        allowedquit |= ringBuffer->IsInDiscMenuOrStillFrame();
    40204027        // Audio can expand by a factor of 6 in audiooutputbase's audiobuffer
    40214028        allowedquit |= !(decodetype & kDecodeVideo) &&
    40224029                       ((ofill + total_decoded_audio * 6) > othresh);
     
    41094116                allowedquit = true;
    41104117        }
    41114118
    4112         if (ringBuffer->isDVD())
     4119        if (ringBuffer->IsDVD())
    41134120        {
    41144121            // Update the title length
    4115             if (m_parent->AtNormalSpeed() && ringBuffer->DVD()->PGCLengthChanged())
     4122            if (m_parent->AtNormalSpeed() &&
     4123                ringBuffer->DVD()->PGCLengthChanged())
    41164124            {
    41174125                ResetPosMap();
    41184126                SyncPositionMap();
     
    41394147            else if (lowbuffers && ((decodetype & kDecodeAV) == kDecodeAV) &&
    41404148                     storedPackets.count() < max_video_queue_size &&
    41414149                     lastapts < lastvpts + 100 &&
    4142                      !ringBuffer->InDiscMenuOrStillFrame())
     4150                     !ringBuffer->IsInDiscMenuOrStillFrame())
    41434151            {
    41444152                storevideoframes = true;
    41454153            }
     
    42084216            continue;
    42094217        }
    42104218
    4211         if (ringBuffer->isDVD() &&
     4219        if (ringBuffer->IsDVD() &&
    42124220            curstream->codec->codec_type == CODEC_TYPE_VIDEO)
    42134221        {
    42144222#ifdef USING_XVMC
     
    42244232                        dvd_xvmc_active = true;
    42254233                    }
    42264234
    4227                     bool indiscmenu   = ringBuffer->InDiscMenuOrStillFrame();
     4235                    bool indiscmenu   = ringBuffer->IsInDiscMenuOrStillFrame();
    42284236                    if ((indiscmenu && dvd_xvmc_active) ||
    42294237                        ((!indiscmenu && !dvd_xvmc_active)))
    42304238                    {
     
    42374245
    42384246                if ((video_width > 0) && dvd_video_codec_changed)
    42394247                {
    4240                     VERBOSE(VB_PLAYBACK, LOC + QString("DVD Stream/Codec Change "
    4241                                 "video_width %1 current_width %2 "
    4242                                 "dvd_video_codec_changed %3")
     4248                    VERBOSE(VB_PLAYBACK, LOC +
     4249                            QString("DVD Stream/Codec Change "
     4250                                    "video_width %1 current_width %2 "
     4251                                    "dvd_video_codec_changed %3")
    42434252                            .arg(video_width).arg(current_width)
    42444253                            .arg(dvd_video_codec_changed));
    42454254                    av_free_packet(pkt);
  • libs/libmythtv/DVDRingBuffer.cpp

     
    3333    "Part",
    3434};
    3535
    36 DVDRingBufferPriv::DVDRingBufferPriv()
    37     : m_dvdnav(NULL),     m_dvdBlockReadBuf(NULL),
    38       m_dvdFilename(QString::null),
    39       m_dvdBlockRPos(0),  m_dvdBlockWPos(0),
    40       m_pgLength(0),      m_pgcLength(0),
    41       m_cellStart(0),     m_cellChanged(false),
    42       m_pgcLengthChanged(false), m_pgStart(0),
    43       m_currentpos(0),
    44       m_lastNav(NULL),    m_part(0), m_lastPart(0),
    45       m_title(0),         m_lastTitle(0),   m_playerWait(false),
    46       m_titleParts(0),    m_gotStop(false), m_currentAngle(0),
    47       m_currentTitleAngleCount(0), m_newSequence(false),
    48       m_still(0), m_lastStill(0),
    49       m_audioStreamsChanged(false),
    50       m_dvdWaiting(false),
    51       m_titleLength(0),
     36DVDRingBuffer::DVDRingBuffer(const QString &lfilename) :
     37    m_dvdnav(NULL),     m_dvdBlockReadBuf(NULL),
     38    m_dvdBlockRPos(0),  m_dvdBlockWPos(0),
     39    m_pgLength(0),      m_pgcLength(0),
     40    m_cellStart(0),     m_cellChanged(false),
     41    m_pgcLengthChanged(false), m_pgStart(0),
     42    m_currentpos(0),
     43    m_lastNav(NULL),    m_part(0), m_lastPart(0),
     44    m_title(0),         m_lastTitle(0),   m_playerWait(false),
     45    m_titleParts(0),    m_gotStop(false), m_currentAngle(0),
     46    m_currentTitleAngleCount(0), m_newSequence(false),
     47    m_still(0), m_lastStill(0),
     48    m_audioStreamsChanged(false),
     49    m_dvdWaiting(false),
     50    m_titleLength(0),
    5251
    53       m_skipstillorwait(true),
    54       m_cellstartPos(0), m_buttonSelected(false),
    55       m_buttonExists(false), m_cellid(0),
    56       m_lastcellid(0), m_vobid(0),
    57       m_lastvobid(0), m_cellRepeated(false),
     52    m_skipstillorwait(true),
     53    m_cellstartPos(0), m_buttonSelected(false),
     54    m_buttonExists(false), m_cellid(0),
     55    m_lastcellid(0), m_vobid(0),
     56    m_lastvobid(0), m_cellRepeated(false),
    5857
    59       m_curAudioTrack(0),
    60       m_curSubtitleTrack(0),
    61       m_autoselectsubtitle(true),
    62       m_dvdname(NULL), m_serialnumber(NULL),
    63       m_seeking(false), m_seektime(0),
    64       m_currentTime(0),
    65       m_parent(NULL),
     58    m_curAudioTrack(0),
     59    m_curSubtitleTrack(0),
     60    m_autoselectsubtitle(true),
     61    m_dvdname(NULL), m_serialnumber(NULL),
     62    m_seeking(false), m_seektime(0),
     63    m_currentTime(0),
     64    m_parent(NULL),
    6665
    67       // Menu/buttons
    68       m_inMenu(false), m_buttonVersion(1), m_buttonStreamID(0),
    69       m_hl_button(0, 0, 0, 0), m_menuSpuPkt(0), m_menuBuflength(0)
     66    // Menu/buttons
     67    m_inMenu(false), m_buttonVersion(1), m_buttonStreamID(0),
     68    m_hl_button(0, 0, 0, 0), m_menuSpuPkt(0), m_menuBuflength(0)
    7069{
    7170    memset(&m_dvdMenuButton, 0, sizeof(AVSubtitle));
    7271    memset(m_dvdBlockWriteBuf, 0, sizeof(char) * DVD_BLOCK_SIZE);
     
    7877
    7978    for (uint i = 0; i < 8; i++)
    8079        m_seekSpeedMap.insert(def[i], seekValues[i]);
     80
     81    OpenFile(filename);
    8182}
    8283
    83 DVDRingBufferPriv::~DVDRingBufferPriv()
     84DVDRingBuffer::~DVDRingBuffer()
    8485{
    8586    CloseDVD();
    8687    ClearMenuSPUParameters();
    8788}
    8889
    89 void DVDRingBufferPriv::CloseDVD(void)
     90void DVDRingBuffer::CloseDVD(void)
    9091{
    9192    if (m_dvdnav)
    9293    {
     
    9697    }
    9798}
    9899
    99 long long DVDRingBufferPriv::NormalSeek(long long time)
     100long long DVDRingBuffer::Seek(long long pos, int whence, bool has_lock)
    100101{
     102    VERBOSE(VB_FILE, LOC + QString("Seek(%1,%2,%3)")
     103            .arg(pos).arg((SEEK_SET==whence)?"SEEK_SET":
     104                          ((SEEK_CUR==whence)?"SEEK_CUR":"SEEK_END"))
     105            .arg(has_lock?"locked":"unlocked"));
     106
     107    long long ret = -1;
     108
     109    // lockForWrite takes priority over lockForRead, so this will
     110    // take priority over the lockForRead in the read ahead thread.
     111    if (!has_lock)
     112        rwlock.lockForWrite();
     113
     114    poslock.lockForWrite();
     115
     116    // Optimize no-op seeks
     117    if (readaheadrunning &&
     118        ((whence == SEEK_SET && pos == readpos) ||
     119         (whence == SEEK_CUR && pos == 0)))
     120    {
     121        ret = readpos;
     122
     123        poslock.unlock();
     124        if (!has_lock)
     125            rwlock.unlock();
     126
     127        return ret;
     128    }
     129
     130    // only valid for SEEK_SET & SEEK_CUR
     131    long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos;
     132
     133    // Here we perform a normal seek. When successful we
     134    // need to call ResetReadAhead(). A reset means we will
     135    // need to refill the buffer, which takes some time.
     136    if ((SEEK_END == whence) ||
     137        ((SEEK_CUR == whence) && new_pos != 0))
     138    {
     139        errno = EINVAL;
     140        ret = -1;
     141    }
     142    else
     143    {
     144        NormalSeek(new_pos);
     145        ret = new_pos;
     146    }
     147
     148    if (ret >= 0)
     149    {
     150        readpos = ret;
     151       
     152        ignorereadpos = -1;
     153
     154        if (readaheadrunning)
     155            ResetReadAhead(readpos);
     156
     157        readAdjust = 0;
     158    }
     159    else
     160    {
     161        QString cmd = QString("Seek(%1, %2)").arg(pos)
     162            .arg((SEEK_SET == whence) ? "SEEK_SET" :
     163                 ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
     164        VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
     165    }
     166
     167    poslock.unlock();
     168
     169    generalWait.wakeAll();
     170
     171    if (!has_lock)
     172        rwlock.unlock();
     173
     174    return ret;
     175}
     176
     177long long DVDRingBuffer::NormalSeek(long long time)
     178{
    101179    QMutexLocker lock(&m_seekLock);
    102180    return Seek(time);
    103181}
    104182
    105 long long DVDRingBufferPriv::Seek(long long time)
     183long long DVDRingBuffer::Seek(long long time)
    106184{
    107185    dvdnav_status_t dvdRet = DVDNAV_STATUS_OK;
    108186
     
    148226    return m_currentpos;
    149227}
    150228
    151 void DVDRingBufferPriv::GetDescForPos(QString &desc)
     229void DVDRingBuffer::GetDescForPos(QString &desc)
    152230{
    153231    if (m_inMenu)
    154232    {
     
    163241    }
    164242}
    165243
    166 bool DVDRingBufferPriv::OpenFile(const QString &filename)
     244bool DVDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
    167245{
    168     m_dvdFilename = filename;
    169     m_dvdFilename.detach();
    170     QByteArray fname = m_dvdFilename.toLocal8Bit();
     246    rwlock.lockForWrite();
    171247
     248    if (m_dvdnav)
     249    {
     250        dvdnav_close(m_dvdnav);
     251        m_dvdnav = NULL;
     252    }
     253
     254    filename = lfilename;
     255    QByteArray fname = filename.toLocal8Bit();
     256
    172257    dvdnav_status_t res = dvdnav_open(&m_dvdnav, fname.constData());
    173258    if (res == DVDNAV_STATUS_ERR)
    174259    {
    175260        VERBOSE(VB_IMPORTANT, QString("Failed to open DVD device at %1")
    176261                .arg(fname.constData()));
     262        rwlock.unlock();
    177263        return false;
    178264    }
    179     else
    180     {
    181         VERBOSE(VB_IMPORTANT, QString("Opened DVD device at %1")
    182                 .arg(fname.constData()));
    183         dvdnav_set_readahead_flag(m_dvdnav, 0);
    184         dvdnav_set_PGC_positioning_flag(m_dvdnav, 1);
    185265
    186         int32_t num_titles = 0;
    187         int32_t num_parts  = 0;
     266    VERBOSE(VB_IMPORTANT, QString("Opened DVD device at %1")
     267            .arg(fname.constData()));
    188268
     269    dvdnav_set_readahead_flag(m_dvdnav, 0);
     270    dvdnav_set_PGC_positioning_flag(m_dvdnav, 1);
     271
     272    int32_t num_titles = 0;
     273    int32_t num_parts  = 0;
     274
     275    res = dvdnav_get_number_of_titles(m_dvdnav, &num_titles);
     276    if (num_titles == 0 || res == DVDNAV_STATUS_ERR)
     277    {
     278        char buf[DVD_BLOCK_SIZE * 5];
     279        VERBOSE(VB_IMPORTANT, QString("Reading %1 bytes from the drive")
     280                .arg(DVD_BLOCK_SIZE * 5));
     281        safe_read(buf, DVD_BLOCK_SIZE * 5);
    189282        res = dvdnav_get_number_of_titles(m_dvdnav, &num_titles);
    190         if (num_titles == 0 || res == DVDNAV_STATUS_ERR)
    191         {
    192             char buf[DVD_BLOCK_SIZE * 5];
    193             VERBOSE(VB_IMPORTANT, QString("Reading %1 bytes from the drive")
    194                     .arg(DVD_BLOCK_SIZE * 5));
    195             safe_read(buf, DVD_BLOCK_SIZE * 5);
    196             res = dvdnav_get_number_of_titles(m_dvdnav, &num_titles);
    197         }
     283    }
    198284
    199         if (res == DVDNAV_STATUS_ERR)
     285    if (res == DVDNAV_STATUS_ERR)
     286    {
     287        VERBOSE(VB_IMPORTANT,
     288                QString("Failed to get the number of titles on the DVD" ));
     289    }
     290    else
     291    {
     292        VERBOSE(VB_IMPORTANT, QString("There are %1 titles on the disk")
     293                .arg(num_titles));
     294
     295        for (int i = 1; i < num_titles + 1; i++)
    200296        {
    201             VERBOSE(VB_IMPORTANT,
    202                     QString("Failed to get the number of titles on the DVD" ));
    203         }
    204         else
    205         {
    206             VERBOSE(VB_IMPORTANT, QString("There are %1 titles on the disk")
    207                     .arg(num_titles));
    208 
    209             for(int i = 1; i < num_titles + 1; i++)
     297            res = dvdnav_get_number_of_parts(m_dvdnav, i, &num_parts);
     298            if (res != DVDNAV_STATUS_ERR)
    210299            {
    211                 res = dvdnav_get_number_of_parts(m_dvdnav, i, &num_parts);
    212                 if (res != DVDNAV_STATUS_ERR)
    213                 {
    214                     VERBOSE(VB_IMPORTANT, LOC + QString("Title %1 has %2 parts.")
     300                VERBOSE(VB_IMPORTANT, LOC + QString("Title %1 has %2 parts.")
    215301                        .arg(i).arg(num_parts));
    216                 }
    217                 else
    218                 {
    219                     VERBOSE(VB_IMPORTANT, LOC_ERR +
     302            }
     303            else
     304            {
     305                VERBOSE(VB_IMPORTANT, LOC_ERR +
    220306                        QString("Failed to get number of parts for title %1")
    221307                        .arg(i));
    222                 }
    223308            }
    224309        }
     310    }
    225311
    226         dvdnav_title_play(m_dvdnav, 1);
    227         dvdnav_current_title_info(m_dvdnav, &m_title, &m_part);
    228         dvdnav_get_title_string(m_dvdnav, &m_dvdname);
    229         dvdnav_get_serial_string(m_dvdnav, &m_serialnumber);
    230         dvdnav_get_angle_info(m_dvdnav, &m_currentAngle, &m_currentTitleAngleCount);
    231         SetDVDSpeed();
    232         VERBOSE(VB_PLAYBACK, QString("DVD Serial Number %1").arg(m_serialnumber));
    233         return true;
    234     }
     312    dvdnav_title_play(m_dvdnav, 1);
     313    dvdnav_current_title_info(m_dvdnav, &m_title, &m_part);
     314    dvdnav_get_title_string(m_dvdnav, &m_dvdname);
     315    dvdnav_get_serial_string(m_dvdnav, &m_serialnumber);
     316    dvdnav_get_angle_info(m_dvdnav, &m_currentAngle, &m_currentTitleAngleCount);
     317    SetDVDSpeed();
     318
     319    VERBOSE(VB_PLAYBACK, QString("DVD Serial Number %1").arg(m_serialnumber));
     320
     321    readblocksize   = DVD_BLOCK_SIZE * 62;
     322    setswitchtonext = false;
     323    ateof           = false;
     324    commserror      = false;
     325    numfailures     = 0;
     326    rawbitrate      = 8000;
     327
     328    CalcReadAheadThresh();
     329
     330    rwlock.unlock();
     331
     332    return true;
    235333}
    236334
    237 bool DVDRingBufferPriv::StartFromBeginning(void)
     335bool DVDRingBuffer::StartFromBeginning(void)
    238336{
    239337    if (!m_dvdnav)
    240338        return false;
     
    249347                "DVD errored after initial scan - trying again");
    250348        CloseDVD();
    251349        m_gotStop = false;
    252         OpenFile(m_dvdFilename);
     350        OpenFile(filename);
    253351        if (!m_dvdnav)
    254352        {
    255353            VERBOSE(VB_IMPORTANT, LOC + "Failed to re-open DVD.");
     
    266364
    267365/** \brief returns current position in the PGC.
    268366 */
    269 long long DVDRingBufferPriv::GetReadPosition(void)
     367long long DVDRingBuffer::GetReadPosition(void) const
    270368{
    271369    uint32_t pos = 0;
    272370    uint32_t length = 1;
     
    281379    return pos * DVD_BLOCK_SIZE;
    282380}
    283381
    284 void DVDRingBufferPriv::WaitForPlayer(void)
     382void DVDRingBuffer::WaitForPlayer(void)
    285383{
    286384    if (!m_skipstillorwait)
    287385    {
     
    299397    }
    300398}
    301399
    302 int DVDRingBufferPriv::safe_read(void *data, unsigned sz)
     400int DVDRingBuffer::safe_read(void *data, uint sz)
    303401{
    304402    dvdnav_status_t dvdStat;
    305403    unsigned char  *blockBuf     = NULL;
     
    313411    if (m_gotStop)
    314412    {
    315413        VERBOSE(VB_IMPORTANT, LOC + "safe_read: called after DVDNAV_STOP");
     414        errno = EBADF;
    316415        return -1;
    317416    }
    318417
     
    327426        {
    328427            VERBOSE(VB_IMPORTANT, QString("Error reading block from DVD: %1")
    329428                    .arg(dvdnav_err_to_string(m_dvdnav)));
     429            errno = EIO;
    330430            return -1;
    331431        }
    332432
     
    386486
    387487                // debug
    388488                VERBOSE(VB_PLAYBACK, LOC +
    389                     QString("---- DVDNAV_CELL_CHANGE - Cell #%1 Menu %2 Length %3")
     489                    QString("---- DVDNAV_CELL_CHANGE - Cell "
     490                            "#%1 Menu %2 Length %3")
    390491                    .arg(cell_event->cellN).arg(m_inMenu ? "Yes" : "No")
    391492                    .arg((float)cell_event->cell_length / 90000.0f, 0, 'f', 1));
    392493                QString still = m_still ? ((m_still < 0xff) ?
     
    401502                }
    402503                else
    403504                {
    404                     VERBOSE(VB_PLAYBACK, LOC + QString("Title #%1: %2 Part %3 of %4")
     505                    VERBOSE(VB_PLAYBACK, LOC +
     506                            QString("Title #%1: %2 Part %3 of %4")
    405507                        .arg(m_title).arg(still).arg(m_part).arg(m_titleParts));
    406508                }
    407509
    408510                // wait unless it is a transition from one normal video cell to
    409511                // another or the same menu id
    410512                if (((m_still != m_lastStill) || (m_title != m_lastTitle)) &&
    411                     !((m_title == 0 && m_lastTitle == 0) && (m_part == m_lastPart)))
     513                    !((m_title == 0 && m_lastTitle == 0) &&
     514                      (m_part == m_lastPart)))
    412515                {
    413516                    WaitForPlayer();
    414517                }
     
    492595                        QString(LOC + "DVDNAV_SPU_STREAM_CHANGE: "
    493596                                "physicalwide %1, physicalletterbox %2, "
    494597                                "physicalpanscan %3, currenttrack %4")
    495                                 .arg(spu->physical_wide).arg(spu->physical_letterbox)
    496                                 .arg(spu->physical_pan_scan).arg(m_curSubtitleTrack));
     598                        .arg(spu->physical_wide).arg(spu->physical_letterbox)
     599                        .arg(spu->physical_pan_scan).arg(m_curSubtitleTrack));
    497600
    498601                // release buffer
    499602                if (blockBuf != m_dvdBlockWriteBuf)
     
    557660                if (m_seeking)
    558661                {
    559662
    560                     int relativetime = (int)((m_seektime - m_currentTime)/ 90000);
     663                    int relativetime =
     664                        (int)((m_seektime - m_currentTime)/ 90000);
    561665                    if (relativetime <= 1)
    562666                    {
    563667                        m_seeking = false;
     
    737841    return tot;
    738842}
    739843
    740 bool DVDRingBufferPriv::nextTrack(void)
     844bool DVDRingBuffer::nextTrack(void)
    741845{
    742846    int newPart = m_part + 1;
    743847
     
    751855    return false;
    752856}
    753857
    754 void DVDRingBufferPriv::prevTrack(void)
     858void DVDRingBuffer::prevTrack(void)
    755859{
    756860    int newPart = m_part - 1;
    757861
     
    766870/** \brief get the total time of the title in seconds
    767871 * 90000 ticks = 1 sec
    768872 */
    769 uint DVDRingBufferPriv::GetTotalTimeOfTitle(void)
     873uint DVDRingBuffer::GetTotalTimeOfTitle(void)
    770874{
    771875    return m_pgcLength / 90000;
    772876}
    773877
    774878/** \brief get the start of the cell in seconds
    775879 */
    776 uint DVDRingBufferPriv::GetCellStart(void)
     880uint DVDRingBuffer::GetCellStart(void)
    777881{
    778882    return m_cellStart / 90000;
    779883}
    780884
    781885/** \brief check if dvd cell has changed
    782886 */
    783 bool DVDRingBufferPriv::CellChanged(void)
     887bool DVDRingBuffer::CellChanged(void)
    784888{
    785889    bool ret = m_cellChanged;
    786890    m_cellChanged = false;
     
    789893
    790894/** \brief check if pgc length has changed
    791895 */
    792 bool DVDRingBufferPriv::PGCLengthChanged(void)
     896bool DVDRingBuffer::PGCLengthChanged(void)
    793897{
    794898    bool ret = m_pgcLengthChanged;
    795899    m_pgcLengthChanged = false;
    796900    return ret;
    797901}
    798902
    799 void DVDRingBufferPriv::SkipStillFrame(void)
     903void DVDRingBuffer::SkipStillFrame(void)
    800904{
    801905    QMutexLocker locker(&m_seekLock);
    802906    VERBOSE(VB_PLAYBACK, LOC + "Skipping still frame.");
    803907    dvdnav_still_skip(m_dvdnav);
    804908}
    805909
    806 void DVDRingBufferPriv::WaitSkip(void)
     910void DVDRingBuffer::WaitSkip(void)
    807911{
    808912    QMutexLocker locker(&m_seekLock);
    809913    dvdnav_wait_skip(m_dvdnav);
     
    813917
    814918/** \brief jump to a dvd root or chapter menu
    815919 */
    816 bool DVDRingBufferPriv::GoToMenu(const QString str)
     920bool DVDRingBuffer::GoToMenu(const QString str)
    817921{
    818922    DVDMenuID_t menuid;
    819923    QMutexLocker locker(&m_seekLock);
     
    839943    return false;
    840944}
    841945
    842 void DVDRingBufferPriv::GoToNextProgram(void)
     946void DVDRingBuffer::GoToNextProgram(void)
    843947{
    844948    QMutexLocker locker(&m_seekLock);
    845949    if (!dvdnav_is_domain_vts(m_dvdnav))
    846950        dvdnav_next_pg_search(m_dvdnav);
    847951}
    848952
    849 void DVDRingBufferPriv::GoToPreviousProgram(void)
     953void DVDRingBuffer::GoToPreviousProgram(void)
    850954{
    851955    QMutexLocker locker(&m_seekLock);
    852956    if (!dvdnav_is_domain_vts(m_dvdnav))
    853957        dvdnav_prev_pg_search(m_dvdnav);
    854958}
    855959
    856 void DVDRingBufferPriv::MoveButtonLeft(void)
     960void DVDRingBuffer::MoveButtonLeft(void)
    857961{
    858962    if (NumMenuButtons() > 1)
    859963    {
     
    862966    }
    863967}
    864968
    865 void DVDRingBufferPriv::MoveButtonRight(void)
     969void DVDRingBuffer::MoveButtonRight(void)
    866970{
    867971    if (NumMenuButtons() > 1)
    868972    {
     
    871975    }
    872976}
    873977
    874 void DVDRingBufferPriv::MoveButtonUp(void)
     978void DVDRingBuffer::MoveButtonUp(void)
    875979{
    876980    if (NumMenuButtons() > 1)
    877981    {
     
    880984    }
    881985}
    882986
    883 void DVDRingBufferPriv::MoveButtonDown(void)
     987void DVDRingBuffer::MoveButtonDown(void)
    884988{
    885989    if (NumMenuButtons() > 1)
    886990    {
     
    891995
    892996/** \brief action taken when a dvd menu button is selected
    893997 */
    894 void DVDRingBufferPriv::ActivateButton(void)
     998void DVDRingBuffer::ActivateButton(void)
    895999{
    8961000    if (NumMenuButtons() > 0)
    8971001    {
     
    9031007
    9041008/** \brief get SPU pkt from dvd menu subtitle stream
    9051009 */
    906 void DVDRingBufferPriv::GetMenuSPUPkt(uint8_t *buf, int buf_size, int stream_id)
     1010void DVDRingBuffer::GetMenuSPUPkt(uint8_t *buf, int buf_size, int stream_id)
    9071011{
    9081012    if (buf_size < 4)
    9091013        return;
     
    9361040/** \brief returns dvd menu button information if available.
    9371041 * used by NVP::DisplayDVDButton
    9381042 */
    939 AVSubtitle *DVDRingBufferPriv::GetMenuSubtitle(uint &version)
     1043AVSubtitle *DVDRingBuffer::GetMenuSubtitle(uint &version)
    9401044{
    9411045    // this is unlocked by ReleaseMenuButton
    9421046    m_menuBtnLock.lock();
     
    9531057}
    9541058
    9551059
    956 void DVDRingBufferPriv::ReleaseMenuButton(void)
     1060void DVDRingBuffer::ReleaseMenuButton(void)
    9571061{
    9581062    m_menuBtnLock.unlock();
    9591063}
    9601064
    9611065/** \brief get coordinates of highlighted button
    9621066 */
    963 QRect DVDRingBufferPriv::GetButtonCoords(void)
     1067QRect DVDRingBuffer::GetButtonCoords(void)
    9641068{
    9651069    QRect rect(0,0,0,0);
    9661070    if (!m_buttonExists)
     
    9821086/** \brief generate dvd subtitle bitmap or dvd menu bitmap.
    9831087 * code obtained from ffmpeg project
    9841088 */
    985 bool DVDRingBufferPriv::DecodeSubtitles(AVSubtitle *sub, int *gotSubtitles,
     1089bool DVDRingBuffer::DecodeSubtitles(AVSubtitle *sub, int *gotSubtitles,
    9861090                                    const uint8_t *spu_pkt, int buf_size)
    9871091{
    9881092    #define GETBE16(p) (((p)[0] << 8) | (p)[1])
     
    11521256/** \brief update the dvd menu button parameters
    11531257 * when a user changes the dvd menu button position
    11541258 */
    1155 bool DVDRingBufferPriv::DVDButtonUpdate(bool b_mode)
     1259bool DVDRingBuffer::DVDButtonUpdate(bool b_mode)
    11561260{
    11571261    if (!m_parent)
    11581262        return false;
     
    11891293
    11901294/** \brief clears the dvd menu button structures
    11911295 */
    1192 void DVDRingBufferPriv::ClearMenuButton(void)
     1296void DVDRingBuffer::ClearMenuButton(void)
    11931297{
    11941298    if (m_buttonExists || m_dvdMenuButton.rects)
    11951299    {
     
    12101314/** \brief clears the menu SPU pkt and parameters.
    12111315 * necessary action during dvd menu changes
    12121316 */
    1213 void DVDRingBufferPriv::ClearMenuSPUParameters(void)
     1317void DVDRingBuffer::ClearMenuSPUParameters(void)
    12141318{
    12151319    if (m_menuBuflength == 0)
    12161320        return;
     
    12241328    m_hl_button.setRect(0, 0, 0, 0);
    12251329}
    12261330
    1227 int DVDRingBufferPriv::NumMenuButtons(void) const
     1331int DVDRingBuffer::NumMenuButtons(void) const
    12281332{
    12291333    pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
    12301334    int numButtons = pci->hli.hl_gi.btn_ns;
     
    12361340
    12371341/** \brief get the audio language from the dvd
    12381342 */
    1239 uint DVDRingBufferPriv::GetAudioLanguage(int id)
     1343uint DVDRingBuffer::GetAudioLanguage(int id)
    12401344{
    12411345    uint16_t lang = dvdnav_audio_stream_to_lang(m_dvdnav, id);
    12421346    VERBOSE(VB_PLAYBACK, LOC + QString("StreamID: %1; lang: %2").arg(id).arg(lang));
     
    12461350/** \brief get real dvd track audio number
    12471351  * \param key stream_id
    12481352*/
    1249 int DVDRingBufferPriv::GetAudioTrackNum(uint stream_id)
     1353int DVDRingBuffer::GetAudioTrackNum(uint stream_id)
    12501354{
    12511355    return dvdnav_get_audio_logical_stream(m_dvdnav, stream_id);
    12521356}
    12531357
    12541358/** \brief get the subtitle language from the dvd
    12551359 */
    1256 uint DVDRingBufferPriv::GetSubtitleLanguage(int id)
     1360uint DVDRingBuffer::GetSubtitleLanguage(int id)
    12571361{
    12581362    uint16_t lang = dvdnav_spu_stream_to_lang(m_dvdnav, id);
    12591363    VERBOSE(VB_PLAYBACK, LOC + QString("StreamID: %1; lang: %2").arg(id).arg(lang));
     
    12621366
    12631367/** \brief converts the subtitle/audio lang code to iso639.
    12641368 */
    1265 uint DVDRingBufferPriv::ConvertLangCode(uint16_t code)
     1369uint DVDRingBuffer::ConvertLangCode(uint16_t code)
    12661370{
    12671371    if (code == 0)
    12681372        return 0;
     
    12821386/** \brief determines the default dvd menu button to
    12831387 * show when you initially access the dvd menu.
    12841388 */
    1285 void DVDRingBufferPriv::SelectDefaultButton(void)
     1389void DVDRingBuffer::SelectDefaultButton(void)
    12861390{
    12871391    pci_t *pci = dvdnav_get_current_nav_pci(m_dvdnav);
    12881392    int32_t button = pci->hli.hl_gi.fosl_btnn;
     
    13021406 *  \param type    currently kTrackTypeSubtitle or kTrackTypeAudio
    13031407 *  \param trackNo if -1 then autoselect the track num from the dvd IFO
    13041408 */
    1305 void DVDRingBufferPriv::SetTrack(uint type, int trackNo)
     1409void DVDRingBuffer::SetTrack(uint type, int trackNo)
    13061410{
    13071411    if (type == kTrackTypeSubtitle)
    13081412    {
     
    13201424}
    13211425
    13221426/** \brief get the track the dvd should be playing.
    1323  * can either be set by the user using DVDRingBufferPriv::SetTrack
     1427 * can either be set by the user using DVDRingBuffer::SetTrack
    13241428 * or determined from the dvd IFO.
    13251429 * \param type: use either kTrackTypeSubtitle or kTrackTypeAudio
    13261430 */
    1327 int DVDRingBufferPriv::GetTrack(uint type)
     1431int DVDRingBuffer::GetTrack(uint type)
    13281432{
    13291433    if (type == kTrackTypeSubtitle)
    13301434        return m_curSubtitleTrack;
     
    13341438    return 0;
    13351439}
    13361440
    1337 uint8_t DVDRingBufferPriv::GetNumAudioChannels(int id)
     1441uint8_t DVDRingBuffer::GetNumAudioChannels(int id)
    13381442{
    13391443    unsigned char channels = dvdnav_audio_stream_channels(m_dvdnav, id);
    13401444    if (channels == 0xff)
     
    13441448
    13451449/** \brief Get the dvd title and serial num
    13461450 */
    1347 bool DVDRingBufferPriv::GetNameAndSerialNum(QString& _name, QString& _serial)
     1451bool DVDRingBuffer::GetNameAndSerialNum(QString& _name, QString& _serial)
    13481452{
    13491453    _name    = QString(m_dvdname);
    13501454    _serial    = QString(m_serialnumber);
     
    13581462 * FPS for a dvd is determined by AFD::normalized_fps
    13591463 * * dvdnav_get_video_format: 0 - NTSC, 1 - PAL
    13601464 */
    1361 double DVDRingBufferPriv::GetFrameRate(void)
     1465double DVDRingBuffer::GetFrameRate(void)
    13621466{
    13631467    double dvdfps = 0;
    13641468    int format = dvdnav_get_video_format(m_dvdnav);
     
    13711475/** \brief set dvd speed. uses the DVDDriveSpeed Setting from the settings
    13721476 *  table
    13731477 */
    1374 void DVDRingBufferPriv::SetDVDSpeed(void)
     1478void DVDRingBuffer::SetDVDSpeed(void)
    13751479{
    13761480    QMutexLocker lock(&m_seekLock);
    13771481    int dvdDriveSpeed = gCoreContext->GetNumSetting("DVDDriveSpeed", 12);
     
    13801484
    13811485/** \brief set dvd speed.
    13821486 */
    1383 void DVDRingBufferPriv::SetDVDSpeed(int speed)
     1487void DVDRingBuffer::SetDVDSpeed(int speed)
    13841488{
    1385     if (m_dvdFilename.startsWith("/"))
    1386         MediaMonitor::SetCDSpeed(m_dvdFilename.toLocal8Bit().constData(), speed);
     1489    if (filename.startsWith("/"))
     1490        MediaMonitor::SetCDSpeed(filename.toLocal8Bit().constData(), speed);
    13871491}
    13881492
    13891493/**\brief returns seconds left in the title
    13901494 */
    1391 uint DVDRingBufferPriv::TitleTimeLeft(void)
     1495uint DVDRingBuffer::TitleTimeLeft(void)
    13921496{
    13931497    return (GetTotalTimeOfTitle() - GetCurrentTime());
    13941498}
    13951499
    13961500/** \brief converts palette values from YUV to RGB
    13971501 */
    1398 void DVDRingBufferPriv::guess_palette(uint32_t *rgba_palette,uint8_t *palette,
     1502void DVDRingBuffer::guess_palette(uint32_t *rgba_palette,uint8_t *palette,
    13991503                                        uint8_t *alpha)
    14001504{
    14011505    int i,r,g,b,y,cr,cb;
     
    14251529/** \brief decodes the bitmap from the subtitle packet.
    14261530 *         copied from ffmpeg's dvdsubdec.c.
    14271531 */
    1428 int DVDRingBufferPriv::decode_rle(uint8_t *bitmap, int linesize, int w, int h,
     1532int DVDRingBuffer::decode_rle(uint8_t *bitmap, int linesize, int w, int h,
    14291533                                  const uint8_t *buf, int nibble_offset, int buf_size)
    14301534{
    14311535    unsigned int v;
     
    14721576
    14731577/** copied from ffmpeg's dvdsubdec.c
    14741578 */
    1475 int DVDRingBufferPriv::get_nibble(const uint8_t *buf, int nibble_offset)
     1579int DVDRingBuffer::get_nibble(const uint8_t *buf, int nibble_offset)
    14761580{
    14771581    return (buf[nibble_offset >> 1] >> ((1 - (nibble_offset & 1)) << 2)) & 0xf;
    14781582}
     
    14811585 * \brief obtained from ffmpeg dvdsubdec.c
    14821586 * used to find smallest bounded rectangle
    14831587 */
    1484 int DVDRingBufferPriv::is_transp(const uint8_t *buf, int pitch, int n,
     1588int DVDRingBuffer::is_transp(const uint8_t *buf, int pitch, int n,
    14851589                     const uint8_t *transp_color)
    14861590{
    14871591    int i;
     
    14991603 * used to find smallest bounded rect.
    15001604 * helps prevent jerky picture during subtitle creation
    15011605 */
    1502 int DVDRingBufferPriv::find_smallest_bounding_rectangle(AVSubtitle *s)
     1606int DVDRingBuffer::find_smallest_bounding_rectangle(AVSubtitle *s)
    15031607{
    15041608    uint8_t transp_color[256];
    15051609    int y1, y2, x1, x2, y, w, h, i;
     
    15791683    return 1;
    15801684}
    15811685
    1582 bool DVDRingBufferPriv::SwitchAngle(uint angle)
     1686bool DVDRingBuffer::SwitchAngle(uint angle)
    15831687{
    15841688    if (!m_dvdnav)
    15851689        return false;
     
    15951699    return false;
    15961700}
    15971701
    1598 bool DVDRingBufferPriv::NewSequence(bool new_sequence)
     1702bool DVDRingBuffer::NewSequence(bool new_sequence)
    15991703{
    16001704    bool result = false;
    16011705    if (new_sequence)
  • libs/libmythtv/libmythtv.pro

     
    141141
    142142# Misc. needed by backend/frontend
    143143HEADERS += recordinginfo.h
    144 HEADERS += RingBuffer.h             avfringbuffer.h
    145 HEADERS += ThreadedFileWriter.h
    146144HEADERS += dbcheck.h
    147145HEADERS += tvremoteutil.h           tv.h
    148146HEADERS += jobqueue.h
     
    163161HEADERS += channelgroup.h           channelgroupsettings.h
    164162HEADERS += recordingrule.h          programdetail.h
    165163HEADERS += mythsystemevent.h
     164HEADERS += avfringbuffer.h          ThreadedFileWriter.h
     165HEADERS += RingBuffer.h             FileRingBuffer.h
     166HEADERS += DVDRingBuffer.h          BDRingBuffer.h
    166167
    167168SOURCES += recordinginfo.cpp
    168 SOURCES += RingBuffer.cpp           avfringbuffer.cpp
    169 SOURCES += ThreadedFileWriter.cpp
    170169SOURCES += dbcheck.cpp
    171170SOURCES += tvremoteutil.cpp         tv.cpp
    172171SOURCES += jobqueue.cpp
     
    187186SOURCES += myth_imgconvert.cpp
    188187SOURCES += recordingrule.cpp        programdetail.cpp
    189188SOURCES += mythsystemevent.cpp
     189SOURCES += avfringbuffer.cpp        ThreadedFileWriter.cpp
     190SOURCES += RingBuffer.cpp           FileRingBuffer.cpp
     191SOURCES += DVDRingBuffer.cpp        BDRingBuffer.cpp
    190192
    191193# DiSEqC
    192194HEADERS += diseqc.h                 diseqcsettings.h
     
    251253    # Video playback
    252254    HEADERS += tv_play.h                mythplayer.h
    253255    HEADERS += mythdvdplayer.h          audioplayer.h
    254     HEADERS += DVDRingBuffer.h          playercontext.h
     256    HEADERS += playercontext.h
    255257    HEADERS += tv_play_win.h            deletemap.h
    256258    HEADERS += mythcommflagplayer.h     commbreakmap.h
    257     HEADERS += BDRingBuffer.h           mythbdplayer.h
     259    HEADERS += mythbdplayer.h
    258260    HEADERS += mythiowrapper.h          tvbrowsehelper.h
    259261    SOURCES += tv_play.cpp              mythplayer.cpp
    260262    SOURCES += mythdvdplayer.cpp        audioplayer.cpp
    261     SOURCES += DVDRingBuffer.cpp        playercontext.cpp
     263    SOURCES += playercontext.cpp
    262264    SOURCES += tv_play_win.cpp          deletemap.cpp
    263265    SOURCES += mythcommflagplayer.cpp   commbreakmap.cpp
    264     SOURCES += BDRingBuffer.cpp         mythbdplayer.cpp
     266    SOURCES += mythbdplayer.cpp
    265267    SOURCES += mythiowrapper.cpp        tvbrowsehelper.cpp
    266268
    267269    # Text subtitle parser
  • libs/libmythtv/tv_play.h

     
    617617    // DVD methods
    618618    void DVDJumpBack(PlayerContext*);
    619619    void DVDJumpForward(PlayerContext*);
    620     bool DiscMenuHandleAction(PlayerContext*,
    621                              const QStringList &actions,
    622                              bool isDVD, bool isDVDStill,
    623                              bool isBD = false);
     620    bool DiscMenuHandleAction(PlayerContext*, const QStringList &actions);
    624621
    625622    // Program jumping stuff
    626623    void SetLastProgram(const ProgramInfo *rcinfo);
  • libs/libmythtv/BDRingBuffer.cpp

     
    1515#include "mythdirs.h"
    1616#include "bluray.h"
    1717
    18 #define LOC     QString("BDRingBuffer: ")
     18#define LOC      QString("BDRingBuf(%1): ").arg(GetFilename())
     19#define LOC_WARN QString("BDRingBuf(%1) Warning: ").arg(GetFilename())
     20#define LOC_ERR  QString("BDRingBuf(%1) Error: ").arg(GetFilename())
    1921
    20 static void HandleOverlayCallback(void *data, const bd_overlay_s * const overlay)
     22static void HandleOverlayCallback(
     23    void *data, const bd_overlay_s * const overlay)
    2124{
    22     BDRingBufferPriv *bdpriv = (BDRingBufferPriv*) data;
     25    BDRingBuffer *bdrb = (BDRingBuffer*) data;
    2326
    24     if (!bdpriv)
     27    if (!bdrb)
    2528        return;
    2629
    2730    if (!overlay || overlay->plane == 1)
    28         bdpriv->m_inMenu = false;
     31        bdrb->m_inMenu = false;
    2932
    3033    if (!overlay || !overlay->img)
    3134        return;
    3235
    33     bdpriv->m_inMenu = true;
     36    bdrb->m_inMenu = true;
    3437
    3538    const BD_PG_RLE_ELEM *rlep = overlay->img;
    3639    uint8_t *yuvimg = (uint8_t*)malloc(overlay->w * overlay->h);
    3740    unsigned pixels = overlay->w * overlay->h;
    3841
     42
    3943    for (unsigned i = 0; i < pixels; i += rlep->len, rlep++)
    4044    {
    4145        memset(yuvimg + i, rlep->color, rlep->len);
     
    4953        palette.push_back(origpalette[i]);
    5054
    5155    qoverlay.setColorTable(palette);
    52     qoverlay.save(QString("bluray.menuimg.%1.%2.png").arg(overlay->w).arg(overlay->h));
     56    qoverlay.save(QString("bluray.menuimg.%1.%2.png")
     57                  .arg(overlay->w).arg(overlay->h));
    5358
    54     VERBOSE(VB_PLAYBACK|VB_EXTRA, LOC + QString("In Menu Callback, ready to draw "
    55                         "an overlay of %1x%2 at %3,%4 (%5 pixels).")
    56                         .arg(overlay->w).arg(overlay->h).arg(overlay->x)
    57                         .arg(overlay->y).arg(pixels));
     59    VERBOSE(VB_PLAYBACK|VB_EXTRA,
     60            QString("BDRingBuf(%1): ").arg(bdrb->GetFilename()) +
     61            QString("In Menu Callback, ready to draw "
     62                    "an overlay of %1x%2 at %3,%4 (%5 pixels).")
     63            .arg(overlay->w).arg(overlay->h).arg(overlay->x)
     64            .arg(overlay->y).arg(pixels));
    5865}
    5966
    60 BDRingBufferPriv::BDRingBufferPriv()
    61     : bdnav(NULL),
    62       m_is_hdmv_navigation(false),
    63       m_numTitles(0)
     67BDRingBuffer::BDRingBuffer(const QString &lfilename) :
     68    bdnav(NULL),
     69    m_is_hdmv_navigation(false), m_numTitles(0)
    6470{
     71    OpenFile(lfilename);
    6572}
    6673
    67 BDRingBufferPriv::~BDRingBufferPriv()
     74BDRingBuffer::~BDRingBuffer()
    6875{
    6976    close();
    7077}
    7178
    72 void BDRingBufferPriv::close(void)
     79void BDRingBuffer::close(void)
    7380{
    7481    if (bdnav)
    7582    {
     
    8087    }
    8188}
    8289
    83 uint64_t BDRingBufferPriv::Seek(uint64_t pos)
     90long long BDRingBuffer::Seek(long long pos, int whence, bool has_lock)
    8491{
     92    VERBOSE(VB_FILE, LOC + QString("Seek(%1,%2,%3)")
     93            .arg(pos).arg((SEEK_SET==whence)?"SEEK_SET":
     94                          ((SEEK_CUR==whence)?"SEEK_CUR":"SEEK_END"))
     95            .arg(has_lock?"locked":"unlocked"));
     96
     97    long long ret = -1;
     98
     99    // lockForWrite takes priority over lockForRead, so this will
     100    // take priority over the lockForRead in the read ahead thread.
     101    if (!has_lock)
     102        rwlock.lockForWrite();
     103
     104    poslock.lockForWrite();
     105
     106    // Optimize no-op seeks
     107    if (readaheadrunning &&
     108        ((whence == SEEK_SET && pos == readpos) ||
     109         (whence == SEEK_CUR && pos == 0)))
     110    {
     111        ret = readpos;
     112
     113        poslock.unlock();
     114        if (!has_lock)
     115            rwlock.unlock();
     116
     117        return ret;
     118    }
     119
     120    // only valid for SEEK_SET & SEEK_CUR
     121    long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos;
     122
     123    // Here we perform a normal seek. When successful we
     124    // need to call ResetReadAhead(). A reset means we will
     125    // need to refill the buffer, which takes some time.
     126    if ((SEEK_END == whence) ||
     127        ((SEEK_CUR == whence) && new_pos != 0))
     128    {
     129        errno = EINVAL;
     130        ret = -1;
     131    }
     132    else
     133    {
     134        Seek(new_pos);
     135        ret = new_pos;
     136    }
     137
     138    if (ret >= 0)
     139    {
     140        readpos = ret;
     141       
     142        ignorereadpos = -1;
     143
     144        if (readaheadrunning)
     145            ResetReadAhead(readpos);
     146
     147        readAdjust = 0;
     148    }
     149    else
     150    {
     151        QString cmd = QString("Seek(%1, %2)").arg(pos)
     152            .arg((SEEK_SET == whence) ? "SEEK_SET" :
     153                 ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
     154        VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
     155    }
     156
     157    poslock.unlock();
     158
     159    generalWait.wakeAll();
     160
     161    if (!has_lock)
     162        rwlock.unlock();
     163
     164    return ret;
     165}
     166
     167uint64_t BDRingBuffer::Seek(uint64_t pos)
     168{
    85169    VERBOSE(VB_PLAYBACK|VB_EXTRA, LOC + QString("Seeking to %1.")
    86170                .arg(pos));
    87171    if (!m_is_hdmv_navigation)
     
    90174    return GetReadPosition();
    91175}
    92176
    93 void BDRingBufferPriv::GetDescForPos(QString &desc) const
     177void BDRingBuffer::GetDescForPos(QString &desc) const
    94178{
    95179    desc = QObject::tr("Title %1 chapter %2")
    96180                       .arg(m_currentTitleInfo->idx)
    97181                       .arg(m_currentTitleInfo->chapters->idx);
    98182}
    99183
    100 bool BDRingBufferPriv::OpenFile(const QString &filename)
     184bool BDRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
    101185{
    102186    VERBOSE(VB_IMPORTANT, LOC + QString("Opened BDRingBuffer device at %1")
    103             .arg(filename.toLatin1().data()));
     187            .arg(lfilename.toLatin1().data()));
    104188
     189    rwlock.lockForWrite();
     190
     191    if (bdnav)
     192    {
     193        if (m_currentTitleInfo)
     194            bd_free_title_info(m_currentTitleInfo);
     195        bd_close(bdnav);
     196        bdnav = NULL;
     197    }
     198
     199    filename = lfilename;
     200
    105201    QString keyfile = QString("%1/KEYDB.cfg").arg(GetConfDir());
    106202    QByteArray keyarray = keyfile.toAscii();
    107203    const char *keyfilepath = keyarray.data();
    108204
    109     bdnav = bd_open(filename.toLatin1().data(), keyfilepath);
     205    bdnav = bd_open(lfilename.toLatin1().data(), keyfilepath);
    110206
    111207    if (!bdnav)
     208    {
     209        rwlock.unlock();
    112210        return false;
     211    }
    113212
    114213    // Check disc to see encryption status, menu and navigation types.
    115214    const BLURAY_DISC_INFO *discinfo = bd_get_disc_info(bdnav);
    116215    if (discinfo)
    117         VERBOSE(VB_PLAYBACK, QString("*** Blu-ray Disc Information ***\n"
    118                                   "First Play Supported: %1\n"
    119                                   "Top Menu Supported: %2\n"
    120                                   "Number of HDMV Titles: %3\n"
    121                                   "Number of BD-J Titles: %4\n"
    122                                   "Number of Unsupported Titles: %5\n"
    123                                   "AACS present on disc: %6\n"
    124                                   "libaacs used: %7\n"
    125                                   "AACS handled: %8\n"
    126                                   "BD+ present on disc: %9\n"
    127                                   "libbdplus used: %10\n"
    128                                   "BD+ handled: %11")
    129                                   .arg(discinfo->first_play_supported ? "yes" : "no")
    130                                   .arg(discinfo->top_menu_supported ? "yes" : "no")
    131                                   .arg(discinfo->num_hdmv_titles)
    132                                   .arg(discinfo->num_bdj_titles)
    133                                   .arg(discinfo->num_unsupported_titles)
    134                                   .arg(discinfo->aacs_detected ? "yes" : "no")
    135                                   .arg(discinfo->libaacs_detected ? "yes" : "no")
    136                                   .arg(discinfo->aacs_handled ? "yes" : "no")
    137                                   .arg(discinfo->bdplus_detected ? "yes" : "no")
    138                                   .arg(discinfo->libbdplus_detected ? "yes" : "no")
    139                                   .arg(discinfo->bdplus_handled ? "yes" : "no"));
     216    {
     217        VERBOSE(VB_PLAYBACK, QString(
     218                    "*** Blu-ray Disc Information ***\n"
     219                    "First Play Supported: %1\n"
     220                    "Top Menu Supported: %2\n"
     221                    "Number of HDMV Titles: %3\n"
     222                    "Number of BD-J Titles: %4\n"
     223                    "Number of Unsupported Titles: %5\n"
     224                    "AACS present on disc: %6\n"
     225                    "libaacs used: %7\n"
     226                    "AACS handled: %8\n"
     227                    "BD+ present on disc: %9\n"
     228                    "libbdplus used: %10\n"
     229                    "BD+ handled: %11")
     230                .arg(discinfo->first_play_supported ? "yes" : "no")
     231                .arg(discinfo->top_menu_supported ? "yes" : "no")
     232                .arg(discinfo->num_hdmv_titles)
     233                .arg(discinfo->num_bdj_titles)
     234                .arg(discinfo->num_unsupported_titles)
     235                .arg(discinfo->aacs_detected ? "yes" : "no")
     236                .arg(discinfo->libaacs_detected ? "yes" : "no")
     237                .arg(discinfo->aacs_handled ? "yes" : "no")
     238                .arg(discinfo->bdplus_detected ? "yes" : "no")
     239                .arg(discinfo->libbdplus_detected ? "yes" : "no")
     240                .arg(discinfo->bdplus_handled ? "yes" : "no"));
     241    }
    140242
    141     // The following settings affect HDMV navigation (default audio track selection,
     243    // The following settings affect HDMV navigation
     244    // (default audio track selection,
    142245    // parental controls, menu language, etc.  They are not yet used.
    143246
    144247    // Set parental level "age" to 99 for now.  TODO: Add support for FE level
    145248    bd_set_player_setting(bdnav, BLURAY_PLAYER_SETTING_PARENTAL, 99);
    146249
    147250    // Set preferred language to FE guide language
    148     const char *langpref = gCoreContext->GetSetting("ISO639Language0", "eng").toLatin1().data();
     251    const char *langpref = gCoreContext->GetSetting(
     252        "ISO639Language0", "eng").toLatin1().data();
    149253    QString QScountry  = gCoreContext->GetLocale()->GetCountryCode().toLower();
    150254    const char *country = QScountry.toLatin1().data();
    151     bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);
     255    bd_set_player_setting_str(
     256        bdnav, BLURAY_PLAYER_SETTING_AUDIO_LANG, langpref);
    152257
    153258    // Set preferred presentation graphics language to the FE guide language
    154259    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_PG_LANG, langpref);
     
    157262    bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_MENU_LANG, langpref);
    158263
    159264    // Set player country code via MythLocale. (not a region setting)
    160     bd_set_player_setting_str(bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);
     265    bd_set_player_setting_str(
     266        bdnav, BLURAY_PLAYER_SETTING_COUNTRY_CODE, country);
    161267
    162268    VERBOSE(VB_IMPORTANT, LOC + QString("Using %1 as keyfile...")
    163269            .arg(QString(keyfilepath)));
     
    227333    }
    228334#endif
    229335
     336    readblocksize   = BD_BLOCK_SIZE * 62;
     337    setswitchtonext = false;
     338    ateof           = false;
     339    commserror      = false;
     340    numfailures     = 0;
     341    rawbitrate      = 8000;
     342    CalcReadAheadThresh();
     343
     344    rwlock.unlock();
     345
    230346    return true;
    231347}
    232348
    233 uint64_t BDRingBufferPriv::GetReadPosition(void)
     349long long BDRingBuffer::GetReadPosition(void) const
    234350{
    235351    if (bdnav)
    236352        return bd_tell(bdnav);
    237353    return 0;
    238354}
    239355
    240 uint32_t BDRingBufferPriv::GetNumChapters(void)
     356uint32_t BDRingBuffer::GetNumChapters(void)
    241357{
    242358    if (m_currentTitleInfo)
    243359        return m_currentTitleInfo->chapter_count;
    244360    return 0;
    245361}
    246362
    247 uint64_t BDRingBufferPriv::GetChapterStartTime(uint32_t chapter)
     363uint64_t BDRingBuffer::GetChapterStartTime(uint32_t chapter)
    248364{
    249365    if (chapter < 0 || chapter >= GetNumChapters())
    250366        return 0;
     
    252368                                   90000.0f);
    253369}
    254370
    255 uint64_t BDRingBufferPriv::GetChapterStartFrame(uint32_t chapter)
     371uint64_t BDRingBuffer::GetChapterStartFrame(uint32_t chapter)
    256372{
    257373    if (chapter < 0 || chapter >= GetNumChapters())
    258374        return 0;
     
    260376                                    GetFrameRate()) / 90000.0f);
    261377}
    262378
    263 int BDRingBufferPriv::GetCurrentTitle(void) const
     379int BDRingBuffer::GetCurrentTitle(void) const
    264380{
    265381    if (m_currentTitleInfo)
    266382        return m_currentTitleInfo->idx;
    267383    return -1;
    268384}
    269385
    270 int BDRingBufferPriv::GetTitleDuration(int title) const
     386int BDRingBuffer::GetTitleDuration(int title) const
    271387{
    272388    int numTitles = GetNumTitles();
    273389
     
    283399    return duration;
    284400}
    285401
    286 bool BDRingBufferPriv::SwitchTitle(uint title)
     402bool BDRingBuffer::SwitchTitle(uint title)
    287403{
    288404    if (!bdnav)
    289405        return false;
     
    333449    return true;
    334450}
    335451
    336 bool BDRingBufferPriv::SwitchAngle(uint angle)
     452bool BDRingBuffer::SwitchAngle(uint angle)
    337453{
    338454    if (!bdnav)
    339455        return false;
     
    344460    return true;
    345461}
    346462
    347 uint64_t BDRingBufferPriv::GetTotalReadPosition(void)
     463uint64_t BDRingBuffer::GetTotalReadPosition(void)
    348464{
    349465    if (bdnav)
    350466        return bd_get_title_size(bdnav);
    351467    return 0;
    352468}
    353469
    354 int BDRingBufferPriv::safe_read(void *data, unsigned sz)
     470int BDRingBuffer::safe_read(void *data, uint sz)
    355471{
    356472    if (m_is_hdmv_navigation)
    357473    {
     
    368484    return sz;
    369485}
    370486
    371 double BDRingBufferPriv::GetFrameRate(void)
     487double BDRingBuffer::GetFrameRate(void)
    372488{
    373489    if (bdnav && m_currentTitleInfo)
    374490    {
     
    401517    return 0;
    402518}
    403519
    404 int BDRingBufferPriv::GetAudioLanguage(uint streamID)
     520int BDRingBuffer::GetAudioLanguage(uint streamID)
    405521{
    406522    if (!m_currentTitleInfo ||
    407523        streamID >= m_currentTitleInfo->clips->audio_stream_count)
     
    416532    return code;
    417533}
    418534
    419 int BDRingBufferPriv::GetSubtitleLanguage(uint streamID)
     535int BDRingBuffer::GetSubtitleLanguage(uint streamID)
    420536{
    421537    if (!m_currentTitleInfo)
    422538        return iso639_str3_to_key("und");
     
    442558    return iso639_str3_to_key("und");
    443559}
    444560
    445 void BDRingBufferPriv::PressButton(int32_t key, int64_t pts)
     561void BDRingBuffer::PressButton(int32_t key, int64_t pts)
    446562{
    447563    if (!bdnav)
    448564        return;
     
    463579
    464580/** \brief jump to a Blu-ray root or popup menu
    465581 */
    466 bool BDRingBufferPriv::GoToMenu(const QString str)
     582bool BDRingBuffer::GoToMenu(const QString str)
    467583{
    468584    if (!m_is_hdmv_navigation)
    469585        return false;
     
    489605    return false;
    490606}
    491607
    492 bool BDRingBufferPriv::HandleBDEvents()
     608bool BDRingBuffer::HandleBDEvents(void)
    493609{
    494610    BD_EVENT ev;
    495611    while (bd_get_event(bdnav, &ev))
     
    504620    return true;
    505621}
    506622
    507 void BDRingBufferPriv::HandleBDEvent(BD_EVENT &ev)
     623void BDRingBuffer::HandleBDEvent(BD_EVENT &ev)
    508624{
    509625    switch (ev.event) {
    510626        case BD_EVENT_NONE:
  • libs/libmythtv/FileRingBuffer.cpp

     
     1#include <cstdlib>
     2#include <cerrno>
     3
     4// POSIX C headers
     5#include <sys/types.h>
     6#include <sys/time.h>
     7#include <unistd.h>
     8#include <fcntl.h>
     9
     10#include <QFileInfo>
     11#include <QDir>
     12
     13#include "ThreadedFileWriter.h"
     14#include "FileRingBuffer.h"
     15#include "mythcontext.h"
     16#include "remotefile.h"
     17#include "util.h"
     18
     19#ifndef O_STREAMING
     20#define O_STREAMING 0
     21#endif
     22
     23#ifndef O_LARGEFILE
     24#define O_LARGEFILE 0
     25#endif
     26
     27#ifndef O_BINARY
     28#define O_BINARY 0
     29#endif
     30
     31#define LOC      QString("FileRingBuf(%1): ").arg(filename)
     32#define LOC_WARN QString("FileRingBuf(%1) Warning: ").arg(filename)
     33#define LOC_ERR  QString("FileRingBuf(%1) Error: ").arg(filename)
     34
     35FileRingBuffer::FileRingBuffer(const QString &lfilename,
     36                               bool write, bool readahead, int timeout_ms)
     37{
     38    startreadahead = readahead;
     39
     40    if (write)
     41    {
     42        filename = lfilename;
     43        if (filename.startsWith("myth://"))
     44        {
     45            remotefile = new RemoteFile(filename, true);
     46            if (!remotefile->isOpen())
     47            {
     48                VERBOSE(VB_IMPORTANT,
     49                        QString("RingBuffer::RingBuffer(): Failed to open "
     50                                "remote file (%1) for write").arg(filename));
     51                delete remotefile;
     52                remotefile = NULL;
     53            }
     54            else
     55                writemode = true;
     56        }
     57        else
     58        {
     59            tfw = new ThreadedFileWriter(
     60                filename, O_WRONLY|O_TRUNC|O_CREAT|O_LARGEFILE, 0644);
     61
     62            if (!tfw->Open())
     63            {
     64                delete tfw;
     65                tfw = NULL;
     66            }
     67            else
     68                writemode = true;
     69        }
     70    }
     71    else if (timeout_ms >= 0)
     72    {
     73        OpenFile(filename, timeout_ms);
     74    }
     75}
     76
     77FileRingBuffer::~FileRingBuffer()
     78{
     79    rwlock.lockForWrite();
     80
     81    if (remotefile)
     82    {
     83        delete remotefile;
     84        remotefile = NULL;
     85    }
     86
     87    if (tfw)
     88    {
     89        delete tfw;
     90        tfw = NULL;
     91    }
     92
     93    if (fd2 >= 0)
     94    {
     95        close(fd2);
     96        fd2 = -1;
     97    }
     98
     99    rwlock.unlock();
     100}
     101
     102/** \fn check_permissions(const QString&)
     103 *  \brief Returns false iff file exists and has incorrect permissions.
     104 *  \param filename File (including path) that we want to know about
     105 */
     106static bool check_permissions(const QString &filename)
     107{
     108    QFileInfo fileInfo(filename);
     109    if (fileInfo.exists() && !fileInfo.isReadable())
     110    {
     111        VERBOSE(VB_IMPORTANT, LOC_ERR +
     112                "File exists but is not readable by MythTV!");
     113        return false;
     114    }
     115    return true;
     116}
     117
     118static bool is_subtitle_possible(const QString &extension)
     119{
     120    QMutexLocker locker(&RingBuffer::subExtLock);
     121    bool no_subtitle = false;
     122    for (uint i = 0; i < (uint)RingBuffer::subExtNoCheck.size(); i++)
     123    {
     124        if (extension.contains(RingBuffer::subExtNoCheck[i].right(3)))
     125        {
     126            no_subtitle = true;
     127            break;
     128        }
     129    }
     130    return !no_subtitle;
     131}
     132
     133static QString local_sub_filename(QFileInfo &fileInfo)
     134{
     135    // Subtitle handling
     136    QString vidFileName = fileInfo.fileName();
     137    QString dirName = fileInfo.absolutePath();
     138
     139    QString baseName = vidFileName;
     140    int suffixPos = vidFileName.lastIndexOf(QChar('.'));
     141    if (suffixPos > 0)
     142        baseName = vidFileName.left(suffixPos);
     143
     144    QStringList el;
     145    {
     146        // The dir listing does not work if the filename has the
     147        // following chars "[]()" so we convert them to the wildcard '?'
     148        const QString findBaseName = baseName
     149            .replace("[", "?")
     150            .replace("]", "?")
     151            .replace("(", "?")
     152            .replace(")", "?");
     153
     154        QMutexLocker locker(&RingBuffer::subExtLock);
     155        QStringList::const_iterator eit = RingBuffer::subExt.begin();
     156        for (; eit != RingBuffer::subExt.end(); eit++)
     157            el += findBaseName + *eit;
     158    }
     159
     160    // Some Qt versions do not accept paths in the search string of
     161    // entryList() so we have to set the dir first
     162    QDir dir;
     163    dir.setPath(dirName);
     164
     165    const QStringList candidates = dir.entryList(el);
     166
     167    QStringList::const_iterator cit = candidates.begin();
     168    for (; cit != candidates.end(); ++cit)
     169    {
     170        QFileInfo fi(dirName + "/" + *cit);
     171        if (fi.exists() && (fi.size() >= RingBuffer::kReadTestSize))
     172            return fi.absoluteFilePath();
     173    }
     174
     175    return QString::null;
     176}
     177
     178bool FileRingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
     179{
     180    VERBOSE(VB_PLAYBACK, LOC + QString("OpenFile(%1, %2 ms)")
     181            .arg(lfilename).arg(retry_ms));
     182
     183    rwlock.lockForWrite();
     184
     185    filename = lfilename;
     186
     187    if (remotefile)
     188    {
     189        delete remotefile;
     190        remotefile = NULL;
     191    }
     192
     193    if (fd2 >= 0)
     194    {
     195        close(fd2);
     196        fd2 = -1;
     197    }
     198
     199    bool is_local =
     200        (filename.left(4) != "/dev") &&
     201        ((filename.left(1) == "/") || QFile::exists(filename));
     202
     203    if (is_local)
     204    {
     205        char buf[kReadTestSize];
     206        int lasterror = 0;
     207
     208        MythTimer openTimer;
     209        openTimer.start();
     210
     211        uint openAttempts = 0;
     212        do
     213        {
     214            openAttempts++;
     215            lasterror = 0;
     216
     217            fd2 = open(filename.toLocal8Bit().constData(),
     218                       O_RDONLY|O_LARGEFILE|O_STREAMING|O_BINARY);
     219
     220            if (fd2 < 0)
     221            {
     222                if (!check_permissions(filename))
     223                {
     224                    lasterror = 3;
     225                    break;
     226                }
     227
     228                lasterror = 1;
     229                usleep(10 * 1000);
     230            }
     231            else
     232            {
     233                int ret = read(fd2, buf, kReadTestSize);
     234                if (ret != (int)kReadTestSize)
     235                {
     236                    lasterror = 2;
     237                    close(fd2);
     238                    fd2 = -1;
     239                    if (oldfile)
     240                        break; // if it's an old file it won't grow..
     241                    usleep(10 * 1000);
     242                }
     243                else
     244                {
     245                    if (0 == lseek(fd2, 0, SEEK_SET))
     246                    {
     247                        posix_fadvise(fd2, 0, 0, POSIX_FADV_SEQUENTIAL);
     248                        posix_fadvise(fd2, 0, 1*1024*1024, POSIX_FADV_WILLNEED);
     249                        lasterror = 0;
     250                        break;
     251                    }
     252                    lasterror = 4;
     253                    close(fd2);
     254                    fd2 = -1;
     255                }
     256            }
     257        }
     258        while ((uint)openTimer.elapsed() < retry_ms);
     259
     260        switch (lasterror)
     261        {
     262            case 0:
     263            {
     264                QFileInfo fi(filename);
     265                oldfile = fi.lastModified()
     266                    .secsTo(QDateTime::currentDateTime()) > 60;
     267                QString extension = fi.completeSuffix().toLower();
     268                if (is_subtitle_possible(extension))
     269                    subtitlefilename = local_sub_filename(fi);
     270                break;
     271            }
     272            case 1:
     273                VERBOSE(VB_IMPORTANT, LOC_ERR +
     274                        QString("OpenFile(): Could not open."));
     275                break;
     276            case 2:
     277                VERBOSE(VB_IMPORTANT, LOC_ERR +
     278                        QString("OpenFile(): File too small (%1B).")
     279                        .arg(QFileInfo(filename).size()));
     280                break;
     281            case 3:
     282                VERBOSE(VB_IMPORTANT, LOC_ERR +
     283                        "OpenFile(): Improper permissions.");
     284                break;
     285            case 4:
     286                VERBOSE(VB_IMPORTANT, LOC_ERR +
     287                        "OpenFile(): Cannot seek in file.");
     288                break;
     289            default:
     290                break;
     291        }
     292        VERBOSE(VB_FILE, LOC + QString("OpenFile() made %1 attempts in %2 ms")
     293                .arg(openAttempts).arg(openTimer.elapsed()));
     294
     295    }
     296    else
     297    {
     298        QString tmpSubName = filename;
     299        QString dirName  = ".";
     300
     301        int dirPos = filename.lastIndexOf(QChar('/'));
     302        if (dirPos > 0)
     303        {
     304            tmpSubName = filename.mid(dirPos + 1);
     305            dirName = filename.left(dirPos);
     306        }
     307
     308        QString baseName  = tmpSubName;
     309        QString extension = tmpSubName;
     310        QStringList auxFiles;
     311
     312        int suffixPos = tmpSubName.lastIndexOf(QChar('.'));
     313        if (suffixPos > 0)
     314        {
     315            baseName = tmpSubName.left(suffixPos);
     316            extension = tmpSubName.right(suffixPos-1);
     317            if (is_subtitle_possible(extension))
     318            {
     319                QMutexLocker locker(&subExtLock);
     320                QStringList::const_iterator eit = subExt.begin();
     321                for (; eit != subExt.end(); eit++)
     322                    auxFiles += baseName + *eit;
     323            }
     324        }
     325
     326        remotefile = new RemoteFile(filename, false, true,
     327                                    retry_ms, &auxFiles);
     328        if (!remotefile->isOpen())
     329        {
     330            VERBOSE(VB_IMPORTANT, LOC_ERR +
     331                    QString("RingBuffer::RingBuffer(): Failed to open remote "
     332                            "file (%1)").arg(filename));
     333            delete remotefile;
     334            remotefile = NULL;
     335        }
     336        else
     337        {
     338            QStringList aux = remotefile->GetAuxiliaryFiles();
     339            if (aux.size())
     340                subtitlefilename = dirName + "/" + aux[0];
     341        }
     342    }
     343
     344    setswitchtonext = false;
     345    ateof = false;
     346    commserror = false;
     347    numfailures = 0;
     348
     349    rawbitrate = 8000;
     350    CalcReadAheadThresh();
     351
     352    bool ok = fd2 >= 0 || remotefile;
     353
     354    rwlock.unlock();
     355
     356    return ok;
     357}
     358
     359bool FileRingBuffer::IsOpen(void) const
     360{
     361    rwlock.lockForRead();
     362    bool ret = tfw || (fd2 > -1) || remotefile;
     363    rwlock.unlock();
     364    return ret;
     365}
     366
     367/** \fn FileRingBuffer::safe_read(int, void*, uint)
     368 *  \brief Reads data from the file-descriptor.
     369 *
     370 *   This will re-read the file forever until the
     371 *   end-of-file is reached or the buffer is full.
     372 *
     373 *  \param fd   File descriptor to read from
     374 *  \param data Pointer to where data will be written
     375 *  \param sz   Number of bytes to read
     376 *  \return Returns number of bytes read
     377 */
     378int FileRingBuffer::safe_read(int fd, void *data, uint sz)
     379{
     380    int ret;
     381    unsigned tot = 0;
     382    unsigned errcnt = 0;
     383    unsigned zerocnt = 0;
     384
     385    if (fd2 < 0)
     386    {
     387        VERBOSE(VB_IMPORTANT, LOC_ERR +
     388                "Invalid file descriptor in 'safe_read()'");
     389        return 0;
     390    }
     391
     392    if (stopreads)
     393        return 0;
     394
     395    while (tot < sz)
     396    {
     397        ret = read(fd2, (char *)data + tot, sz - tot);
     398        if (ret < 0)
     399        {
     400            if (errno == EAGAIN)
     401                continue;
     402
     403            VERBOSE(VB_IMPORTANT,
     404                    LOC_ERR + "File I/O problem in 'safe_read()'" + ENO);
     405
     406            errcnt++;
     407            numfailures++;
     408            if (errcnt == 3)
     409                break;
     410        }
     411        else if (ret > 0)
     412        {
     413            tot += ret;
     414        }
     415
     416        if (oldfile)
     417            break;
     418
     419        if (ret == 0) // EOF returns 0
     420        {
     421            if (tot > 0)
     422                break;
     423
     424            zerocnt++;
     425
     426            // 0.36 second timeout for livetvchain with usleep(60000),
     427            // or 2.4 seconds if it's a new file less than 30 minutes old.
     428            if (zerocnt >= (livetvchain ? 6 : 40))
     429            {
     430                break;
     431            }
     432        }
     433        if (stopreads)
     434            break;
     435        if (tot < sz)
     436            usleep(60000);
     437    }
     438    return tot;
     439}
     440
     441/** \fn FileRingBuffer::safe_read(RemoteFile*, void*, uint)
     442 *  \brief Reads data from the RemoteFile.
     443 *
     444 *  \param rf   RemoteFile to read from
     445 *  \param data Pointer to where data will be written
     446 *  \param sz   Number of bytes to read
     447 *  \return Returns number of bytes read
     448 */
     449int FileRingBuffer::safe_read(RemoteFile *rf, void *data, uint sz)
     450{
     451    int ret = rf->Read(data, sz);
     452    if (ret < 0)
     453    {
     454        VERBOSE(VB_IMPORTANT, LOC_ERR +
     455                "safe_read(RemoteFile* ...): read failed");
     456           
     457        poslock.lockForRead();
     458        rf->Seek(internalreadpos - readAdjust, SEEK_SET);
     459        poslock.unlock();
     460        numfailures++;
     461    }
     462    else if (ret == 0)
     463    {
     464        VERBOSE(VB_FILE, LOC +
     465                "safe_read(RemoteFile* ...): at EOF");
     466    }
     467
     468    return ret;
     469}
     470
     471long long FileRingBuffer::GetReadPosition(void) const
     472{
     473    poslock.lockForRead();
     474    long long ret = readpos;
     475    poslock.unlock();
     476    return ret;
     477}
     478
     479long long FileRingBuffer::GetRealFileSize(void) const
     480{
     481    rwlock.lockForRead();
     482    long long ret = -1;
     483    if (remotefile)
     484        ret = remotefile->GetFileSize();
     485    else
     486        ret = QFileInfo(filename).size();
     487    rwlock.unlock();
     488    return ret;
     489}
     490
     491long long FileRingBuffer::Seek(long long pos, int whence, bool has_lock)
     492{
     493    VERBOSE(VB_FILE, LOC + QString("Seek(%1,%2,%3)")
     494            .arg(pos).arg((SEEK_SET==whence)?"SEEK_SET":
     495                          ((SEEK_CUR==whence)?"SEEK_CUR":"SEEK_END"))
     496            .arg(has_lock?"locked":"unlocked"));
     497
     498    long long ret = -1;
     499
     500    StopReads();
     501
     502    // lockForWrite takes priority over lockForRead, so this will
     503    // take priority over the lockForRead in the read ahead thread.
     504    if (!has_lock)
     505        rwlock.lockForWrite();
     506
     507    StartReads();
     508
     509    if (writemode)
     510    {
     511        ret = WriterSeek(pos, whence, true);
     512        if (!has_lock)
     513            rwlock.unlock();
     514        return ret;
     515    }
     516
     517    poslock.lockForWrite();
     518
     519    // Optimize no-op seeks
     520    if (readaheadrunning &&
     521        ((whence == SEEK_SET && pos == readpos) ||
     522         (whence == SEEK_CUR && pos == 0)))
     523    {
     524        ret = readpos;
     525
     526        poslock.unlock();
     527        if (!has_lock)
     528            rwlock.unlock();
     529
     530        return ret;
     531    }
     532
     533    // only valid for SEEK_SET & SEEK_CUR
     534    long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos;
     535
     536#if 1
     537    // Optimize short seeks where the data for
     538    // them is in our ringbuffer already.
     539    if (readaheadrunning &&
     540        (SEEK_SET==whence || SEEK_CUR==whence))
     541    {
     542        rbrlock.lockForWrite();
     543        rbwlock.lockForRead();
     544        VERBOSE(VB_FILE, LOC +
     545                QString("Seek(): rbrpos: %1 rbwpos: %2"
     546                        "\n\t\t\treadpos: %3 internalreadpos: %4")
     547                .arg(rbrpos).arg(rbwpos)
     548                .arg(readpos).arg(internalreadpos));
     549        bool used_opt = false;
     550        if ((new_pos < readpos))
     551        {
     552            int min_safety = max(fill_min, readblocksize);
     553            int free = ((rbwpos >= rbrpos) ?
     554                        rbrpos + kBufferSize : rbrpos) - rbwpos;
     555            int internal_backbuf =
     556                (rbwpos >= rbrpos) ? rbrpos : rbrpos - rbwpos;
     557            internal_backbuf = min(internal_backbuf, free - min_safety);
     558            long long sba = readpos - new_pos;
     559            VERBOSE(VB_FILE, LOC +
     560                    QString("Seek(): internal_backbuf: %1 sba: %2")
     561                    .arg(internal_backbuf).arg(sba));
     562            if (internal_backbuf >= sba)
     563            {
     564                rbrpos = (rbrpos>=sba) ? rbrpos - sba :
     565                    kBufferSize + rbrpos - sba;
     566                used_opt = true;
     567                VERBOSE(VB_FILE, LOC +
     568                        QString("Seek(): OPT1 rbrpos: %1 rbwpos: %2"
     569                                "\n\t\t\treadpos: %3 internalreadpos: %4")
     570                        .arg(rbrpos).arg(rbwpos)
     571                        .arg(new_pos).arg(internalreadpos));
     572            }
     573        }
     574        else if ((new_pos >= readpos) && (new_pos <= internalreadpos))
     575        {
     576            rbrpos = (rbrpos + (new_pos - readpos)) % kBufferSize;
     577            used_opt = true;
     578            VERBOSE(VB_FILE, LOC +
     579                    QString("Seek(): OPT2 rbrpos: %1 sba: %2")
     580                    .arg(rbrpos).arg(readpos - new_pos));
     581        }
     582        rbwlock.unlock();
     583        rbrlock.unlock();
     584
     585        if (used_opt)
     586        {
     587            if (ignorereadpos >= 0)
     588            {
     589                // seek should always succeed since we were at this position
     590                int ret;
     591                if (remotefile)
     592                    ret = remotefile->Seek(internalreadpos, SEEK_SET);
     593                else
     594                {
     595                    ret = lseek64(fd2, internalreadpos, SEEK_SET);
     596                    posix_fadvise(fd2, 0,
     597                                  internalreadpos, POSIX_FADV_DONTNEED);
     598                    posix_fadvise(fd2, internalreadpos,
     599                                  1*1024*1024, POSIX_FADV_WILLNEED);
     600                }
     601                VERBOSE(VB_FILE, LOC +
     602                        QString("Seek to %1 from ignore pos %2 returned %3")
     603                        .arg(internalreadpos).arg(ignorereadpos).arg(ret));
     604                ignorereadpos = -1;
     605            }
     606            readpos = new_pos;
     607            poslock.unlock();
     608            generalWait.wakeAll();
     609            ateof = false;
     610            readsallowed = false;
     611            if (!has_lock)
     612                rwlock.unlock();
     613            return new_pos;
     614        }
     615    }
     616#endif
     617
     618#if 1
     619    // This optimizes the seek end-250000, read, seek 0, read portion
     620    // of the pattern ffmpeg performs at the start of playback to
     621    // determine the pts.
     622    // If the seek is a SEEK_END or is a seek where the position
     623    // changes over 100 MB we check the file size and if the
     624    // destination point is within 300000 bytes of the end of
     625    // the file we enter a special mode where the read ahead
     626    // buffer stops reading data and all reads are made directly
     627    // until another seek is performed. The point of all this is
     628    // to avoid flushing out the buffer that still contains all
     629    // the data the final seek 0, read will need just to read the
     630    // last 250000 bytes. A further optimization would be to buffer
     631    // the 250000 byte read, which is currently performed in 32KB
     632    // blocks (inefficient with RemoteFile).
     633    if ((remotefile || fd2 >= 0) && (ignorereadpos < 0))
     634    {
     635        long long off_end = 0xDEADBEEF;
     636        if (SEEK_END == whence)
     637        {
     638            off_end = pos;
     639            if (remotefile)
     640            {
     641                new_pos = remotefile->GetFileSize() - off_end;
     642            }
     643            else
     644            {
     645                QFileInfo fi(filename);
     646                new_pos = fi.size() - off_end;
     647            }
     648        }
     649        else
     650        {
     651            if (remotefile)
     652            {
     653                off_end = remotefile->GetFileSize() - new_pos;
     654            }
     655            else
     656            {
     657                QFileInfo fi(filename);
     658                off_end = fi.size() - new_pos;
     659            }
     660        }
     661
     662        if (off_end != 0xDEADBEEF)
     663        {
     664            VERBOSE(VB_FILE, LOC +
     665                    QString("Seek(): Offset from end: %1").arg(off_end));
     666        }
     667
     668        if (off_end <= 250000)
     669        {
     670            VERBOSE(VB_FILE, LOC +
     671                    QString("Seek(): offset from end: %1").arg(off_end) +
     672                    "\n\t\t\t -- ignoring read ahead thread until next seek.");
     673
     674            ignorereadpos = new_pos;
     675            errno = EINVAL;
     676            long long ret;
     677            if (remotefile)
     678                ret = remotefile->Seek(ignorereadpos, SEEK_SET);
     679            else
     680            {
     681                ret = lseek64(fd2, ignorereadpos, SEEK_SET);
     682                posix_fadvise(fd2, ignorereadpos, 250000, POSIX_FADV_WILLNEED);
     683            }
     684
     685            if (ret < 0)
     686            {
     687                int tmp_eno = errno;
     688                QString cmd = QString("Seek(%1, SEEK_SET) ign ")
     689                    .arg(ignorereadpos);
     690
     691                ignorereadpos = -1;
     692
     693                VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
     694
     695                // try to return to former position..
     696                if (remotefile)
     697                    ret = remotefile->Seek(internalreadpos, SEEK_SET);
     698                else
     699                    ret = lseek64(fd2, internalreadpos, SEEK_SET);
     700                if (ret < 0)
     701                {
     702                    QString cmd = QString("Seek(%1, SEEK_SET) int ")
     703                        .arg(internalreadpos);
     704                    VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
     705                }
     706                else
     707                {
     708                    QString cmd = QString("Seek(%1, %2) int ")
     709                        .arg(internalreadpos)
     710                        .arg((SEEK_SET == whence) ? "SEEK_SET" :
     711                             ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
     712                    VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " succeeded");
     713                }
     714                ret = -1;
     715                errno = tmp_eno;
     716            }
     717            else
     718            {
     719                ateof = false;
     720                readsallowed = false;
     721            }
     722
     723            rbwlock.unlock();
     724            rbrlock.unlock();
     725            poslock.unlock();
     726
     727            generalWait.wakeAll();
     728
     729            if (!has_lock)
     730                rwlock.unlock();
     731
     732            return ret;
     733        }
     734    }
     735#endif
     736
     737    // Here we perform a normal seek. When successful we
     738    // need to call ResetReadAhead(). A reset means we will
     739    // need to refill the buffer, which takes some time.
     740    if (remotefile)
     741    {
     742        ret = remotefile->Seek(pos, whence, readpos);
     743        if (ret<0)
     744            errno = EINVAL;
     745    }
     746    else
     747    {
     748        ret = lseek64(fd2, pos, whence);
     749        if (ret >= 0)
     750        {
     751            posix_fadvise(fd2, 0,   ret,         POSIX_FADV_DONTNEED);
     752            posix_fadvise(fd2, ret, 1*1024*1024, POSIX_FADV_WILLNEED);
     753        }
     754    }
     755
     756    if (ret >= 0)
     757    {
     758        readpos = ret;
     759       
     760        ignorereadpos = -1;
     761
     762        if (readaheadrunning)
     763            ResetReadAhead(readpos);
     764
     765        readAdjust = 0;
     766    }
     767    else
     768    {
     769        QString cmd = QString("Seek(%1, %2)").arg(pos)
     770            .arg((SEEK_SET == whence) ? "SEEK_SET" :
     771                 ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
     772        VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
     773    }
     774
     775    poslock.unlock();
     776
     777    generalWait.wakeAll();
     778
     779    if (!has_lock)
     780        rwlock.unlock();
     781
     782    return ret;
     783}
  • libs/libmythtv/mythdvdplayer.cpp

     
    1111MythDVDPlayer::MythDVDPlayer(bool muted)
    1212  : MythPlayer(muted), m_buttonVersion(0),
    1313    dvd_stillframe_showing(false), need_change_dvd_track(0),
    14     m_initial_title(-1), m_initial_audio_track(-1), m_initial_subtitle_track(-1),
     14    m_initial_title(-1), m_initial_audio_track(-1),
     15    m_initial_subtitle_track(-1),
    1516    m_stillFrameLength(0)
    1617{
    1718}
     
    2526                                          int64_t timecode, bool wrap)
    2627{
    2728    MythPlayer::ReleaseNextVideoFrame(buffer, timecode,
    28                         !player_ctx->buffer->InDiscMenuOrStillFrame());
     29                        !player_ctx->buffer->IsInDiscMenuOrStillFrame());
    2930}
    3031
    3132void MythDVDPlayer::DisableCaptions(uint mode, bool osd_msg)
    3233{
    33     if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->isDVD())
     34    if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->IsDVD())
    3435        player_ctx->buffer->DVD()->SetTrack(kTrackTypeSubtitle, -1);
    3536    MythPlayer::DisableCaptions(mode, osd_msg);
    3637}
    3738
    3839void MythDVDPlayer::EnableCaptions(uint mode, bool osd_msg)
    3940{
    40     if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->isDVD())
     41    if ((kDisplayAVSubtitle & mode) && player_ctx->buffer->IsDVD())
    4142        player_ctx->buffer->DVD()->SetTrack(kTrackTypeSubtitle,
    4243                                            GetTrack(kTrackTypeSubtitle));
    4344    MythPlayer::EnableCaptions(mode, osd_msg);
     
    4546
    4647void MythDVDPlayer::DisplayPauseFrame(void)
    4748{
    48     if (player_ctx->buffer->isDVD() &&
    49         player_ctx->buffer->DVD()->InStillFrame())
     49    if (player_ctx->buffer->IsDVD() &&
     50        player_ctx->buffer->DVD()->IsInStillFrame())
     51    {
    5052        SetScanType(kScan_Progressive);
     53    }
    5154    DisplayDVDButton();
    5255    MythPlayer::DisplayPauseFrame();
    5356}
     
    6063
    6164bool MythDVDPlayer::PrebufferEnoughFrames(bool pause_audio, int  min_buffers)
    6265{
    63     bool instill = player_ctx->buffer->InDiscMenuOrStillFrame();
     66    bool instill = player_ctx->buffer->IsInDiscMenuOrStillFrame();
    6467    return MythPlayer::PrebufferEnoughFrames(!instill, 1);
    6568}
    6669
     
    7477bool MythDVDPlayer::DecoderGetFrameREW(void)
    7578{
    7679    MythPlayer::DecoderGetFrameREW();
    77     return (player_ctx->buffer->isDVD() &&
    78            (player_ctx->buffer->DVD()->GetCurrentTime() < 2));
     80    return (player_ctx->buffer->IsDVD() &&
     81            (player_ctx->buffer->DVD()->GetCurrentTime() < 2));
    7982}
    8083
    8184void MythDVDPlayer::PreProcessNormalFrame(void)
     
    8588
    8689bool MythDVDPlayer::VideoLoop(void)
    8790{
    88     if (!player_ctx->buffer->isDVD())
     91    if (!player_ctx->buffer->IsDVD())
    8992    {
    9093        SetErrored("RingBuffer is not a DVD.");
    9194        return !IsErrored();
     
    104107    bool release_one = (nbframes > 1) && videoPaused && !allpaused &&
    105108                       (!videoOutput->EnoughFreeFrames() ||
    106109                        player_ctx->buffer->DVD()->IsWaiting() ||
    107                         player_ctx->buffer->DVD()->InStillFrame());
     110                        player_ctx->buffer->DVD()->IsInStillFrame());
    108111    if (release_all || release_one)
    109112    {
    110113        if (nbframes < 5 && videoOutput)
     
    123126        VERBOSE(VB_PLAYBACK, LOC + "Clearing Mythtv dvd wait state");
    124127        player_ctx->buffer->DVD()->SkipDVDWaitingForPlayer();
    125128        ClearAfterSeek(true);
    126         if (!player_ctx->buffer->DVD()->InStillFrame() && videoPaused)
     129        if (!player_ctx->buffer->DVD()->IsInStillFrame() && videoPaused)
    127130            UnpauseVideo();
    128131        return !IsErrored();
    129132    }
     
    136139        {
    137140            VERBOSE(VB_PLAYBACK, LOC + "Clearing DVD wait state");
    138141            player_ctx->buffer->DVD()->WaitSkip();
    139             if (!player_ctx->buffer->DVD()->InStillFrame() && videoPaused)
     142            if (!player_ctx->buffer->DVD()->IsInStillFrame() && videoPaused)
    140143                UnpauseVideo();
    141144            return !IsErrored();
    142145        }
    143146
    144147        // we need a custom presentation method for still frame menus with audio
    145148        if (player_ctx->buffer->DVD()->IsInMenu() &&
    146            !player_ctx->buffer->DVD()->InStillFrame())
     149            !player_ctx->buffer->DVD()->IsInStillFrame())
    147150        {
    148151            // ensure we refresh the pause frame
    149152            if (!dvd_stillframe_showing)
     
    155158        }
    156159
    157160        // the still frame is treated as a pause frame
    158         if (player_ctx->buffer->DVD()->InStillFrame())
     161        if (player_ctx->buffer->DVD()->IsInStillFrame())
    159162        {
    160163            // ensure we refresh the pause frame
    161164            if (!dvd_stillframe_showing)
     
    318321
    319322bool MythDVDPlayer::PrepareAudioSample(int64_t &timecode)
    320323{
    321     if (!player_ctx->buffer->InDiscMenuOrStillFrame())
     324    if (!player_ctx->buffer->IsInDiscMenuOrStillFrame())
    322325        WrapTimecode(timecode, TC_AUDIO);
    323326
    324     if (player_ctx->buffer->isDVD() &&
    325         player_ctx->buffer->DVD()->InStillFrame())
     327    if (player_ctx->buffer->IsDVD() &&
     328        player_ctx->buffer->DVD()->IsInStillFrame())
    326329        return true;
    327330    return false;
    328331}
    329332
    330333void MythDVDPlayer::SetBookmark(void)
    331334{
    332     if (player_ctx->buffer->InDiscMenuOrStillFrame())
     335    if (player_ctx->buffer->IsInDiscMenuOrStillFrame())
     336    {
    333337        SetDVDBookmark(0);
     338    }
    334339    else
    335340    {
    336341        SetDVDBookmark(framesPlayed);
     
    348353
    349354uint64_t MythDVDPlayer::GetBookmark(void)
    350355{
    351     if (gCoreContext->IsDatabaseIgnored() || !player_ctx->buffer->isDVD())
     356    if (gCoreContext->IsDatabaseIgnored() || !player_ctx->buffer->IsDVD())
    352357        return 0;
    353358
    354359    QStringList dvdbookmark = QStringList();
     
    387392    MythPlayer::ChangeSpeed();
    388393    if (decoder)
    389394        decoder->UpdateDVDFramesPlayed();
    390     if (play_speed != normal_speed && player_ctx->buffer->isDVD())
     395    if (play_speed != normal_speed && player_ctx->buffer->IsDVD())
    391396        player_ctx->buffer->DVD()->SetDVDSpeed(-1);
    392     else if (player_ctx->buffer->isDVD())
     397    else if (player_ctx->buffer->IsDVD())
    393398        player_ctx->buffer->DVD()->SetDVDSpeed();
    394399}
    395400
     
    400405
    401406long long MythDVDPlayer::CalcMaxFFTime(long long ff, bool setjump) const
    402407{
    403     if ((totalFrames > 0) && player_ctx->buffer->isDVD() &&
     408    if ((totalFrames > 0) && player_ctx->buffer->IsDVD() &&
    404409        player_ctx->buffer->DVD()->TitleTimeLeft() < 5)
    405410        return 0;
    406411    return MythPlayer::CalcMaxFFTime(ff, setjump);
     
    413418    info.values.insert("position",   0);
    414419    info.values.insert("progbefore", 0);
    415420    info.values.insert("progafter",  0);
    416     if (!player_ctx->buffer->isDVD())
     421    if (!player_ctx->buffer->IsDVD())
    417422        return;
    418423
    419424    int playbackLen = totalLength;
     
    438443void MythDVDPlayer::SeekForScreenGrab(uint64_t &number, uint64_t frameNum,
    439444                                      bool absolute)
    440445{
    441     if (!player_ctx->buffer->isDVD())
     446    if (!player_ctx->buffer->IsDVD())
    442447        return;
    443448    if (GoToDVDMenu("menu"))
    444449    {
    445450        if (player_ctx->buffer->DVD()->IsInMenu() &&
    446            !player_ctx->buffer->DVD()->InStillFrame())
     451            !player_ctx->buffer->DVD()->IsInStillFrame())
     452        {
    447453            GoToDVDProgram(1);
     454        }
    448455    }
    449456    else if (player_ctx->buffer->DVD()->GetTotalTimeOfTitle() < 60)
    450457    {
     
    471478{
    472479    if (decoder)
    473480        decoder->ChangeDVDTrack(need_change_dvd_track > 0);
    474     ClearAfterSeek(!player_ctx->buffer->InDiscMenuOrStillFrame());
     481    ClearAfterSeek(!player_ctx->buffer->IsInDiscMenuOrStillFrame());
    475482}
    476483
    477484void MythDVDPlayer::DisplayDVDButton(void)
    478485{
    479     if (!osd || !player_ctx->buffer->isDVD())
     486    if (!osd || !player_ctx->buffer->IsDVD())
    480487        return;
    481488
    482489    uint buttonversion = 0;
     
    484491    bool numbuttons    = player_ctx->buffer->DVD()->NumMenuButtons();
    485492
    486493    // nothing to do
    487     if (buttonversion == m_buttonVersion)
     494    if (buttonversion == ((uint)m_buttonVersion))
    488495    {
    489496        player_ctx->buffer->DVD()->ReleaseMenuButton();
    490497        return;
     
    510517
    511518bool MythDVDPlayer::GoToDVDMenu(QString str)
    512519{
    513     if (!player_ctx->buffer->isDVD())
     520    if (!player_ctx->buffer->IsDVD())
    514521        return false;
    515522    textDisplayMode = kDisplayNone;
    516523    bool ret = player_ctx->buffer->DVD()->GoToMenu(str);
     
    527534
    528535void MythDVDPlayer::GoToDVDProgram(bool direction)
    529536{
    530     if (!player_ctx->buffer->isDVD())
     537    if (!player_ctx->buffer->IsDVD())
    531538        return;
    532539    if (direction == 0)
    533540        player_ctx->buffer->DVD()->GoToPreviousProgram();
     
    537544
    538545void MythDVDPlayer::SetDVDBookmark(uint64_t frame)
    539546{
    540     if (!player_ctx->buffer->isDVD())
     547    if (!player_ctx->buffer->IsDVD())
    541548        return;
    542549
    543550    uint64_t framenum = frame;
     
    556563        return;
    557564    }
    558565
    559     if (!player_ctx->buffer->InDiscMenuOrStillFrame() &&
    560         player_ctx->buffer->DVD()->GetTotalTimeOfTitle() > 120 && frame > 0)
     566    if (!player_ctx->buffer->IsInDiscMenuOrStillFrame() &&
     567        player_ctx->buffer->DVD()->
     568        GetTotalTimeOfTitle() > 120 && frame > 0)
    561569    {
    562570        audiotrack = GetTrack(kTrackTypeAudio);
    563571        if (GetCaptionMode() == kDisplayAVSubtitle)
     
    637645
    638646void MythDVDPlayer::StillFrameCheck(void)
    639647{
    640     if (player_ctx->buffer->isDVD() &&
    641         player_ctx->buffer->DVD()->InStillFrame() &&
     648    if (player_ctx->buffer->IsDVD() &&
     649        player_ctx->buffer->DVD()->IsInStillFrame() &&
    642650       (m_stillFrameLength > 0) && (m_stillFrameLength < 0xff))
    643651    {
    644652        m_stillFrameTimerLock.lock();
  • libs/libmythtv/previewgenerator.cpp

     
    788788        }
    789789    }
    790790
    791     RingBuffer *rbuf = new RingBuffer(filename, false, false, 0);
     791    RingBuffer *rbuf = RingBuffer::Create(filename, false, false, 0);
    792792    if (!rbuf->IsOpen())
    793793    {
    794794        VERBOSE(VB_IMPORTANT, LOC_ERR + "Previewer could not open file: " +
  • libs/libmythtv/FileRingBuffer.h

     
     1#include "RingBuffer.h"
     2
     3class MPUBLIC FileRingBuffer : public RingBuffer
     4{
     5    friend class RingBuffer;
     6  public:
     7    ~FileRingBuffer();
     8
     9    // Gets
     10    virtual bool      IsOpen(void)          const;
     11    virtual long long GetReadPosition(void) const;
     12    virtual long long GetRealFileSize(void) const;
     13
     14    // General Commands
     15    virtual bool OpenFile(const QString &lfilename,
     16                          uint retry_ms = kDefaultOpenTimeout);
     17    virtual long long Seek(long long pos, int whence, bool has_lock);
     18
     19  protected:
     20    FileRingBuffer(const QString &lfilename,
     21                   bool write, bool readahead, int timeout_ms);
     22
     23    virtual int safe_read(void *data, uint sz)
     24    {
     25        if (remotefile)
     26            return safe_read(remotefile, data, sz);
     27        else if (fd2 >= 0)
     28            return safe_read(fd2, data, sz);
     29
     30        errno = EBADF;
     31        return -1;
     32    }
     33    int safe_read(int fd, void *data, uint sz);
     34    int safe_read(RemoteFile *rf, void *data, uint sz);
     35};
  • libs/libmythtv/RingBuffer.cpp

     
    99#include <sys/time.h>
    1010#include <unistd.h>
    1111#include <fcntl.h>
    12 #include <pthread.h>
    1312
    1413// Qt headers
    1514#include <QFile>
    1615#include <QDateTime>
    17 #include <QFileInfo>
    18 #include <QDir>
    1916
    20 using namespace std;
    21 
    22 #include "mythcontext.h" // for VERBOSE
    23 #include "mythconfig.h"
    24 #include "exitcodes.h"
    25 #include "RingBuffer.h"
    26 #include "remotefile.h"
    2717#include "ThreadedFileWriter.h"
    28 #include "livetvchain.h"
     18#include "FileRingBuffer.h"
    2919#include "DVDRingBuffer.h"
    3020#include "BDRingBuffer.h"
    31 #include "util.h"
     21#include "livetvchain.h"
     22#include "mythcontext.h"
     23#include "RingBuffer.h"
     24#include "mythconfig.h"
     25#include "remotefile.h"
    3226#include "compat.h"
     27#include "util.h"
    3328
    34 #ifndef O_STREAMING
    35 #define O_STREAMING 0
    36 #endif
    37 
    38 #ifndef O_LARGEFILE
    39 #define O_LARGEFILE 0
    40 #endif
    41 
    42 #ifndef O_BINARY
    43 #define O_BINARY 0
    44 #endif
    45 
    4629#if HAVE_POSIX_FADVISE < 1
    4730static int posix_fadvise(int, off_t, off_t, int) { return 0; }
    4831#define POSIX_FADV_SEQUENTIAL 0
     
    122105 *                      the file after the first failure in
    123106 *                      milliseconds before giving up.
    124107 */
    125 RingBuffer::RingBuffer(const QString &lfilename,
    126                        bool write, bool readahead,
    127                        int timeout_ms)
    128     : readpos(0),               writepos(0),
    129       internalreadpos(0),       ignorereadpos(-1),
    130       rbrpos(0),                rbwpos(0),
    131       stopreads(false),
    132       filename(lfilename),      subtitlefilename(QString::null),
    133       tfw(NULL),                fd2(-1),
    134       writemode(false),         remotefile(NULL),
    135       startreadahead(readahead),readAheadBuffer(NULL),
    136       readaheadrunning(false),  reallyrunning(false),
    137       request_pause(false),     paused(false),
    138       ateof(false),             readsallowed(false),
    139       setswitchtonext(false),   streamOnly(false),
    140       rawbitrate(8000),         playspeed(1.0f),
    141       fill_threshold(65536),    fill_min(-1),
    142       readblocksize(CHUNK),     wanttoread(0),
    143       numfailures(0),           commserror(false),
    144       dvdPriv(NULL),            bdPriv(NULL),
    145       oldfile(false),           livetvchain(NULL),
    146       ignoreliveeof(false),     readAdjust(0)
     108RingBuffer *RingBuffer::Create(
     109    const QString &xfilename, bool write,
     110    bool usereadahead, int timeout_ms, bool stream_only)
    147111{
    148     filename.detach();
     112    QString lfilename = xfilename;
    149113
    150     {
    151         QMutexLocker locker(&subExtLock);
    152         if (!subExt.size())
    153         {
    154             // Possible subtitle file extensions '.srt', '.sub', '.txt'
    155             subExt += ".srt";
    156             subExt += ".sub";
    157             subExt += ".txt";
    158 
    159             // Extensions for which a subtitle file should not exist
    160             subExtNoCheck = subExt;
    161             subExtNoCheck += ".gif";
    162             subExtNoCheck += ".png";
    163         }
    164     }
    165 
    166114    if (write)
    167115    {
    168         if (filename.startsWith("myth://"))
    169         {
    170             remotefile = new RemoteFile(filename, true);
    171             if (!remotefile->isOpen())
    172             {
    173                 VERBOSE(VB_IMPORTANT,
    174                         QString("RingBuffer::RingBuffer(): Failed to open "
    175                                 "remote file (%1) for write").arg(filename));
    176                 delete remotefile;
    177                 remotefile = NULL;
    178             }
    179             else
    180                 writemode = true;
    181         }
    182         else
    183         {
    184             tfw = new ThreadedFileWriter(
    185                 filename, O_WRONLY|O_TRUNC|O_CREAT|O_LARGEFILE, 0644);
    186 
    187             if (!tfw->Open())
    188             {
    189                 delete tfw;
    190                 tfw = NULL;
    191             }
    192             else
    193                 writemode = true;
    194         }
    195         return;
     116        return new FileRingBuffer(
     117            lfilename, write, usereadahead, timeout_ms);
    196118    }
    197119
    198     if (timeout_ms >= 0)
    199         OpenFile(filename, timeout_ms);
    200 }
    201 
    202 /** \fn check_permissions(const QString&)
    203  *  \brief Returns false iff file exists and has incorrect permissions.
    204  *  \param filename File (including path) that we want to know about
    205  */
    206 static bool check_permissions(const QString &filename)
    207 {
    208     QFileInfo fileInfo(filename);
    209     if (fileInfo.exists() && !fileInfo.isReadable())
    210     {
    211         VERBOSE(VB_IMPORTANT, LOC_ERR +
    212                 "File exists but is not readable by MythTV!");
    213         return false;
    214     }
    215     return true;
    216 }
    217 
    218 static bool is_subtitle_possible(const QString &extension)
    219 {
    220     QMutexLocker locker(&RingBuffer::subExtLock);
    221     bool no_subtitle = false;
    222     for (uint i = 0; i < (uint)RingBuffer::subExtNoCheck.size(); i++)
    223     {
    224         if (extension.contains(RingBuffer::subExtNoCheck[i].right(3)))
    225         {
    226             no_subtitle = true;
    227             break;
    228         }
    229     }
    230     return !no_subtitle;
    231 }
    232 
    233 static QString local_sub_filename(QFileInfo &fileInfo)
    234 {
    235     // Subtitle handling
    236     QString vidFileName = fileInfo.fileName();
    237     QString dirName = fileInfo.absolutePath();
    238 
    239     QString baseName = vidFileName;
    240     int suffixPos = vidFileName.lastIndexOf(QChar('.'));
    241     if (suffixPos > 0)
    242         baseName = vidFileName.left(suffixPos);
    243 
    244     QStringList el;
    245     {
    246         // The dir listing does not work if the filename has the
    247         // following chars "[]()" so we convert them to the wildcard '?'
    248         const QString findBaseName = baseName
    249             .replace("[", "?")
    250             .replace("]", "?")
    251             .replace("(", "?")
    252             .replace(")", "?");
    253 
    254         QMutexLocker locker(&RingBuffer::subExtLock);
    255         QStringList::const_iterator eit = RingBuffer::subExt.begin();
    256         for (; eit != RingBuffer::subExt.end(); eit++)
    257             el += findBaseName + *eit;
    258     }
    259 
    260     // Some Qt versions do not accept paths in the search string of
    261     // entryList() so we have to set the dir first
    262     QDir dir;
    263     dir.setPath(dirName);
    264 
    265     const QStringList candidates = dir.entryList(el);
    266 
    267     QStringList::const_iterator cit = candidates.begin();
    268     for (; cit != candidates.end(); ++cit)
    269     {
    270         QFileInfo fi(dirName + "/" + *cit);
    271         if (fi.exists() && (fi.size() >= RingBuffer::kReadTestSize))
    272             return fi.absoluteFilePath();
    273     }
    274 
    275     return QString::null;
    276 }
    277 
    278 /** \brief Opens a file for reading.
    279  *
    280  *  \param lfilename  Name of file to read
    281  *  \param retry_ms   How many ms to retry reading the file
    282  *                    after the first try before giving up.
    283  */
    284 void RingBuffer::OpenFile(const QString &lfilename, uint retry_ms)
    285 {
    286     VERBOSE(VB_PLAYBACK, LOC + QString("OpenFile(%1, %2 ms)")
    287             .arg(lfilename).arg(retry_ms));
    288 
    289     if (retry_ms >= 1 && retry_ms <= 20)
    290     {
    291         VERBOSE(VB_IMPORTANT, LOC + QString("OpenFile(%1, %2 ms)")
    292                 .arg(lfilename).arg(retry_ms) +
    293                 "Timeout small, assuming caller meant for this "
    294                 "to be retries." + "\n\t\t\t"
    295                 "WARNING: This workaround will be removed after the "
    296                 "0.24 release, and this client may stop working.");
    297         retry_ms *= 150;
    298         qWarning("Applying temporary OpenFile() hack");
    299     }
    300 
    301     rwlock.lockForWrite();
    302 
    303     filename = lfilename;
    304 
    305     if (remotefile)
    306     {
    307         delete remotefile;
    308     }
    309 
    310     if (fd2 >= 0)
    311     {
    312         close(fd2);
    313         fd2 = -1;
    314     }
    315 
    316     bool is_local = false;
    317120    bool is_dvd = false;
    318     (void) is_dvd; // not used when frontend is disabled.
    319     bool is_bd = false;
    320     (void) is_bd;
     121    bool is_bd  = false;
    321122
    322     if (!streamOnly && filename.startsWith("myth://"))
     123    if (!stream_only && lfilename.startsWith("myth://"))
    323124    {
    324125        struct stat fileInfo;
    325         if ((RemoteFile::Exists(filename, &fileInfo)) &&
     126        if ((RemoteFile::Exists(lfilename, &fileInfo)) &&
    326127            (S_ISDIR(fileInfo.st_mode)))
    327128        {
    328             QString tmpFile = filename + "/VIDEO_TS";
     129            QString tmpFile = lfilename + "/VIDEO_TS";
    329130            if (RemoteFile::Exists(tmpFile))
    330131            {
    331132                is_dvd = true;
    332133            }
    333134            else
    334135            {
    335                 tmpFile = filename + "/BDMV";
     136                tmpFile = lfilename + "/BDMV";
    336137                if (RemoteFile::Exists(tmpFile))
    337138                    is_bd = true;
    338139            }
    339140        }
    340141    }
    341142
    342     if ((filename.left(1) == "/") ||
    343         (QFile::exists(filename)))
    344         is_local = true;
    345 
    346 #ifdef USING_FRONTEND
    347     else if ((!streamOnly) &&
    348              ((filename.startsWith("dvd:")) || is_dvd ||
    349               ((filename.startsWith("myth://")) &&
    350                ((filename.endsWith(".img")) ||
    351                 (filename.endsWith(".iso"))))))
     143    if ((lfilename.left(1) == "/") || (QFile::exists(lfilename)))
    352144    {
     145    }
     146    else if ((!stream_only) &&
     147             ((lfilename.startsWith("dvd:")) || is_dvd ||
     148              ((lfilename.startsWith("myth://")) &&
     149               ((lfilename.endsWith(".img")) ||
     150                (lfilename.endsWith(".iso"))))))
     151    {
    353152        is_dvd = true;
    354         dvdPriv = new DVDRingBufferPriv();
    355         startreadahead = false;
    356153
    357         if (filename.left(6) == "dvd://")      // 'Play DVD' sends "dvd:/" + dev
    358             filename.remove(0,5);              //            e.g. "dvd://dev/sda"
    359         else if (filename.left(5) == "dvd:/") // Less correct URI "dvd:" + path
    360             filename.remove(0,4);              //            e.g. "dvd:/videos/ET"
     154        if (lfilename.left(6) == "dvd://")     // 'Play DVD' sends "dvd:/" + dev
     155            lfilename.remove(0,5);             // e.g. "dvd://dev/sda"
     156        else if (lfilename.left(5) == "dvd:/") // Less correct URI "dvd:" + path
     157            lfilename.remove(0,4);             // e.g. "dvd:/videos/ET"
    361158
    362         if (QFile::exists(filename) || filename.startsWith("myth://"))
    363             VERBOSE(VB_PLAYBACK, "OpenFile() trying DVD at " + filename);
    364         else
     159        if (QFile::exists(lfilename) || lfilename.startsWith("myth://"))
    365160        {
    366             filename = "/dev/dvd";
     161            VERBOSE(VB_PLAYBACK, "Trying DVD at " + lfilename);
    367162        }
    368     }
    369     else if ((!streamOnly) && (filename.left(3) == "bd:" || is_bd))
    370     {
    371         is_bd = true;
    372         bdPriv = new BDRingBufferPriv();
    373         startreadahead = false;
    374 
    375         if (filename.left(5) == "bd://")      // 'Play DVD' sends "bd:/" + dev
    376             filename.remove(0,4);             //             e.g. "bd://dev/sda"
    377         else if (filename.left(4) == "bd:/")  // Less correct URI "bd:" + path
    378             filename.remove(0,3);             //             e.g. "bd:/videos/ET"
    379 
    380         if (QFile::exists(filename) || filename.startsWith("myth://"))
    381             VERBOSE(VB_PLAYBACK, "OpenFile() trying BD at " + filename);
    382163        else
    383164        {
    384             filename = "/dev/dvd";
     165            lfilename = "/dev/dvd";
    385166        }
    386     }
    387 #endif // USING_FRONTEND
    388167
    389     if (is_local)
     168        return new DVDRingBuffer(lfilename);
     169    }
     170    else if ((!stream_only) && (lfilename.left(3) == "bd:" || is_bd))
    390171    {
    391         char buf[kReadTestSize];
    392         int lasterror = 0;
     172        is_bd = true;
    393173
    394         MythTimer openTimer;
    395         openTimer.start();
     174        if (lfilename.left(5) == "bd://")      // 'Play DVD' sends "bd:/" + dev
     175            lfilename.remove(0,4);             // e.g. "bd://dev/sda"
     176        else if (lfilename.left(4) == "bd:/")  // Less correct URI "bd:" + path
     177            lfilename.remove(0,3);             // e.g. "bd:/videos/ET"
    396178
    397         uint openAttempts = 0;
    398         do
     179        if (QFile::exists(lfilename) || lfilename.startsWith("myth://"))
    399180        {
    400             openAttempts++;
    401             lasterror = 0;
    402             QByteArray fname = filename.toLocal8Bit();
    403             fd2 = open(fname.constData(),
    404                        O_RDONLY|O_LARGEFILE|O_STREAMING|O_BINARY);
    405 
    406             if (fd2 < 0)
    407             {
    408                 if (!check_permissions(filename))
    409                 {
    410                     lasterror = 3;
    411                     break;
    412                 }
    413 
    414                 lasterror = 1;
    415                 usleep(10 * 1000);
    416             }
    417             else
    418             {
    419                 int ret = read(fd2, buf, kReadTestSize);
    420                 if (ret != (int)kReadTestSize)
    421                 {
    422                     lasterror = 2;
    423                     close(fd2);
    424                     fd2 = -1;
    425                     if (oldfile)
    426                         break; // if it's an old file it won't grow..
    427                     usleep(10 * 1000);
    428                 }
    429                 else
    430                 {
    431                     if (0 == lseek(fd2, 0, SEEK_SET))
    432                     {
    433                         posix_fadvise(fd2, 0, 0, POSIX_FADV_SEQUENTIAL);
    434                         posix_fadvise(fd2, 0, 1*1024*1024, POSIX_FADV_WILLNEED);
    435                         lasterror = 0;
    436                         break;
    437                     }
    438                     lasterror = 4;
    439                     close(fd2);
    440                     fd2 = -1;
    441                 }
    442             }
     181            VERBOSE(VB_PLAYBACK, "Trying BD at " + lfilename);
    443182        }
    444         while ((uint)openTimer.elapsed() < retry_ms);
    445 
    446         switch (lasterror)
     183        else
    447184        {
    448             case 0:
    449             {
    450                 QFileInfo fi(filename);
    451                 oldfile = fi.lastModified()
    452                     .secsTo(QDateTime::currentDateTime()) > 60;
    453                 QString extension = fi.completeSuffix().toLower();
    454                 if (is_subtitle_possible(extension))
    455                     subtitlefilename = local_sub_filename(fi);
    456                 break;
    457             }
    458             case 1:
    459                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    460                         QString("OpenFile(): Could not open."));
    461                 break;
    462             case 2:
    463                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    464                         QString("OpenFile(): File too small (%1B).")
    465                         .arg(QFileInfo(filename).size()));
    466                 break;
    467             case 3:
    468                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    469                         "OpenFile(): Improper permissions.");
    470                 break;
    471             case 4:
    472                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    473                         "OpenFile(): Cannot seek in file.");
    474                 break;
    475             default:
    476                 break;
     185            lfilename = "/dev/dvd";
    477186        }
    478         VERBOSE(VB_FILE, LOC + QString("OpenFile() made %1 attempts in %2 ms")
    479                 .arg(openAttempts).arg(openTimer.elapsed()));
    480187
     188        return new BDRingBuffer(lfilename);
    481189    }
    482 #ifdef USING_FRONTEND
    483     else if (is_dvd)
    484     {
    485         dvdPriv->OpenFile(filename);
    486         readblocksize = DVD_BLOCK_SIZE * 62;
    487     }
    488     else if (is_bd)
    489     {
    490         bdPriv->OpenFile(filename);
    491         readblocksize = BD_BLOCK_SIZE * 62;
    492     }
    493 #endif // USING_FRONTEND
    494     else
    495     {
    496         QString tmpSubName = filename;
    497         QString dirName  = ".";
    498190
    499         int dirPos = filename.lastIndexOf(QChar('/'));
    500         if (dirPos > 0)
    501         {
    502             tmpSubName = filename.mid(dirPos + 1);
    503             dirName = filename.left(dirPos);
    504         }
     191    return new FileRingBuffer(
     192        lfilename, write, usereadahead, timeout_ms);
     193}
    505194
    506         QString baseName  = tmpSubName;
    507         QString extension = tmpSubName;
    508         QStringList auxFiles;
    509 
    510         int suffixPos = tmpSubName.lastIndexOf(QChar('.'));
    511         if (suffixPos > 0)
     195RingBuffer::RingBuffer(void) :
     196    readpos(0),               writepos(0),
     197    internalreadpos(0),       ignorereadpos(-1),
     198    rbrpos(0),                rbwpos(0),
     199    stopreads(false),
     200    filename(),               subtitlefilename(),
     201    tfw(NULL),                fd2(-1),
     202    writemode(false),         remotefile(NULL),
     203    startreadahead(false),    readAheadBuffer(NULL),
     204    readaheadrunning(false),  reallyrunning(false),
     205    request_pause(false),     paused(false),
     206    ateof(false),             readsallowed(false),
     207    setswitchtonext(false),
     208    rawbitrate(8000),         playspeed(1.0f),
     209    fill_threshold(65536),    fill_min(-1),
     210    readblocksize(CHUNK),     wanttoread(0),
     211    numfailures(0),           commserror(false),
     212    oldfile(false),           livetvchain(NULL),
     213    ignoreliveeof(false),     readAdjust(0)
     214{
     215    {
     216        QMutexLocker locker(&subExtLock);
     217        if (subExt.empty())
    512218        {
    513             baseName = tmpSubName.left(suffixPos);
    514             extension = tmpSubName.right(suffixPos-1);
    515             if (is_subtitle_possible(extension))
    516             {
    517                 QMutexLocker locker(&subExtLock);
    518                 QStringList::const_iterator eit = subExt.begin();
    519                 for (; eit != subExt.end(); eit++)
    520                     auxFiles += baseName + *eit;
    521             }
    522         }
     219            // Possible subtitle file extensions '.srt', '.sub', '.txt'
     220            subExt += ".srt";
     221            subExt += ".sub";
     222            subExt += ".txt";
    523223
    524         remotefile = new RemoteFile(filename, false, true,
    525                                     retry_ms, &auxFiles);
    526         if (!remotefile->isOpen())
    527         {
    528             VERBOSE(VB_IMPORTANT, LOC_ERR +
    529                     QString("RingBuffer::RingBuffer(): Failed to open remote "
    530                             "file (%1)").arg(filename));
    531             delete remotefile;
    532             remotefile = NULL;
     224            // Extensions for which a subtitle file should not exist
     225            subExtNoCheck = subExt;
     226            subExtNoCheck += ".gif";
     227            subExtNoCheck += ".png";
    533228        }
    534         else
    535         {
    536             QStringList aux = remotefile->GetAuxiliaryFiles();
    537             if (aux.size())
    538                 subtitlefilename = dirName + "/" + aux[0];
    539         }
    540229    }
    541 
    542     setswitchtonext = false;
    543     ateof = false;
    544     commserror = false;
    545     numfailures = 0;
    546 
    547     rawbitrate = 8000;
    548     CalcReadAheadThresh();
    549 
    550     rwlock.unlock();
    551230}
    552231
    553 /** \fn RingBuffer::IsOpen(void) const
    554  *  \brief Returns true if the file is open for either reading or writing.
    555  */
    556 bool RingBuffer::IsOpen(void) const
    557 {
    558     rwlock.lockForRead();
    559     bool ret;
    560 #ifdef USING_FRONTEND
    561     ret = tfw || (fd2 > -1) || remotefile || (dvdPriv && dvdPriv->IsOpen()) ||
    562            (bdPriv && bdPriv->IsOpen());
    563 #else // if !USING_FRONTEND
    564     ret = tfw || (fd2 > -1) || remotefile;
    565 #endif // !USING_FRONTEND
    566     rwlock.unlock();
    567     return ret;
    568 }
    569 
    570232/** \fn RingBuffer::~RingBuffer(void)
    571233 *  \brief Shuts down any threads and closes any files.
    572234 */
     
    574236{
    575237    KillReadAheadThread();
    576238
    577     rwlock.lockForWrite();
    578 
    579     if (remotefile)
    580     {
    581         delete remotefile;
    582         remotefile = NULL;
    583     }
    584 
    585     if (tfw)
    586     {
    587         delete tfw;
    588         tfw = NULL;
    589     }
    590 
    591     if (fd2 >= 0)
    592     {
    593         close(fd2);
    594         fd2 = -1;
    595     }
    596 
    597 #ifdef USING_FRONTEND
    598     if (dvdPriv)
    599     {
    600         delete dvdPriv;
    601     }
    602     if (bdPriv)
    603     {
    604         delete bdPriv;
    605     }
    606 #endif // USING_FRONTEND
    607 
    608239    if (readAheadBuffer) // this only runs if thread is terminated
    609240    {
    610241        delete [] readAheadBuffer;
     
    653284    rwlock.unlock();
    654285}
    655286
    656 /** \fn RingBuffer::safe_read(int, void*, uint)
    657  *  \brief Reads data from the file-descriptor.
    658  *
    659  *   This will re-read the file forever until the
    660  *   end-of-file is reached or the buffer is full.
    661  *
    662  *  \param fd   File descriptor to read from
    663  *  \param data Pointer to where data will be written
    664  *  \param sz   Number of bytes to read
    665  *  \return Returns number of bytes read
    666  */
    667 int RingBuffer::safe_read(int fd, void *data, uint sz)
    668 {
    669     int ret;
    670     unsigned tot = 0;
    671     unsigned errcnt = 0;
    672     unsigned zerocnt = 0;
    673 
    674     if (fd2 < 0)
    675     {
    676         VERBOSE(VB_IMPORTANT, LOC_ERR +
    677                 "Invalid file descriptor in 'safe_read()'");
    678         return 0;
    679     }
    680 
    681     if (stopreads)
    682         return 0;
    683 
    684     while (tot < sz)
    685     {
    686         ret = read(fd2, (char *)data + tot, sz - tot);
    687         if (ret < 0)
    688         {
    689             if (errno == EAGAIN)
    690                 continue;
    691 
    692             VERBOSE(VB_IMPORTANT,
    693                     LOC_ERR + "File I/O problem in 'safe_read()'" + ENO);
    694 
    695             errcnt++;
    696             numfailures++;
    697             if (errcnt == 3)
    698                 break;
    699         }
    700         else if (ret > 0)
    701         {
    702             tot += ret;
    703         }
    704 
    705         if (oldfile)
    706             break;
    707 
    708         if (ret == 0) // EOF returns 0
    709         {
    710             if (tot > 0)
    711                 break;
    712 
    713             zerocnt++;
    714 
    715             // 0.36 second timeout for livetvchain with usleep(60000),
    716             // or 2.4 seconds if it's a new file less than 30 minutes old.
    717             if (zerocnt >= (livetvchain ? 6 : 40))
    718             {
    719                 break;
    720             }
    721         }
    722         if (stopreads)
    723             break;
    724         if (tot < sz)
    725             usleep(60000);
    726     }
    727     return tot;
    728 }
    729 
    730 /** \fn RingBuffer::safe_read(RemoteFile*, void*, uint)
    731  *  \brief Reads data from the RemoteFile.
    732  *
    733  *  \param rf   RemoteFile to read from
    734  *  \param data Pointer to where data will be written
    735  *  \param sz   Number of bytes to read
    736  *  \return Returns number of bytes read
    737  */
    738 int RingBuffer::safe_read(RemoteFile *rf, void *data, uint sz)
    739 {
    740     int ret = rf->Read(data, sz);
    741     if (ret < 0)
    742     {
    743         VERBOSE(VB_IMPORTANT, LOC_ERR +
    744                 "RingBuffer::safe_read(RemoteFile* ...): read failed");
    745            
    746         poslock.lockForRead();
    747         rf->Seek(internalreadpos - readAdjust, SEEK_SET);
    748         poslock.unlock();
    749         numfailures++;
    750     }
    751     else if (ret == 0)
    752     {
    753         VERBOSE(VB_FILE, LOC +
    754                 "RingBuffer::safe_read(RemoteFile* ...): at EOF");
    755     }
    756 
    757     return ret;
    758 }
    759 
    760287/** \fn RingBuffer::UpdateRawBitrate(uint)
    761288 *  \brief Set the raw bit rate, to allow RingBuffer adjust effective bitrate.
    762289 *  \param raw_bitrate Streams average number of kilobits per second when
     
    1228755                        "Reading enough data to start playback");
    1229756            }
    1230757
     758            if (remotefile && livetvchain && livetvchain->HasNext())
     759                remotefile->SetTimeout(true);
     760
    1231761            VERBOSE(VB_FILE|VB_EXTRA,
    1232762                    LOC + QString("safe_read(...@%1, %2) -- begin")
    1233763                    .arg(rbwpos).arg(totfree));
    1234             if (remotefile)
    1235             {
    1236                 if (livetvchain && livetvchain->HasNext())
    1237                     remotefile->SetTimeout(true);
    1238                 read_return = safe_read(
    1239                     remotefile, readAheadBuffer + rbwpos, totfree);
    1240             }
    1241 #ifdef USING_FRONTEND
    1242             else if (dvdPriv)
    1243             {
    1244                 read_return = dvdPriv->safe_read(
    1245                     readAheadBuffer + rbwpos, totfree);
    1246             }
    1247             else if (bdPriv)
    1248             {
    1249                 read_return = bdPriv->safe_read(
    1250                     readAheadBuffer + rbwpos, totfree);
    1251             }
    1252 #endif // USING_FRONTEND
    1253             else
    1254             {
    1255                 read_return = safe_read(fd2, readAheadBuffer + rbwpos, totfree);
    1256             }
     764
     765            read_return = safe_read(readAheadBuffer + rbwpos, totfree);
     766
    1257767            VERBOSE(VB_FILE|VB_EXTRA, LOC +
    1258768                    QString("safe_read(...@%1, %2) -> %3")
    1259769                    .arg(rbwpos).arg(totfree).arg(read_return));
     770
    1260771            rbwlock.unlock();
    1261772        }
    1262773
     
    1485996        poslock.unlock();
    1486997    }
    1487998
    1488     int ret;
    1489     if (remotefile)
    1490         ret = safe_read(remotefile, buf, count);
    1491 #ifdef USING_FRONTEND
    1492     else if (dvdPriv)
    1493         ret = dvdPriv->safe_read(buf, count);
    1494     else if (bdPriv)
    1495         ret = bdPriv->safe_read(buf, count);
    1496 #endif // USING_FRONTEND
    1497     else if (fd2 >= 0)
    1498         ret = safe_read(fd2, buf, count);
    1499     else
    1500     {
    1501         ret = -1;
    1502         errno = EBADF;
    1503     }
     999    int ret = safe_read(buf, count);
    15041000
    15051001    poslock.lockForWrite();
    15061002    if (ignorereadpos >= 0 && ret > 0)
     
    15271023
    15281024    if (peek && ret > 0)
    15291025    {
    1530         if (!dvdPriv && !bdPriv)
     1026        if ((IsDVD() || IsBD()) && old_pos != 0)
    15311027        {
    1532             long long new_pos = Seek(old_pos, SEEK_SET, true);
    1533             if (new_pos != old_pos)
    1534             {
    1535                 VERBOSE(VB_IMPORTANT, LOC_ERR +
    1536                         QString("Peek() Failed to return from new "
    1537                                 "position %1 to old position %2, now "
    1538                                 "at position %3")
    1539                         .arg(old_pos - ret).arg(old_pos).arg(new_pos));
    1540             }
    1541         }
    1542         else if (old_pos != 0)
    1543         {
    15441028            VERBOSE(VB_IMPORTANT, LOC_ERR +
    15451029                    "DVD and Blu-Ray do not support arbitrary "
    15461030                    "peeks except when read-ahead is enabled."
    15471031                    "\n\t\t\tWill seek to beginning of video.");
     1032            old_pos = 0;
    15481033        }
    1549 #ifdef USING_FRONTEND
    1550         if (dvdPriv)
    1551             dvdPriv->NormalSeek(old_pos);
    1552         else if (bdPriv)
    1553             bdPriv->Seek(old_pos);
    1554 #endif // USING_FRONTEND
     1034
     1035        long long new_pos = Seek(old_pos, SEEK_SET, true);
     1036
     1037        if (new_pos != old_pos)
     1038        {
     1039            VERBOSE(VB_IMPORTANT, LOC_ERR +
     1040                    QString("Peek() Failed to return from new "
     1041                            "position %1 to old position %2, now "
     1042                            "at position %3")
     1043                    .arg(old_pos - ret).arg(old_pos).arg(new_pos));
     1044        }
    15551045    }
    15561046
    15571047    return ret;
     
    17771267    rwlock.unlock();
    17781268}
    17791269
    1780 /** \brief Seeks to a particular position in the file.
    1781  */
    1782 long long RingBuffer::Seek(long long pos, int whence, bool has_lock)
    1783 {
    1784     VERBOSE(VB_FILE, LOC + QString("Seek(%1,%2,%3)")
    1785             .arg(pos).arg((SEEK_SET==whence)?"SEEK_SET":
    1786                           ((SEEK_CUR==whence)?"SEEK_CUR":"SEEK_END"))
    1787             .arg(has_lock?"locked":"unlocked"));
    1788 
    1789     long long ret = -1;
    1790 
    1791     StopReads();
    1792 
    1793     // lockForWrite takes priority over lockForRead, so this will
    1794     // take priority over the lockForRead in the read ahead thread.
    1795     if (!has_lock)
    1796         rwlock.lockForWrite();
    1797 
    1798     StartReads();
    1799 
    1800     if (writemode)
    1801     {
    1802         ret = WriterSeek(pos, whence, true);
    1803         if (!has_lock)
    1804             rwlock.unlock();
    1805         return ret;
    1806     }
    1807 
    1808     poslock.lockForWrite();
    1809 
    1810     // Optimize no-op seeks
    1811     if (readaheadrunning &&
    1812         ((whence == SEEK_SET && pos == readpos) ||
    1813          (whence == SEEK_CUR && pos == 0)))
    1814     {
    1815         ret = readpos;
    1816 
    1817         poslock.unlock();
    1818         if (!has_lock)
    1819             rwlock.unlock();
    1820 
    1821         return ret;
    1822     }
    1823 
    1824     // only valid for SEEK_SET & SEEK_CUR
    1825     long long new_pos = (SEEK_SET==whence) ? pos : readpos + pos;
    1826 
    1827 #if 1
    1828     // Optimize short seeks where the data for
    1829     // them is in our ringbuffer already.
    1830     if (readaheadrunning &&
    1831         (SEEK_SET==whence || SEEK_CUR==whence))
    1832     {
    1833         rbrlock.lockForWrite();
    1834         rbwlock.lockForRead();
    1835         VERBOSE(VB_FILE, LOC +
    1836                 QString("Seek(): rbrpos: %1 rbwpos: %2"
    1837                         "\n\t\t\treadpos: %3 internalreadpos: %4")
    1838                 .arg(rbrpos).arg(rbwpos)
    1839                 .arg(readpos).arg(internalreadpos));
    1840         bool used_opt = false;
    1841         if ((new_pos < readpos))
    1842         {
    1843             int min_safety = max(fill_min, readblocksize);
    1844             int free = ((rbwpos >= rbrpos) ?
    1845                         rbrpos + kBufferSize : rbrpos) - rbwpos;
    1846             int internal_backbuf =
    1847                 (rbwpos >= rbrpos) ? rbrpos : rbrpos - rbwpos;
    1848             internal_backbuf = min(internal_backbuf, free - min_safety);
    1849             long long sba = readpos - new_pos;
    1850             VERBOSE(VB_FILE, LOC +
    1851                     QString("Seek(): internal_backbuf: %1 sba: %2")
    1852                     .arg(internal_backbuf).arg(sba));
    1853             if (internal_backbuf >= sba)
    1854             {
    1855                 rbrpos = (rbrpos>=sba) ? rbrpos - sba :
    1856                     kBufferSize + rbrpos - sba;
    1857                 used_opt = true;
    1858                 VERBOSE(VB_FILE, LOC +
    1859                         QString("Seek(): OPT1 rbrpos: %1 rbwpos: %2"
    1860                                 "\n\t\t\treadpos: %3 internalreadpos: %4")
    1861                         .arg(rbrpos).arg(rbwpos)
    1862                         .arg(new_pos).arg(internalreadpos));
    1863             }
    1864         }
    1865         else if ((new_pos >= readpos) && (new_pos <= internalreadpos))
    1866         {
    1867             rbrpos = (rbrpos + (new_pos - readpos)) % kBufferSize;
    1868             used_opt = true;
    1869             VERBOSE(VB_FILE, LOC +
    1870                     QString("Seek(): OPT2 rbrpos: %1 sba: %2")
    1871                     .arg(rbrpos).arg(readpos - new_pos));
    1872         }
    1873         rbwlock.unlock();
    1874         rbrlock.unlock();
    1875 
    1876         if (used_opt)
    1877         {
    1878             if (ignorereadpos >= 0)
    1879             {
    1880                 // seek should always succeed since we were at this position
    1881                 int ret;
    1882                 if (remotefile)
    1883                     ret = remotefile->Seek(internalreadpos, SEEK_SET);
    1884                 else
    1885                 {
    1886                     ret = lseek64(fd2, internalreadpos, SEEK_SET);
    1887                     posix_fadvise(fd2, 0,
    1888                                   internalreadpos, POSIX_FADV_DONTNEED);
    1889                     posix_fadvise(fd2, internalreadpos,
    1890                                   1*1024*1024, POSIX_FADV_WILLNEED);
    1891                 }
    1892                 VERBOSE(VB_FILE, LOC +
    1893                         QString("Seek to %1 from ignore pos %2 returned %3")
    1894                         .arg(internalreadpos).arg(ignorereadpos).arg(ret));
    1895                 ignorereadpos = -1;
    1896             }
    1897             readpos = new_pos;
    1898             poslock.unlock();
    1899             generalWait.wakeAll();
    1900             ateof = false;
    1901             readsallowed = false;
    1902             if (!has_lock)
    1903                 rwlock.unlock();
    1904             return new_pos;
    1905         }
    1906     }
    1907 #endif
    1908 
    1909 #if 1
    1910     // This optimizes the seek end-250000, read, seek 0, read portion
    1911     // of the pattern ffmpeg performs at the start of playback to
    1912     // determine the pts.
    1913     // If the seek is a SEEK_END or is a seek where the position
    1914     // changes over 100 MB we check the file size and if the
    1915     // destination point is within 300000 bytes of the end of
    1916     // the file we enter a special mode where the read ahead
    1917     // buffer stops reading data and all reads are made directly
    1918     // until another seek is performed. The point of all this is
    1919     // to avoid flushing out the buffer that still contains all
    1920     // the data the final seek 0, read will need just to read the
    1921     // last 250000 bytes. A further optimization would be to buffer
    1922     // the 250000 byte read, which is currently performed in 32KB
    1923     // blocks (inefficient with RemoteFile).
    1924     if ((remotefile || fd2 >= 0) && (ignorereadpos < 0))
    1925     {
    1926         long long off_end = 0xDEADBEEF;
    1927         if (SEEK_END == whence)
    1928         {
    1929             off_end = pos;
    1930             if (remotefile)
    1931             {
    1932                 new_pos = remotefile->GetFileSize() - off_end;
    1933             }
    1934             else
    1935             {
    1936                 QFileInfo fi(filename);
    1937                 new_pos = fi.size() - off_end;
    1938             }
    1939         }
    1940         else
    1941         {
    1942             if (remotefile)
    1943             {
    1944                 off_end = remotefile->GetFileSize() - new_pos;
    1945             }
    1946             else
    1947             {
    1948                 QFileInfo fi(filename);
    1949                 off_end = fi.size() - new_pos;
    1950             }
    1951         }
    1952 
    1953         if (off_end != 0xDEADBEEF)
    1954         {
    1955             VERBOSE(VB_FILE, LOC +
    1956                     QString("Seek(): Offset from end: %1").arg(off_end));
    1957         }
    1958 
    1959         if (off_end <= 250000)
    1960         {
    1961             VERBOSE(VB_FILE, LOC +
    1962                     QString("Seek(): offset from end: %1").arg(off_end) +
    1963                     "\n\t\t\t -- ignoring read ahead thread until next seek.");
    1964 
    1965             ignorereadpos = new_pos;
    1966             errno = EINVAL;
    1967             long long ret;
    1968             if (remotefile)
    1969                 ret = remotefile->Seek(ignorereadpos, SEEK_SET);
    1970             else
    1971             {
    1972                 ret = lseek64(fd2, ignorereadpos, SEEK_SET);
    1973                 posix_fadvise(fd2, ignorereadpos, 250000, POSIX_FADV_WILLNEED);
    1974             }
    1975 
    1976             if (ret < 0)
    1977             {
    1978                 int tmp_eno = errno;
    1979                 QString cmd = QString("Seek(%1, SEEK_SET) ign ")
    1980                     .arg(ignorereadpos);
    1981 
    1982                 ignorereadpos = -1;
    1983 
    1984                 VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
    1985 
    1986                 // try to return to former position..
    1987                 if (remotefile)
    1988                     ret = remotefile->Seek(internalreadpos, SEEK_SET);
    1989                 else
    1990                     ret = lseek64(fd2, internalreadpos, SEEK_SET);
    1991                 if (ret < 0)
    1992                 {
    1993                     QString cmd = QString("Seek(%1, SEEK_SET) int ")
    1994                         .arg(internalreadpos);
    1995                     VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
    1996                 }
    1997                 else
    1998                 {
    1999                     QString cmd = QString("Seek(%1, %2) int ")
    2000                         .arg(internalreadpos)
    2001                         .arg((SEEK_SET == whence) ? "SEEK_SET" :
    2002                              ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
    2003                     VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " succeeded");
    2004                 }
    2005                 ret = -1;
    2006                 errno = tmp_eno;
    2007             }
    2008             else
    2009             {
    2010                 ateof = false;
    2011                 readsallowed = false;
    2012             }
    2013 
    2014             rbwlock.unlock();
    2015             rbrlock.unlock();
    2016             poslock.unlock();
    2017 
    2018             generalWait.wakeAll();
    2019 
    2020             if (!has_lock)
    2021                 rwlock.unlock();
    2022 
    2023             return ret;
    2024         }
    2025     }
    2026 #endif
    2027 
    2028     // Here we perform a normal seek. When successful we
    2029     // need to call ResetReadAhead(). A reset means we will
    2030     // need to refill the buffer, which takes some time.
    2031     if (remotefile)
    2032     {
    2033         ret = remotefile->Seek(pos, whence, readpos);
    2034         if (ret<0)
    2035             errno = EINVAL;
    2036     }
    2037 #ifdef USING_FRONTEND
    2038     else if ((dvdPriv || bdPriv) && (SEEK_END == whence))
    2039     {
    2040         errno = EINVAL;
    2041         ret = -1;
    2042     }
    2043     else if (dvdPriv)
    2044     {
    2045         dvdPriv->NormalSeek(new_pos);
    2046         ret = new_pos;
    2047     }
    2048     else if (bdPriv)
    2049     {
    2050         bdPriv->Seek(new_pos);
    2051         ret = new_pos;
    2052     }
    2053 #endif // USING_FRONTEND
    2054     else
    2055     {
    2056         ret = lseek64(fd2, pos, whence);
    2057         if (ret >= 0)
    2058         {
    2059             posix_fadvise(fd2, 0,   ret,         POSIX_FADV_DONTNEED);
    2060             posix_fadvise(fd2, ret, 1*1024*1024, POSIX_FADV_WILLNEED);
    2061         }
    2062     }
    2063 
    2064     if (ret >= 0)
    2065     {
    2066         readpos = ret;
    2067        
    2068         ignorereadpos = -1;
    2069 
    2070         if (readaheadrunning)
    2071             ResetReadAhead(readpos);
    2072 
    2073         readAdjust = 0;
    2074     }
    2075     else
    2076     {
    2077         QString cmd = QString("Seek(%1, %2)").arg(pos)
    2078             .arg((SEEK_SET == whence) ? "SEEK_SET" :
    2079                  ((SEEK_CUR == whence) ?"SEEK_CUR" : "SEEK_END"));
    2080         VERBOSE(VB_IMPORTANT, LOC_ERR + cmd + " Failed" + ENO);
    2081     }
    2082 
    2083     poslock.unlock();
    2084 
    2085     generalWait.wakeAll();
    2086 
    2087     if (!has_lock)
    2088         rwlock.unlock();
    2089 
    2090     return ret;
    2091 }
    2092 
    20931270/** \brief Calls ThreadedFileWriter::Seek(long long,int).
    20941271 */
    20951272long long RingBuffer::WriterSeek(long long pos, int whence, bool has_lock)
     
    21741351    rwlock.unlock();
    21751352}
    21761353
    2177 // This appears to allow direct access to the DVD/BD device
    2178 // when called with false (the default value), and enable
    2179 // the ring buffer when called with true. But I'm not entirely
    2180 // certain. -- dtk 2010-08-26
    2181 void RingBuffer::SetStreamOnly(bool stream)
    2182 {
    2183     rwlock.lockForWrite();
    2184     streamOnly = stream;
    2185     rwlock.unlock();
    2186 }
    2187 
    21881354/// Returns name of file used by this RingBuffer
    21891355QString RingBuffer::GetFilename(void) const
    21901356{
    21911357    rwlock.lockForRead();
    21921358    QString tmp = filename;
    2193     tmp.detach();
    21941359    rwlock.unlock();
    21951360    return tmp;
    21961361}
     
    21991364{
    22001365    rwlock.lockForRead();
    22011366    QString tmp = subtitlefilename;
    2202     tmp.detach();
    22031367    rwlock.unlock();
    22041368    return tmp;
    22051369}
    22061370
    2207 /** \fn RingBuffer::GetReadPosition(void) const
    2208  *  \brief Returns how far into the file we have read.
    2209  */
    2210 long long RingBuffer::GetReadPosition(void) const
    2211 {
    2212     rwlock.lockForRead();
    2213     poslock.lockForRead();
    2214     long long ret = readpos;
    2215 #ifdef USING_FRONTEND
    2216     if (dvdPriv)
    2217         ret = dvdPriv->GetReadPosition();
    2218     else if (bdPriv)
    2219         ret = bdPriv->GetReadPosition();
    2220 #endif // USING_FRONTEND
    2221     poslock.unlock();
    2222     rwlock.unlock();
    2223     return ret;
    2224 }
    2225 
    22261371/** \fn RingBuffer::GetWritePosition(void) const
    22271372 *  \brief Returns how far into a ThreadedFileWriter file we have written.
    22281373 */
     
    22341379    return ret;
    22351380}
    22361381
    2237 /** \fn RingBuffer::GetRealFileSize(void) const
    2238  *  \brief Returns the size of the file we are reading/writing,
    2239  *         or -1 if the query fails.
    2240  */
    2241 long long RingBuffer::GetRealFileSize(void) const
    2242 {
    2243     rwlock.lockForRead();
    2244     long long ret = -1;
    2245     if (remotefile)
    2246         ret = remotefile->GetFileSize();
    2247     else
    2248         ret = QFileInfo(filename).size();
    2249     rwlock.unlock();
    2250     return ret;
    2251 }
    2252 
    22531382/** \fn RingBuffer::LiveMode(void) const
    22541383 *  \brief Returns true if this RingBuffer has been assigned a LiveTVChain.
    22551384 *  \sa SetLiveMode(LiveTVChain*)
     
    22811410    rwlock.unlock();
    22821411}
    22831412
    2284 /** \brief Returns true if this is a DVD backed RingBuffer.
    2285  *
    2286  * NOTE: This is not locked because ReadDirect calls
    2287  * DVD safe_read which sleeps with a write lock on
    2288  * rwlock in the DVDNAV_WAIT condition.
    2289  *
    2290  * Due to the lack of locking is only safe to call once OpenFile()
    2291  * has completed.
    2292  */
    2293 bool RingBuffer::IsDVD(void) const
     1413const DVDRingBuffer *RingBuffer::DVD(void) const
    22941414{
    2295     //rwlock.lockForRead();
    2296     bool ret = dvdPriv;
    2297     //rwlock.unlock();
    2298     return ret;
     1415    return dynamic_cast<const DVDRingBuffer*>(this);
    22991416}
    23001417
    2301 /** \brief Returns true if this is a DVD backed RingBuffer.
    2302  *
    2303  * NOTE: This is not locked because ReadDirect calls
    2304  * DVD safe_read which sleeps with a write lock on
    2305  * rwlock in the DVDNAV_WAIT condition.
    2306  *
    2307  * Due to the lack of locking is only safe to call once OpenFile()
    2308  * has completed.
    2309  */
    2310 bool RingBuffer::InDiscMenuOrStillFrame(void)
     1418const BDRingBuffer  *RingBuffer::BD(void) const
    23111419{
    2312     //rwlock.lockForRead();
    2313     bool ret = false;
    2314 #ifdef USING_FRONTEND
    2315     if (dvdPriv)
    2316         ret = (dvdPriv->IsInMenu() || dvdPriv->InStillFrame());
    2317     else if (bdPriv)
    2318         ret = (bdPriv->IsInMenu() || bdPriv->InStillFrame());
    2319 #endif // USING_FRONTEND
    2320     //rwlock.unlock();
    2321     return ret;
     1420    return dynamic_cast<const BDRingBuffer*>(this);
    23221421}
    23231422
    2324 /// Returns true if this is a Blu-ray backed RingBuffer.
    2325 bool RingBuffer::IsBD(void) const
     1423DVDRingBuffer *RingBuffer::DVD(void)
    23261424{
    2327     //rwlock.lockForRead();
    2328     bool ret = bdPriv;
    2329     //rwlock.unlock();
    2330     return ret;
     1425    return dynamic_cast<DVDRingBuffer*>(this);
    23311426}
    23321427
     1428BDRingBuffer  *RingBuffer::BD(void)
     1429{
     1430    return dynamic_cast<BDRingBuffer*>(this);
     1431}
     1432
    23331433/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/DVDRingBuffer.h

     
    1010#include <QMutex>
    1111#include <QRect>
    1212
     13#include "RingBuffer.h"
    1314#include "util.h"
     15
    1416extern "C" {
    1517#include "libavcodec/avcodec.h"
    1618}
     
    2527
    2628class MythDVDPlayer;
    2729
    28 class MPUBLIC DVDRingBufferPriv
     30class MPUBLIC DVDRingBuffer : public RingBuffer
    2931{
    3032  public:
    31     DVDRingBufferPriv();
    32     virtual ~DVDRingBufferPriv();
     33    DVDRingBuffer(const QString &lfilename);
     34    virtual ~DVDRingBuffer();
    3335
    3436    // gets
    3537    int  GetTitle(void) const { return m_title;        }
     
    3840    int  GetCurrentAngle(void) const { return m_currentAngle;           };
    3941    int  GetNumAngles(void)          { return m_currentTitleAngleCount; };
    4042    bool IsOpen(void)   const { return m_dvdnav;       }
    41     long long GetReadPosition(void);
     43    virtual long long GetReadPosition(void) const;
    4244    long long GetTotalReadPosition(void) { return m_titleLength; }
    4345    void GetDescForPos(QString &desc);
    4446    void GetPartAndTitle(int &_part, int &_title) const
     
    4850    uint GetCellStart(void);
    4951    bool PGCLengthChanged(void);
    5052    bool CellChanged(void);
    51     bool InStillFrame(void) const { return m_still > 0; }
    52     bool NeedsStillFrame(void) { return InStillFrame() || NewSequence(); }
     53    bool IsInStillFrame(void) const { return m_still > 0; }
     54    bool NeedsStillFrame(void) { return IsInStillFrame() || NewSequence(); }
    5355    bool NewSequence(bool new_sequence = false);
    5456    bool AudioStreamsChanged(void) const { return m_audioStreamsChanged; }
    5557    bool IsWaiting(void) const { return m_dvdWaiting; }
    5658    int  NumPartsInTitle(void) const { return m_titleParts; }
    5759    void GetMenuSPUPkt(uint8_t *buf, int len, int stream_id);
     60    virtual bool IsInDiscMenuOrStillFrame(void) const
     61        { return IsInMenu() || IsInStillFrame(); } // RingBuffer
    5862
    5963    // Public menu/button stuff
    6064    AVSubtitle *GetMenuSubtitle(uint &version);
    6165    int         NumMenuButtons(void) const;
    6266    QRect       GetButtonCoords(void);
    6367    void        ReleaseMenuButton(void);
    64     bool        IsInMenu(void) { return m_inMenu; }
     68    bool        IsInMenu(void) const { return m_inMenu; }
    6569    void        ActivateButton(void);
    6670    void        MoveButtonLeft(void);
    6771    void        MoveButtonRight(void);
     
    8589                                        (m_titleParts == 1)); }
    8690
    8791    // commands
    88     bool OpenFile(const QString &filename);
     92    virtual bool OpenFile(const QString &lfilename,
     93                          uint retry_ms = kDefaultOpenTimeout); // RingBuffer
    8994    void PlayTitleAndPart(int _title, int _part)
    9095        { dvdnav_part_play(m_dvdnav, _title, _part); }
    9196    bool StartFromBeginning(void);
    9297    void CloseDVD(void);
    9398    bool nextTrack(void);
    9499    void prevTrack(void);
    95     int  safe_read(void *data, unsigned sz);
     100    virtual int safe_read(void *data, uint sz); // RingBuffer
     101    virtual long long Seek(long long pos, int whence, bool has_lock);
    96102    long long NormalSeek(long long time);
    97103    void SkipStillFrame(void);
    98104    void WaitSkip(void);
     
    118124    dvdnav_t      *m_dvdnav;
    119125    unsigned char  m_dvdBlockWriteBuf[DVD_BLOCK_SIZE];
    120126    unsigned char *m_dvdBlockReadBuf;
    121     QString        m_dvdFilename;
    122127    int            m_dvdBlockRPos;
    123128    int            m_dvdBlockWPos;
    124129    long long      m_pgLength;
  • libs/libmythtv/tv_play.cpp

     
    20382038                                          "cardtype(%2)")
    20392039                    .arg(playbackURL).arg(ctx->tvchain->GetCardType(-1)));
    20402040
    2041             ctx->SetRingBuffer(new RingBuffer(playbackURL, false, true,
    2042                                opennow ? RingBuffer::kLiveTVOpenTimeout : -1));
     2041            ctx->SetRingBuffer(
     2042                RingBuffer::Create(
     2043                    playbackURL, false, true,
     2044                    opennow ? RingBuffer::kLiveTVOpenTimeout : -1));
     2045
    20432046            ctx->buffer->SetLiveMode(ctx->tvchain);
    20442047        }
    20452048
     
    21132116        }
    21142117        ctx->UnlockPlayingInfo(__FILE__, __LINE__);
    21152118
    2116         ctx->SetRingBuffer(new RingBuffer(playbackURL, false));
     2119        ctx->SetRingBuffer(RingBuffer::Create(playbackURL, false));
    21172120
    21182121        if (ctx->buffer && ctx->buffer->IsOpen())
    21192122        {
     
    22392242            ITVRestart(ctx, false);
    22402243        }
    22412244
    2242         if (ctx->buffer && ctx->buffer->isDVD())
     2245        if (ctx->buffer && ctx->buffer->IsDVD())
    22432246        {
    22442247            UpdateLCD();
    22452248        }
     
    23672370
    23682371    SetActive(mctx, 0, false);
    23692372
    2370     if (ctx->buffer && ctx->buffer->isDVD())
     2373    if (ctx->buffer && ctx->buffer->IsDVD())
    23712374    {
    23722375        VERBOSE(VB_PLAYBACK,LOC + " StopStuff() -- "
    23732376                "get dvd player out of still frame or wait status");
     
    30623065        if (StateIsLiveTV(GetState(actx)))
    30633066            ShowLCDChannelInfo(actx);
    30643067
    3065         if (actx->buffer && actx->buffer->isDVD())
     3068        if (actx->buffer && actx->buffer->IsDVD())
    30663069        {
    30673070            ShowLCDDVDInfo(actx);
    3068             showProgress = !actx->buffer->InDiscMenuOrStillFrame();
     3071            showProgress = !actx->buffer->IsInDiscMenuOrStillFrame();
    30693072        }
    30703073
    30713074        if (showProgress)
     
    37353738
    37363739    handled = false;
    37373740
    3738     bool isDVD = actx->buffer && actx->buffer->isDVD();
    3739     bool isDVDStill = isDVD && actx->buffer->InDiscMenuOrStillFrame();
    3740     bool isBD = actx->buffer && actx->buffer->isBD();
    3741     bool isBDStill = isBD && actx->buffer->InDiscMenuOrStillFrame();
     3741    bool isDVD = actx->buffer && actx->buffer->IsDVD();
     3742    bool isMenuOrStill = actx->buffer->IsInDiscMenuOrStillFrame();
    37423743
    37433744    handled = handled || BrowseHandleAction(actx, actions);
    37443745    handled = handled || ManualZoomHandleAction(actx, actions);
    37453746    handled = handled || PictureAttributeHandleAction(actx, actions);
    37463747    handled = handled || TimeStretchHandleAction(actx, actions);
    37473748    handled = handled || AudioSyncHandleAction(actx, actions);
    3748     handled = handled || DiscMenuHandleAction(actx, actions, isDVD, isDVDStill, isBD);
    3749     handled = handled || ActiveHandleAction(actx, actions, isDVD, isDVDStill);
     3749    handled = handled || DiscMenuHandleAction(actx, actions);
     3750    handled = handled || ActiveHandleAction(
     3751        actx, actions, isDVD, isMenuOrStill);
    37503752    handled = handled || ToggleHandleAction(actx, actions, isDVD);
    37513753    handled = handled || PxPHandleAction(actx, actions);
    37523754    handled = handled || FFRewHandleAction(actx, actions);
     
    39723974    return handled;
    39733975}
    39743976
    3975 bool TV::DiscMenuHandleAction(PlayerContext *ctx,
    3976                              const QStringList &actions,
    3977                              bool isDVD, bool isDVDStill,
    3978                              bool isBD)
     3977bool TV::DiscMenuHandleAction(PlayerContext *ctx, const QStringList &actions)
    39793978{
    39803979    bool handled = false;
     3980    DVDRingBuffer *dvdrb = ctx->buffer->DVD();
     3981    BDRingBuffer  *bdrb  = ctx->buffer->BD();
    39813982
    3982     if (isDVD)
     3983    if (dvdrb)
    39833984    {
    3984         int nb_buttons = ctx->buffer->DVD()->NumMenuButtons();
     3985        int nb_buttons = dvdrb->NumMenuButtons();
    39853986        if (nb_buttons == 0)
    39863987            return false;
    39873988
     
    39893990        if (has_action("UP", actions) ||
    39903991            has_action("CHANNELUP", actions))
    39913992        {
    3992             ctx->buffer->DVD()->MoveButtonUp();
     3993            dvdrb->MoveButtonUp();
    39933994        }
    39943995        else if (has_action("DOWN", actions) ||
    39953996                 has_action("CHANNELDOWN", actions))
    39963997        {
    3997             ctx->buffer->DVD()->MoveButtonDown();
     3998            dvdrb->MoveButtonDown();
    39983999        }
    39994000        else if (has_action("LEFT", actions) ||
    40004001                 has_action("SEEKRWND", actions))
    40014002        {
    4002             ctx->buffer->DVD()->MoveButtonLeft();
     4003            dvdrb->MoveButtonLeft();
    40034004        }
    40044005        else if (has_action("RIGHT", actions) ||
    40054006                 has_action("SEEKFFWD", actions))
    40064007        {
    4007             ctx->buffer->DVD()->MoveButtonRight();
     4008            dvdrb->MoveButtonRight();
    40084009        }
    40094010        else if (has_action("SELECT", actions))
    40104011        {
    40114012            ctx->LockDeletePlayer(__FILE__, __LINE__);
    4012             ctx->buffer->DVD()->ActivateButton();
     4013            dvdrb->ActivateButton();
    40134014            ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    40144015        }
    40154016        else
    40164017            handled = false;
    40174018    }
    4018     if (isBD)
     4019    else if (bdrb)
    40194020    {
    40204021        int64_t pts = 0;
    40214022        VideoOutput *output = ctx->player->getVideoOutput();
     
    40334034        if (has_action("UP", actions) ||
    40344035            has_action("CHANNELUP", actions))
    40354036        {
    4036             ctx->buffer->BD()->PressButton(BD_VK_UP, pts);
     4037            bdrb->PressButton(BD_VK_UP, pts);
    40374038        }
    40384039        else if (has_action("DOWN", actions) ||
    40394040                 has_action("CHANNELDOWN", actions))
    40404041        {
    4041             ctx->buffer->BD()->PressButton(BD_VK_DOWN, pts);
     4042            bdrb->PressButton(BD_VK_DOWN, pts);
    40424043        }
    40434044        else if (has_action("LEFT", actions) ||
    40444045                 has_action("SEEKRWND", actions))
    40454046        {
    4046             ctx->buffer->BD()->PressButton(BD_VK_LEFT, pts);
     4047            bdrb->PressButton(BD_VK_LEFT, pts);
    40474048        }
    40484049        else if (has_action("RIGHT", actions) ||
    40494050                 has_action("SEEKFFWD", actions))
    40504051        {
    4051             ctx->buffer->BD()->PressButton(BD_VK_RIGHT, pts);
     4052            bdrb->PressButton(BD_VK_RIGHT, pts);
    40524053        }
    40534054        else if (has_action("MENUTEXT", actions))
    40544055        {
    4055             ctx->buffer->BD()->PressButton(BD_VK_POPUP, pts);
     4056            bdrb->PressButton(BD_VK_POPUP, pts);
    40564057        }
    40574058        else if (has_action("0", actions))
    40584059        {
    4059             ctx->buffer->BD()->PressButton(BD_VK_0, pts);
     4060            bdrb->PressButton(BD_VK_0, pts);
    40604061        }
    40614062        else if (has_action("1", actions))
    40624063        {
    4063             ctx->buffer->BD()->PressButton(BD_VK_1, pts);
     4064            bdrb->PressButton(BD_VK_1, pts);
    40644065        }
    40654066        else if (has_action("2", actions))
    40664067        {
    4067             ctx->buffer->BD()->PressButton(BD_VK_2, pts);
     4068            bdrb->PressButton(BD_VK_2, pts);
    40684069        }
    40694070        else if (has_action("3", actions))
    40704071        {
    4071             ctx->buffer->BD()->PressButton(BD_VK_3, pts);
     4072            bdrb->PressButton(BD_VK_3, pts);
    40724073        }
    40734074        else if (has_action("4", actions))
    40744075        {
    4075             ctx->buffer->BD()->PressButton(BD_VK_4, pts);
     4076            bdrb->PressButton(BD_VK_4, pts);
    40764077        }
    40774078        else if (has_action("5", actions))
    40784079        {
    4079             ctx->buffer->BD()->PressButton(BD_VK_5, pts);
     4080            bdrb->PressButton(BD_VK_5, pts);
    40804081        }
    40814082        else if (has_action("6", actions))
    40824083        {
    4083             ctx->buffer->BD()->PressButton(BD_VK_6, pts);
     4084            bdrb->PressButton(BD_VK_6, pts);
    40844085        }
    40854086        else if (has_action("7", actions))
    40864087        {
    4087             ctx->buffer->BD()->PressButton(BD_VK_7, pts);
     4088            bdrb->PressButton(BD_VK_7, pts);
    40884089        }
    40894090        else if (has_action("8", actions))
    40904091        {
    4091             ctx->buffer->BD()->PressButton(BD_VK_8, pts);
     4092            bdrb->PressButton(BD_VK_8, pts);
    40924093        }
    40934094        else if (has_action("9", actions))
    40944095        {
    4095             ctx->buffer->BD()->PressButton(BD_VK_9, pts);
     4096            bdrb->PressButton(BD_VK_9, pts);
    40964097        }
    40974098        else if (has_action("SELECT", actions))
    40984099        {
    4099             ctx->buffer->BD()->PressButton(BD_VK_ENTER, pts);
     4100            bdrb->PressButton(BD_VK_ENTER, pts);
    41004101        }
    41014102        else
    41024103            handled = false;
     
    48144815    }
    48154816    else if (tokens.size() >= 3 && tokens[1] == "SEEK" && ctx->HasPlayer())
    48164817    {
    4817         if (ctx->buffer && ctx->buffer->InDiscMenuOrStillFrame())
     4818        if (ctx->buffer && ctx->buffer->IsInDiscMenuOrStillFrame())
    48184819            return;
    48194820
    48204821        ctx->LockDeletePlayer(__FILE__, __LINE__);
     
    49294930            }
    49304931            else
    49314932            {
    4932                 if (ctx->buffer->isDVD())
     4933                if (ctx->buffer->IsDVD())
    49334934                    infoStr = "DVD";
    49344935                else if (ctx->playingInfo->IsRecording())
    49354936                    infoStr = "Recorded";
     
    57535754    if (!ctx)
    57545755        return 0.0f;
    57555756
    5756     if (ctx->buffer && ctx->buffer->InDiscMenuOrStillFrame())
     5757    if (ctx->buffer && ctx->buffer->IsInDiscMenuOrStillFrame())
    57575758        return 0.0f;
    57585759
    57595760    ctx->ff_rew_speed = 0;
     
    57925793    if (!ctx || !ctx->HasPlayer())
    57935794        return;
    57945795
    5795     if (ctx->buffer && ctx->buffer->InDiscMenuOrStillFrame())
     5796    if (ctx->buffer && ctx->buffer->IsInDiscMenuOrStillFrame())
    57965797        return;
    57975798
    57985799    if (ctx->paused)
     
    65856586            ctx->LockPlayingInfo(__FILE__, __LINE__);
    65866587            QString playbackURL = ctx->playingInfo->GetPlaybackURL(true);
    65876588            bool opennow = (ctx->tvchain->GetCardType(-1) != "DUMMY");
    6588             ctx->SetRingBuffer(new RingBuffer(playbackURL, false, true,
    6589                                opennow ? RingBuffer::kLiveTVOpenTimeout : -1));
     6589            ctx->SetRingBuffer(
     6590                RingBuffer::Create(
     6591                    playbackURL, false, true,
     6592                    opennow ? RingBuffer::kLiveTVOpenTimeout : -1));
    65906593
    65916594            ctx->tvchain->SetProgram(*ctx->playingInfo);
    65926595            ctx->buffer->SetLiveMode(ctx->tvchain);
     
    76477650{
    76487651    class LCD * lcd = LCD::Get();
    76497652
    7650     if (!lcd || !ctx->buffer || !ctx->buffer->isDVD())
     7653    if (!lcd || !ctx->buffer || !ctx->buffer->IsDVD())
    76517654    {
    76527655        return;
    76537656    }
    76547657
    7655     DVDRingBufferPriv *dvd = ctx->buffer->DVD();
     7658    DVDRingBuffer *dvd = ctx->buffer->DVD();
    76567659    QString dvdName, dvdSerial;
    76577660    QString mainStatus, subStatus;
    76587661
     
    76607663    {
    76617664        dvdName = tr("DVD");
    76627665    }
     7666
    76637667    if (dvd->IsInMenu())
     7668    {
    76647669        mainStatus = tr("Menu");
    7665     else if (dvd->InStillFrame())
     7670    }
     7671    else if (dvd->IsInStillFrame())
     7672    {
    76667673        mainStatus = tr("Still Frame");
     7674    }
    76677675    else
    76687676    {
    76697677        QString timeMins, timeHrsMin;
     
    1148011488*/
    1148111489void TV::DVDJumpBack(PlayerContext *ctx)
    1148211490{
    11483     if (!ctx->HasPlayer() || !ctx->buffer || !ctx->buffer->isDVD())
     11491    DVDRingBuffer *dvdrb = dynamic_cast<DVDRingBuffer*>(ctx->buffer);
     11492    if (!ctx->HasPlayer() || !dvdrb)
    1148411493        return;
    1148511494
    11486     if (ctx->buffer->InDiscMenuOrStillFrame())
     11495    if (ctx->buffer->IsInDiscMenuOrStillFrame())
    1148711496    {
    1148811497        UpdateOSDSeekMessage(ctx, tr("Skip Back Not Allowed"), kOSDTimeout_Med);
    1148911498    }
    11490     else if (!ctx->buffer->DVD()->StartOfTitle())
     11499    else if (!dvdrb->StartOfTitle())
    1149111500    {
    1149211501        ctx->LockDeletePlayer(__FILE__, __LINE__);
    1149311502        if (ctx->player)
     
    1149711506    }
    1149811507    else
    1149911508    {
    11500         uint titleLength = ctx->buffer->DVD()->GetTotalTimeOfTitle();
    11501         uint chapterLength = ctx->buffer->DVD()->GetChapterLength();
     11509        uint titleLength = dvdrb->GetTotalTimeOfTitle();
     11510        uint chapterLength = dvdrb->GetChapterLength();
    1150211511        if ((titleLength == chapterLength) && chapterLength > 300)
    1150311512        {
    1150411513            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     
    1152011529 */
    1152111530void TV::DVDJumpForward(PlayerContext *ctx)
    1152211531{
    11523     if (!ctx->HasPlayer() || !ctx->buffer || !ctx->buffer->isDVD())
     11532    DVDRingBuffer *dvdrb = dynamic_cast<DVDRingBuffer*>(ctx->buffer);
     11533    if (!ctx->HasPlayer() || !dvdrb)
    1152411534        return;
    1152511535
    11526     bool in_still = ctx->buffer->DVD()->InStillFrame();
    11527     bool in_menu  = ctx->buffer->DVD()->IsInMenu();
    11528     if (in_still && !ctx->buffer->DVD()->NumMenuButtons())
     11536    bool in_still = dvdrb->IsInStillFrame();
     11537    bool in_menu  = dvdrb->IsInMenu();
     11538    if (in_still && !dvdrb->NumMenuButtons())
    1152911539    {
    11530         ctx->buffer->DVD()->SkipStillFrame();
     11540        dvdrb->SkipStillFrame();
    1153111541        UpdateOSDSeekMessage(ctx, tr("Skip Still Frame"), kOSDTimeout_Med);
    1153211542    }
    11533     else if (!ctx->buffer->DVD()->EndOfTitle() && !in_still && !in_menu)
     11543    else if (!dvdrb->EndOfTitle() && !in_still && !in_menu)
    1153411544    {
    1153511545        ctx->LockDeletePlayer(__FILE__, __LINE__);
    1153611546        if (ctx->player)
     
    1154111551    }
    1154211552    else if (!in_still && !in_menu)
    1154311553    {
    11544         uint titleLength = ctx->buffer->DVD()->GetTotalTimeOfTitle();
    11545         uint chapterLength = ctx->buffer->DVD()->GetChapterLength();
    11546         uint currentTime = ctx->buffer->DVD()->GetCurrentTime();
     11554        uint titleLength = dvdrb->GetTotalTimeOfTitle();
     11555        uint chapterLength = dvdrb->GetChapterLength();
     11556        uint currentTime = dvdrb->GetCurrentTime();
    1154711557        if ((titleLength == chapterLength) &&
    1154811558             (currentTime < (chapterLength - (ctx->jumptime * 60))) &&
    1154911559             chapterLength > 300)
     
    1156711577 */
    1156811578bool TV::IsBookmarkAllowed(const PlayerContext *ctx) const
    1156911579{
    11570     bool isDVD = ctx->buffer && ctx->buffer->isDVD();
     11580    bool isDVD = ctx->buffer && ctx->buffer->IsDVD();
    1157111581
    1157211582    ctx->LockPlayingInfo(__FILE__, __LINE__);
    1157311583
     
    1162411634
    1162511635    if (StateIsLiveTV(GetState(ctx)))
    1162611636        videotype = tr("Live TV");
    11627     else if (ctx->buffer->isDVD())
     11637    else if (ctx->buffer->IsDVD())
    1162811638        videotype = tr("this DVD");
    1162911639
    1163011640    ctx->LockPlayingInfo(__FILE__, __LINE__);
  • libs/libmythtv/BDRingBuffer.h

     
    88#include "libmythbluray/bluray.h"
    99#include "libmythbluray/keys.h"
    1010
     11#include "RingBuffer.h"
    1112#include "util.h"
    1213
    1314/** \class BDRingBufferPriv
     
    1819
    1920class NuppelVideoPlayer;
    2021
    21 class MPUBLIC BDRingBufferPriv
     22class MPUBLIC BDRingBuffer : public RingBuffer
    2223{
    2324  public:
    24     BDRingBufferPriv();
    25     virtual ~BDRingBufferPriv();
     25    BDRingBuffer(const QString &lfilename);
     26    virtual ~BDRingBuffer();
    2627
    2728    uint32_t GetNumTitles(void) const { return m_numTitles; }
    2829    int      GetCurrentTitle(void) const;
     
    3334    // Get The total duration of the current title in 90Khz ticks.
    3435    uint64_t GetTotalTimeOfTitle(void) const { return (m_currentTitleLength / 90000); }
    3536    uint64_t GetCurrentTime(void) { return (m_currentTime / 90000); }
    36     uint64_t GetReadPosition(void);
     37    virtual long long GetReadPosition(void) const; // RingBuffer
    3738    uint64_t GetTotalReadPosition(void);
    3839    uint32_t GetNumChapters(void);
    3940    uint64_t GetNumAngles(void) { return m_currentTitleAngleCount; }
     
    4243    bool IsOpen(void)        const { return bdnav; }
    4344    bool IsHDMVNavigation(void) const { return m_is_hdmv_navigation; }
    4445    bool IsInMenu(void) const { return m_inMenu; }
    45     bool InStillFrame(void) { return m_still > 0; }
     46    bool IsInStillFrame(void) const { return m_still > 0; }
     47    virtual bool IsInDiscMenuOrStillFrame(void) const
     48        { return IsInMenu() || IsInStillFrame(); } // RingBuffer
    4649
    4750    void GetDescForPos(QString &desc) const;
    4851    double GetFrameRate(void);
     
    5154    int GetSubtitleLanguage(uint streamID);
    5255
    5356    // commands
    54     bool OpenFile(const QString &filename);
     57    virtual bool OpenFile(const QString &filename,
     58                          uint retry_ms = kDefaultOpenTimeout); // RingBuffer
    5559    void close(void);
    5660
    5761    bool GoToMenu(const QString str);
    5862    bool SwitchTitle(uint title);
    5963    bool SwitchAngle(uint angle);
    6064
    61     int  safe_read(void *data, unsigned sz);
     65    virtual int safe_read(void *data, uint sz); // RingBuffer
     66    virtual long long Seek(long long pos, int whence, bool has_lock);
    6267    uint64_t Seek(uint64_t pos);
    6368
    6469    bool HandleBDEvents(void);
     
    97102
    98103  public:
    99104    bool               m_still;
    100     bool               m_inMenu;
     105    volatile bool      m_inMenu;
    101106
    102107};
    103108#endif
  • libs/libmythtv/RingBuffer.h

     
    1717
    1818#include "mythexp.h"
    1919
    20 class RemoteFile;
    2120class ThreadedFileWriter;
    22 class DVDRingBufferPriv;
    23 class BDRingBufferPriv;
     21class DVDRingBuffer;
     22class BDRingBuffer;
    2423class LiveTVChain;
     24class RemoteFile;
    2525
    2626class MPUBLIC RingBuffer : protected QThread
    2727{
    2828  public:
    29     RingBuffer(const QString &lfilename, bool write,
    30                bool usereadahead = true,
    31                int timeout_ms = kDefaultOpenTimeout);
    32    ~RingBuffer();
     29    static RingBuffer *Create(const QString &lfilename, bool write,
     30                              bool usereadahead = true,
     31                              int timeout_ms = kDefaultOpenTimeout,
     32                              bool stream_only = false);
     33    ~RingBuffer();
    3334
    3435    // Sets
    3536    void SetWriteBufferSize(int newSize);
    3637    void SetWriteBufferMinWriteSize(int newMinSize);
    3738    void SetOldFile(bool is_old);
    38     void SetStreamOnly(bool stream);
    3939    void UpdateRawBitrate(uint rawbitrate);
    4040    void UpdatePlaySpeed(float playspeed);
    4141
     
    4646    /// \sa StartReads(void), StopReads(void)
    4747    bool      GetStopReads(void)     const { return stopreads; }
    4848    bool      isPaused(void)         const;
    49     long long GetReadPosition(void)  const;
     49    /// \brief Returns how far into the file we have read.
     50    virtual long long GetReadPosition(void)  const = 0;
    5051    long long GetWritePosition(void) const;
    51     long long GetRealFileSize(void)  const;
    52     bool      IsOpen(void)           const;
     52    /// \brief Returns the size of the file we are reading/writing,
     53    ///        or -1 if the query fails.
     54    virtual long long GetRealFileSize(void)  const { return -1; }
    5355    bool      IsNearEnd(double fps, uint vvf) const;
     56    /// \brief Returns true if open for either reading or writing.
     57    virtual bool IsOpen(void) const = 0;
    5458
     59    bool IsDisc(void) const { return IsDVD() || IsBD(); }
     60    bool IsDVD(void)  const { return DVD() != NULL;     }
     61    bool IsBD(void)   const { return BD()  != NULL;     }
     62    const DVDRingBuffer *DVD(void) const;
     63    const BDRingBuffer  *BD(void)  const;
     64    DVDRingBuffer *DVD(void);
     65    BDRingBuffer  *BD(void);
     66
     67    virtual bool IsInDiscMenuOrStillFrame(void) const { return false; }
     68
    5569    // General Commands
    56     void OpenFile(const QString &lfilename,
    57                   uint retry_ms = kDefaultOpenTimeout);
     70
     71    /** \brief Opens a file for reading.
     72     *
     73     *  \param lfilename  Name of file to read
     74     *  \param retry_ms   How many ms to retry reading the file
     75     *                    after the first try before giving up.
     76     */
     77    virtual bool OpenFile(const QString &lfilename,
     78                          uint retry_ms = kDefaultOpenTimeout) = 0;
     79
    5880    int  Read(void *buf, int count);
    5981    int  Peek(void *buf, int count); // only works with readahead
    6082
     
    6284               bool toAdjust      = false,
    6385               bool resetInternal = false);
    6486
    65     // Seeks
    66     long long Seek(long long pos, int whence, bool has_lock = false);
     87    /// \brief Seeks to a particular position in the file.
     88    virtual long long Seek(
     89        long long pos, int whence, bool has_lock = false) = 0;
    6790
    6891    // Pause commands
    6992    void Pause(void);
     
    87110    void Sync(void);
    88111    long long WriterSeek(long long pos, int whence, bool has_lock = false);
    89112
    90     // DVDRingBuffer proxies
    91     bool IsDVD(void) const;
    92 
    93     // BDRingBuffer proxies
    94     bool IsBD(void) const;
    95 
    96     // Universal still frame/menu check
    97     bool InDiscMenuOrStillFrame(void);
    98 
    99113    long long SetAdjustFilesize(void);
    100114
    101115    /// Calls SetOldFile(), do not use
    102116    void SetTimeout(bool is_old) MDEPRECATED { SetOldFile(is_old); }
    103     /// Calls IsDVD(), do not use
    104     bool isDVD(void) const MDEPRECATED { return IsDVD(); }
    105     /// Calls IsBD(), do not use
    106     bool isBD(void) const MDEPRECATED { return IsBD(); }
    107     /// Illicitly manipulating privates is ill advised!
    108     /// DO NOT USE
    109     DVDRingBufferPriv *DVD() MDEPRECATED
    110     {
    111         return dvdPriv;
    112     }
    113     /// Illicitly manipulating privates is ill advised!
    114     /// DO NOT USE
    115     BDRingBufferPriv *BD() MDEPRECATED
    116     {
    117         return bdPriv;
    118     }
    119117
    120118    static const int kDefaultOpenTimeout;
    121119    static const int kLiveTVOpenTimeout;
    122120
    123121  protected:
     122    RingBuffer();
     123
    124124    void run(void); // QThread
    125125    void CalcReadAheadThresh(void);
    126126    bool PauseAndWait(void);
    127     int safe_read_bd(void *data, uint sz);
    128     int safe_read_dvd(void *data, uint sz);
    129     int safe_read(int fd, void *data, uint sz);
    130     int safe_read(RemoteFile *rf, void *data, uint sz);
     127    virtual int safe_read(void *data, uint sz) = 0;
    131128
    132129    int ReadPriv(void *buf, int count, bool peek);
    133130    int ReadDirect(void *buf, int count, bool peek);
     
    140137    void ResetReadAhead(long long newinternal);
    141138    void KillReadAheadThread(void);
    142139
    143   private:
     140  protected:
    144141    mutable QReadWriteLock poslock;
    145142    long long readpos;            // protected by poslock
    146143    long long writepos;           // protected by poslock
     
    176173    bool      ateof;              // protected by rwlock
    177174    bool      readsallowed;       // protected by rwlock
    178175    bool      setswitchtonext;    // protected by rwlock
    179     bool      streamOnly;         // protected by rwlock
    180176    bool      ignorereadahead;    // protected by rwlock
    181177    uint      rawbitrate;         // protected by rwlock
    182178    float     playspeed;          // protected by rwlock
     
    187183    int       numfailures;        // protected by rwlock (see note 1)
    188184    bool      commserror;         // protected by rwlock
    189185
    190     // We should really subclass for these two sets of functionality..
    191     // current implementation is not thread-safe.
    192     DVDRingBufferPriv *dvdPriv; // NOT protected by a lock
    193     BDRingBufferPriv  *bdPriv;  // NOT protected by a lock
    194 
    195186    bool oldfile;                 // protected by rwlock
    196187
    197188    LiveTVChain *livetvchain;     // protected by rwlock
  • libs/libmythtv/decoderbase.cpp

     
    106106    // Overwrites current positionmap with entire contents of database
    107107    frm_pos_map_t posMap;
    108108
    109     if (ringBuffer->isDVD())
     109    if (ringBuffer->IsDVD())
    110110    {
    111111        long long totframes;
    112112        keyframedist = 15;
     
    116116        totframes = (long long)(ringBuffer->DVD()->GetTotalTimeOfTitle() * fps);
    117117        posMap[totframes] = ringBuffer->DVD()->GetTotalReadPosition();
    118118    }
    119     else if (ringBuffer->isBD())
     119    else if (ringBuffer->IsBD())
    120120    {
    121121        long long totframes;
    122122        keyframedist = 15;
     
    182182        m_positionMap.push_back(e);
    183183    }
    184184
    185     if (!m_positionMap.empty() && !ringBuffer->isDVD() &&
    186         !ringBuffer->isBD())
     185    if (!m_positionMap.empty() && !ringBuffer->IsDisc())
    187186        indexOffset = m_positionMap[0].index;
    188187
    189188    if (!m_positionMap.empty())
     
    234233        m_positionMap.push_back(e);
    235234    }
    236235
    237     if (!m_positionMap.empty() && !ringBuffer->isDVD() &&
    238         !ringBuffer->isBD())
     236    if (!m_positionMap.empty() && !ringBuffer->IsDisc())
    239237        indexOffset = m_positionMap[0].index;
    240238
    241239    if (!m_positionMap.empty())
     
    335333        long long totframes = 0;
    336334        int length = 0;
    337335
    338         if (ringBuffer->isDVD())
     336        if (ringBuffer->IsDVD())
    339337        {
    340338            length = ringBuffer->DVD()->GetTotalTimeOfTitle();
    341339            QMutexLocker locker(&m_positionMapLock);
    342340            totframes = m_positionMap.back().index;
    343341        }
    344         else if (ringBuffer->isBD())
     342        else if (ringBuffer->IsBD())
    345343        {
    346344            length = ringBuffer->BD()->GetTotalTimeOfTitle();
    347345            QMutexLocker locker(&m_positionMapLock);
     
    509507    normalframes = max(normalframes, 0);
    510508    SeekReset(lastKey, normalframes, true, discardFrames);
    511509
    512     if (ringBuffer->isDVD() || ringBuffer->isBD() || discardFrames)
     510    if (ringBuffer->IsDisc() || discardFrames)
    513511    {
    514512        // We need to tell the NVP and VideoOutput what frame we're on.
    515513        m_parent->SetFramesPlayed(framesPlayed+1);
     
    521519
    522520long long DecoderBase::GetKey(const PosMapEntry &e) const
    523521{
    524     long long kf  = (ringBuffer->isDVD() || ringBuffer->isBD()) ? 1LL : keyframedist;
     522    long long kf = (ringBuffer->IsDisc()) ? 1LL : keyframedist;
    525523    return (hasKeyFrameAdjustTable) ? e.adjFrame :(e.index - indexOffset) * kf;
    526524}
    527525
    528526bool DecoderBase::DoRewindSeek(long long desiredFrame)
    529527{
    530     if (ringBuffer->isDVD())
     528    if (ringBuffer->IsDVD())
    531529    {
    532530        long long pos = DVDFindPosition(desiredFrame);
    533531        ringBuffer->Seek(pos, SEEK_SET);
    534532        lastKey = desiredFrame + 1;
    535533        return true;
    536534    }
    537     else if (ringBuffer->isBD())
     535    else if (ringBuffer->IsBD())
    538536    {
    539537        long long pos = BDFindPosition(desiredFrame);
    540538        ringBuffer->Seek(pos, SEEK_SET);
     
    645643            .arg(desiredFrame).arg(framesPlayed)
    646644            .arg((discardFrames) ? "do" : "don't"));
    647645
    648     if (ringBuffer->isDVD() &&
    649         ringBuffer->DVD()->TitleTimeLeft() < 5 &&
    650         !ringBuffer->InDiscMenuOrStillFrame())
     646    if (ringBuffer->IsDVD() &&
     647        !ringBuffer->IsInDiscMenuOrStillFrame() &&
     648        ringBuffer->DVD()->TitleTimeLeft() < 5)
    651649    {
    652650        return false;
    653651    }
     
    753751 */
    754752void DecoderBase::DoFastForwardSeek(long long desiredFrame, bool &needflush)
    755753{
    756     if (ringBuffer->isDVD())
     754    if (ringBuffer->IsDVD())
    757755    {
    758756        long long pos = DVDFindPosition(desiredFrame);
    759757        ringBuffer->Seek(pos,SEEK_SET);
     
    763761        framesRead   = lastKey;
    764762        return;
    765763    }
    766     else if (ringBuffer->isBD())
     764    else if (ringBuffer->IsBD())
    767765    {
    768766        long long pos = BDFindPosition(desiredFrame);
    769767        ringBuffer->Seek(pos,SEEK_SET);
     
    830828
    831829void DecoderBase::ChangeDVDTrack(bool ffw)
    832830{
    833     if (!ringBuffer->isDVD())
     831    if (!ringBuffer->IsDVD())
    834832        return;
    835833
    836834    bool result = true;
     
    853851
    854852long long DecoderBase::DVDFindPosition(long long desiredFrame)
    855853{
    856     if (!ringBuffer->isDVD())
     854    if (!ringBuffer->IsDVD())
    857855        return 0;
    858856    int diffTime = 0;
    859857    long long desiredTimePos;
     
    884882
    885883long long DecoderBase::BDFindPosition(long long desiredFrame)
    886884{
    887     if (!ringBuffer->isBD())
     885    if (!ringBuffer->IsBD())
    888886        return 0;
    889887    int diffTime = 0;
    890888    long long desiredTimePos;
     
    915913
    916914void DecoderBase::UpdateDVDFramesPlayed(void)
    917915{
    918     if (!ringBuffer->isDVD())
     916    if (!ringBuffer->IsDVD())
    919917        return;
    920918    long long currentpos = (long long)(ringBuffer->DVD()->GetCurrentTime() * fps);
    921919    framesPlayed = framesRead = currentpos ;
     
    925923
    926924void DecoderBase::UpdateBDFramesPlayed(void)
    927925{
    928     if (!ringBuffer->isBD())
     926    if (!ringBuffer->IsBD())
    929927        return;
    930928    long long currentpos = (long long)(ringBuffer->BD()->GetCurrentTime() * fps);
    931929    framesPlayed = framesRead = currentpos ;
  • libs/libmythtv/tv_rec.cpp

     
    40664066        bool write = genOpt.cardtype != "IMPORT";
    40674067        VERBOSE(VB_IMPORTANT, LOC + QString("rec->GetPathname(): '%1'")
    40684068                .arg(rec->GetPathname()));
    4069         SetRingBuffer(new RingBuffer(rec->GetPathname(), write));
     4069        SetRingBuffer(RingBuffer::Create(rec->GetPathname(), write));
    40704070        if (!ringBuffer->IsOpen() && write)
    40714071        {
    40724072            VERBOSE(VB_IMPORTANT, LOC_ERR +
     
    44514451
    44524452    StartedRecording(prog);
    44534453
    4454     *rb = new RingBuffer(prog->GetPathname(), true);
     4454    *rb = RingBuffer::Create(prog->GetPathname(), true);
    44554455    if (!(*rb)->IsOpen())
    44564456    {
    44574457        VERBOSE(VB_IMPORTANT, LOC_ERR +
  • libs/libmythtv/textsubtitleparser.cpp

     
    119119bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target)
    120120{
    121121    demux_sputext_t sub_data;
    122     sub_data.rbuffer = new RingBuffer(fileName, 0, false);
     122    sub_data.rbuffer = RingBuffer::Create(fileName, 0, false);
    123123
    124124    if (!sub_data.rbuffer)
    125125        return false;
  • programs/mythfrontend/main.cpp

     
    750750
    751751    if (pginfo->IsVideoDVD())
    752752    {
    753         RingBuffer *tmprbuf = new RingBuffer(pginfo->GetPathname(), false);
     753        RingBuffer *tmprbuf = RingBuffer::Create(pginfo->GetPathname(), false);
    754754
    755755        if (!tmprbuf)
    756756        {
     
    759759        }
    760760        QString name;
    761761        QString serialid;
    762         if (tmprbuf->isDVD() &&
    763              tmprbuf->DVD()->GetNameAndSerialNum(name, serialid))
     762        if (tmprbuf->IsDVD() &&
     763            tmprbuf->DVD()->GetNameAndSerialNum(name, serialid))
    764764        {
    765765            QStringList fields = pginfo->QueryDVDBookmark(serialid, false);
    766766            if (!fields.empty())
  • programs/mythtranscode/transcode.cpp

     
    377377    nvr = new NuppelVideoRecorder(NULL, NULL);
    378378
    379379    // Input setup
    380     inRingBuffer = new RingBuffer(inputname, false, false);
     380    inRingBuffer = RingBuffer::Create(inputname, false, false);
    381381    player = new MythPlayer();
    382382
    383383    player_ctx = new PlayerContext(kTranscoderInUseID);
     
    684684        else if (vidsetting == "RTjpeg")
    685685            nvr->SetupRTjpeg();
    686686
    687         outRingBuffer = new RingBuffer(outputname, true, false);
     687        outRingBuffer = RingBuffer::Create(outputname, true, false);
    688688        nvr->SetRingBuffer(outRingBuffer);
    689689        nvr->WriteHeader();
    690690        nvr->StreamAllocate();
  • programs/mythcommflag/main.cpp

     
    155155    else
    156156        filename = get_filename(program_info);
    157157
    158     RingBuffer *tmprbuf = new RingBuffer(filename, false);
     158    RingBuffer *tmprbuf = RingBuffer::Create(filename, false);
    159159    if (!tmprbuf)
    160160    {
    161161        VERBOSE(VB_IMPORTANT,
     
    737737
    738738    QString filename = get_filename(program_info);
    739739
    740     RingBuffer *tmprbuf = new RingBuffer(filename, false);
     740    RingBuffer *tmprbuf = RingBuffer::Create(filename, false);
    741741    if (!tmprbuf)
    742742    {
    743743        VERBOSE(VB_IMPORTANT,
  • programs/mythbackend/filetransfer.cpp

     
    1111FileTransfer::FileTransfer(QString &filename, MythSocket *remote,
    1212                           bool usereadahead, int timeout_ms) :
    1313    readthreadlive(true), readsLocked(false),
    14     rbuffer(new RingBuffer(filename, false, usereadahead, timeout_ms)),
     14    rbuffer(RingBuffer::Create(filename, false, usereadahead, timeout_ms)),
    1515    sock(remote), ateof(false), lock(QMutex::NonRecursive),
    1616    refLock(QMutex::NonRecursive), refCount(0), writemode(false)
    1717{
     
    2121
    2222FileTransfer::FileTransfer(QString &filename, MythSocket *remote, bool write) :
    2323    readthreadlive(true), readsLocked(false),
    24     rbuffer(new RingBuffer(filename, write)),
     24    rbuffer(RingBuffer::Create(filename, write)),
    2525    sock(remote), ateof(false), lock(QMutex::NonRecursive),
    2626    refLock(QMutex::NonRecursive), refCount(0), writemode(write)
    2727{
     
    234234    if (pginfo)
    235235        pginfo->UpdateInUseMark();
    236236
    237     rbuffer->SetTimeout(fast);
     237    rbuffer->SetOldFile(fast);
    238238}
    239239
    240240/* vim: set expandtab tabstop=4 shiftwidth=4: */