Ignore:
Timestamp:
12/15/07 19:09:12 (16 years ago)
Author:
radscorpion
Message:

Fixed seeking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • dsfilters/demux_mpc/src/mpc_filter.cpp

    r372 r373  
    5454        rtStop(0xFFFFFFFFFFFFFF),
    5555        rate(1.0),
    56         ev_abort(TRUE)
     56        ev_abort(TRUE),
     57        ev_seek_ready(TRUE)
    5758{
    5859        input = new CMPCInputPin(NAME("MPC Input Pin"), this, phr, L"In");
     
    6162
    6263        ev_abort.Reset();
     64        ev_seek_ready.Set();
    6365}
    6466
     
    311313}
    312314
     315
     316
     317// IMediaSeeking
     318
     319STDMETHODIMP CMPCDemux::GetCapabilities(DWORD* pCapabilities)
     320{
     321        return pCapabilities ? *pCapabilities =
     322                        AM_SEEKING_CanGetStopPos|AM_SEEKING_CanGetDuration|AM_SEEKING_CanSeekAbsolute|AM_SEEKING_CanSeekForwards|AM_SEEKING_CanSeekBackwards,
     323                        S_OK : E_POINTER;
     324}
     325STDMETHODIMP CMPCDemux::CheckCapabilities(DWORD* pCapabilities)
     326{
     327        CheckPointer(pCapabilities, E_POINTER);
     328        if (*pCapabilities == 0) return S_OK;
     329        DWORD caps;
     330        GetCapabilities(&caps);
     331        if ((caps&*pCapabilities) == 0) return E_FAIL;
     332        if (caps == *pCapabilities) return S_OK;
     333        return S_FALSE;
     334}
     335STDMETHODIMP CMPCDemux::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
     336STDMETHODIMP CMPCDemux::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
     337STDMETHODIMP CMPCDemux::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
     338STDMETHODIMP CMPCDemux::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
     339STDMETHODIMP CMPCDemux::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
     340STDMETHODIMP CMPCDemux::GetStopPosition(LONGLONG* pStop) {return this->rtStop; }
     341STDMETHODIMP CMPCDemux::GetCurrentPosition(LONGLONG* pCurrent) {return E_NOTIMPL;}
     342STDMETHODIMP CMPCDemux::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
     343
     344STDMETHODIMP CMPCDemux::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
     345{
     346        return SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
     347}
     348
     349STDMETHODIMP CMPCDemux::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop)
     350{
     351        if(pCurrent) *pCurrent = rtCurrent;
     352        if(pStop) *pStop = rtStop;
     353        return S_OK;
     354}
     355STDMETHODIMP CMPCDemux::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest)
     356{
     357        if(pEarliest) *pEarliest = 0;
     358        return GetDuration(pLatest);
     359}
     360STDMETHODIMP CMPCDemux::SetRate(double dRate) {return dRate > 0 ? rate = dRate, S_OK : E_INVALIDARG;}
     361STDMETHODIMP CMPCDemux::GetRate(double* pdRate) {return pdRate ? *pdRate = rate, S_OK : E_POINTER;}
     362STDMETHODIMP CMPCDemux::GetPreroll(LONGLONG* pllPreroll) {return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;}
     363
     364STDMETHODIMP CMPCDemux::GetDuration(LONGLONG* pDuration)
     365{       
     366        CheckPointer(pDuration, E_POINTER);
     367        *pDuration = 0;
     368
     369        if (file) {
     370                if (pDuration) *pDuration = file->duration_10mhz;
     371        }
     372        return S_OK;
     373}
     374
     375STDMETHODIMP CMPCDemux::SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
     376{
     377        // only our first pin can seek
     378        if (iD != 0) return NOERROR;
     379
     380
     381        CAutoLock cAutoLock(&lock_filter);
     382
     383        if (!pCurrent && !pStop || (dwCurrentFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning
     384                && (dwStopFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
     385                return S_OK;
     386
     387        REFERENCE_TIME rtCurrent = this->rtCurrent, rtStop = this->rtStop;
     388
     389        if (pCurrent) {
     390                switch(dwCurrentFlags&AM_SEEKING_PositioningBitsMask) {
     391                case AM_SEEKING_NoPositioning: break;
     392                case AM_SEEKING_AbsolutePositioning: rtCurrent = *pCurrent; break;
     393                case AM_SEEKING_RelativePositioning: rtCurrent = rtCurrent + *pCurrent; break;
     394                case AM_SEEKING_IncrementalPositioning: rtCurrent = rtCurrent + *pCurrent; break;
     395                }
     396        }
     397
     398        if (pStop) {
     399                switch(dwStopFlags&AM_SEEKING_PositioningBitsMask) {
     400                case AM_SEEKING_NoPositioning: break;
     401                case AM_SEEKING_AbsolutePositioning: rtStop = *pStop; break;
     402                case AM_SEEKING_RelativePositioning: rtStop += *pStop; break;
     403                case AM_SEEKING_IncrementalPositioning: rtStop = rtCurrent + *pStop; break;
     404                }
     405        }
     406
     407        if (this->rtCurrent == rtCurrent && this->rtStop == rtStop) {
     408                return S_OK;
     409        }
     410
     411        this->rtCurrent = rtCurrent;
     412        this->rtStop = rtStop;
     413
     414        // now there are new valid Current and Stop positions
     415        ev_seek_ready.Wait();
     416        ev_seek_ready.Reset();
     417        HRESULT hr = DoNewSeek();
     418        ev_seek_ready.Set();
     419        return hr;
     420}
     421
     422
     423STDMETHODIMP CMPCDemux::Pause()
     424{
     425        CAutoLock       lck(&lock_filter);
     426
     427        if (m_State == State_Stopped) {
     428
     429                ev_abort.Reset();
     430
     431                // activate pins
     432                for (int i=0; i<output.GetCount(); i++) output[i]->Active();
     433                if (input) input->Active();
     434
     435                // seekneme na danu poziciu
     436                DoNewSeek();
     437
     438                // pustime parser thread
     439                if (!ThreadExists()) {
     440                        Create();
     441                        CallWorker(CMD_RUN);
     442                }
     443        }
     444
     445        m_State = State_Paused;
     446        return NOERROR;
     447}
     448
     449STDMETHODIMP CMPCDemux::Stop()
     450{
     451        CAutoLock       lock(&lock_filter);
     452        HRESULT         hr = NOERROR;
     453
     454        if (m_State != State_Stopped) {
     455
     456                // set abort
     457                ev_abort.Set();
     458                if (reader) reader->BeginFlush();
     459
     460                // deaktivujeme piny
     461                if (input) input->Inactive();
     462                for (int i=0; i<output.GetCount(); i++) output[i]->Inactive();
     463
     464                // zrusime parser thread
     465                if (ThreadExists()) {
     466                        CallWorker(CMD_EXIT);
     467                        Close();
     468                }
     469
     470                if (reader) reader->EndFlush();
     471                ev_abort.Reset();
     472        }
     473
     474
     475        m_State = State_Stopped;
     476        return hr;
     477}
     478
     479
     480HRESULT CMPCDemux::DoNewSeek()
     481{
     482        CMPCOutputPin   *pin = output[0];
     483        HRESULT                 hr;
     484
     485        if (!pin->IsConnected()) return NOERROR;
     486
     487        // stop first
     488        ev_abort.Set();
     489        if (reader) reader->BeginFlush();
     490
     491        FILTER_STATE    state = m_State;
     492
     493        // abort
     494        if (state != State_Stopped) {
     495                if (pin->ThreadExists()) {
     496                        pin->ev_abort.Set();
     497                        hr = pin->DeliverBeginFlush();
     498                        if (FAILED(hr)) {
     499                                ASSERT(FALSE);
     500                        }
     501                        if (ThreadExists()) {
     502                                CallWorker(CMD_STOP);
     503                        }
     504                        pin->CallWorker(CMD_STOP);
     505
     506                        hr = pin->DeliverEndFlush();
     507                        if (FAILED(hr)) {
     508                                ASSERT(FALSE);
     509                        }
     510                        pin->FlushQueue();
     511                }
     512        }
     513
     514        pin->DoNewSegment(rtCurrent, rtStop, rate);
     515        if (reader) reader->EndFlush();
     516
     517        // seek the file
     518        if (file) {
     519                int64 sample_pos = (rtCurrent * file->sample_rate) / 10000000;
     520                file->Seek(sample_pos);
     521        }
     522
     523        ev_abort.Reset();
     524
     525        if (state != State_Stopped) {
     526                // spustime aj jeho thread
     527                pin->FlushQueue();
     528                pin->ev_abort.Reset();
     529                if (pin->ThreadExists()) {
     530                        pin->CallWorker(CMD_RUN);
     531                }
     532                if (ThreadExists()) {
     533                        CallWorker(CMD_RUN);
     534                }
     535        }
     536
     537        return NOERROR;
     538}
     539
    313540DWORD CMPCDemux::ThreadProc()
    314541{
     
    318545                switch (cmd) {
    319546                case CMD_EXIT:  Reply(NOERROR); return 0;
    320                 case CMD_STOP:  Reply(NOERROR); break;
     547                case CMD_STOP: 
     548                        {
     549                                Reply(NOERROR);
     550                        }
     551                        break;
    321552                case CMD_RUN:
    322553                        {
     
    361592                                                REFERENCE_TIME  tStart = (current_sample * 10000000) / file->sample_rate;
    362593                                                REFERENCE_TIME  tStop  = ((current_sample + 1152*file->audio_block_frames) * 10000000) / file->sample_rate;
    363                                                 packet.tStart = tStart;
    364                                                 packet.tStop  = tStop;
     594
     595                                                packet.tStart = tStart - rtCurrent;
     596                                                packet.tStop  = tStop  - rtCurrent;
    365597
    366598                                                // deliver packet
    367599                                                hr = output[0]->DeliverPacket(packet);
    368                                                 if (FAILED(hr)) break;
     600                                                if (FAILED(hr)) {
     601                                                        break;
     602                                                }
    369603
    370604                                                delivered++;
     
    382616}
    383617
    384 
    385 // IMediaSeeking
    386 
    387 STDMETHODIMP CMPCDemux::GetCapabilities(DWORD* pCapabilities)
    388 {
    389         return pCapabilities ? *pCapabilities =
    390                         AM_SEEKING_CanGetStopPos|AM_SEEKING_CanGetDuration|AM_SEEKING_CanSeekAbsolute|AM_SEEKING_CanSeekForwards|AM_SEEKING_CanSeekBackwards,
    391                         S_OK : E_POINTER;
    392 }
    393 STDMETHODIMP CMPCDemux::CheckCapabilities(DWORD* pCapabilities)
    394 {
    395         CheckPointer(pCapabilities, E_POINTER);
    396         if (*pCapabilities == 0) return S_OK;
    397         DWORD caps;
    398         GetCapabilities(&caps);
    399         if ((caps&*pCapabilities) == 0) return E_FAIL;
    400         if (caps == *pCapabilities) return S_OK;
    401         return S_FALSE;
    402 }
    403 STDMETHODIMP CMPCDemux::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
    404 STDMETHODIMP CMPCDemux::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
    405 STDMETHODIMP CMPCDemux::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
    406 STDMETHODIMP CMPCDemux::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
    407 STDMETHODIMP CMPCDemux::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
    408 STDMETHODIMP CMPCDemux::GetStopPosition(LONGLONG* pStop) {return this->rtStop; }
    409 STDMETHODIMP CMPCDemux::GetCurrentPosition(LONGLONG* pCurrent) {return E_NOTIMPL;}
    410 STDMETHODIMP CMPCDemux::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
    411 
    412 STDMETHODIMP CMPCDemux::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
    413 {
    414         return SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
    415 }
    416 
    417 STDMETHODIMP CMPCDemux::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop)
    418 {
    419         if(pCurrent) *pCurrent = rtCurrent;
    420         if(pStop) *pStop = rtStop;
    421         return S_OK;
    422 }
    423 STDMETHODIMP CMPCDemux::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest)
    424 {
    425         if(pEarliest) *pEarliest = 0;
    426         return GetDuration(pLatest);
    427 }
    428 STDMETHODIMP CMPCDemux::SetRate(double dRate) {return dRate > 0 ? rate = dRate, S_OK : E_INVALIDARG;}
    429 STDMETHODIMP CMPCDemux::GetRate(double* pdRate) {return pdRate ? *pdRate = rate, S_OK : E_POINTER;}
    430 STDMETHODIMP CMPCDemux::GetPreroll(LONGLONG* pllPreroll) {return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;}
    431 
    432 STDMETHODIMP CMPCDemux::GetDuration(LONGLONG* pDuration)
    433 {       
    434         CheckPointer(pDuration, E_POINTER);
    435         *pDuration = 0;
    436 
    437         if (file) {
    438                 if (pDuration) *pDuration = file->duration_10mhz;
    439         }
    440         return S_OK;
    441 }
    442 
    443 STDMETHODIMP CMPCDemux::SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
    444 {
    445         // only our first pin can seek
    446         if (iD != 0) return NOERROR;
    447         CAutoLock cAutoLock(&lock_filter);
    448 
    449         if (!pCurrent && !pStop || (dwCurrentFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning
    450                 && (dwStopFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
    451                 return S_OK;
    452 
    453         REFERENCE_TIME rtCurrent = this->rtCurrent, rtStop = this->rtStop;
    454 
    455         if (pCurrent) {
    456                 switch(dwCurrentFlags&AM_SEEKING_PositioningBitsMask) {
    457                 case AM_SEEKING_NoPositioning: break;
    458                 case AM_SEEKING_AbsolutePositioning: rtCurrent = *pCurrent; break;
    459                 case AM_SEEKING_RelativePositioning: rtCurrent = rtCurrent + *pCurrent; break;
    460                 case AM_SEEKING_IncrementalPositioning: rtCurrent = rtCurrent + *pCurrent; break;
    461                 }
    462         }
    463 
    464         if (pStop) {
    465                 switch(dwStopFlags&AM_SEEKING_PositioningBitsMask) {
    466                 case AM_SEEKING_NoPositioning: break;
    467                 case AM_SEEKING_AbsolutePositioning: rtStop = *pStop; break;
    468                 case AM_SEEKING_RelativePositioning: rtStop += *pStop; break;
    469                 case AM_SEEKING_IncrementalPositioning: rtStop = rtCurrent + *pStop; break;
    470                 }
    471         }
    472 
    473         if (this->rtCurrent == rtCurrent && this->rtStop == rtStop) return S_OK;
    474 
    475         this->rtCurrent = rtCurrent;
    476         this->rtStop = rtStop;
    477 
    478         // now there are new valid Current and Stop positions
    479         HRESULT hr = DoNewSeek();
    480         return hr;
    481 }
    482 
    483 HRESULT CMPCDemux::DoNewSeek()
    484 {
    485         // stop first
    486         ev_abort.Set();
    487         if (reader) reader->BeginFlush();
    488 
    489         CMPCOutputPin   *pin = output[0];
    490         FILTER_STATE    state = m_State;
    491 
    492         if (pin->IsConnected()) {
    493                 // abort
    494                 if (state != State_Stopped) {
    495                         if (pin->ThreadExists()) {
    496                                 pin->ev_abort.Set();
    497                                 pin->DeliverBeginFlush();
    498 
    499                                 pin->CallWorker(CMD_STOP);
    500                                 pin->FlushQueue();
    501                         }
    502                 }
    503         }
    504 
    505         if (reader) reader->EndFlush();
    506 
    507         if (pin->IsConnected()) {
    508                 if (state != State_Stopped) {
    509                         if (pin->ThreadExists()) {
    510                                 pin->ev_abort.Reset();
    511                                 pin->DeliverEndFlush();
    512                         }
    513                 }
    514                 pin->DoNewSegment(rtCurrent, rtStop, rate);
    515         }
    516 
    517         if (ThreadExists()) {
    518                 CallWorker(CMD_STOP);
    519         }
    520 
    521         // seek the file
    522         if (file) {
    523                 int64 sample_pos = rtCurrent * file->sample_rate / 10000000;
    524                 file->Seek(sample_pos);
    525         }
    526 
    527         ev_abort.Reset();
    528         if (ThreadExists()) {
    529                 CallWorker(CMD_RUN);
    530         }
    531 
    532         if (pin->IsConnected()) {
    533                 if (state != State_Stopped) {
    534                         // spustime aj jeho thread
    535                         if (pin->ThreadExists()) {
    536                                 pin->FlushQueue();
    537                                 pin->CallWorker(CMD_RUN);
    538                         }
    539                 }
    540         }
    541 
    542         return NOERROR;
    543 }
    544 
    545 
    546 STDMETHODIMP CMPCDemux::Pause()
    547 {
    548         CAutoLock       lck(&lock_filter);
    549 
    550         if (m_State == State_Stopped) {
    551 
    552                 ev_abort.Reset();
    553 
    554                 // activate pins
    555                 for (int i=0; i<output.GetCount(); i++) output[i]->Active();
    556                 if (input) input->Active();
    557 
    558                 // seekneme na danu poziciu
    559                 DoNewSeek();
    560 
    561                 // pustime parser thread
    562                 if (!ThreadExists()) {
    563                         Create();
    564                         CallWorker(CMD_RUN);
    565                 }
    566         }
    567 
    568         m_State = State_Paused;
    569         return NOERROR;
    570 }
    571 
    572 STDMETHODIMP CMPCDemux::Stop()
    573 {
    574         CAutoLock       lock(&lock_filter);
    575         HRESULT         hr = NOERROR;
    576 
    577         if (m_State != State_Stopped) {
    578 
    579                 // set abort
    580                 ev_abort.Set();
    581                 if (reader) reader->BeginFlush();
    582 
    583                 // deaktivujeme piny
    584                 if (input) input->Inactive();
    585                 for (int i=0; i<output.GetCount(); i++) output[i]->Inactive();
    586 
    587                 // zrusime parser thread
    588                 if (ThreadExists()) {
    589                         CallWorker(CMD_EXIT);
    590                         Close();
    591                 }
    592 
    593                 if (reader) reader->EndFlush();
    594                 ev_abort.Reset();
    595         }
    596 
    597 
    598         m_State = State_Stopped;
    599         return hr;
    600 }
Note: See TracChangeset for help on using the changeset viewer.