Ignore:
Timestamp:
12/14/07 00:22:01 (16 years ago)
Author:
radscorpion
Message:

MPC Demux works. Right now it can only be used with Dump filter, because
it accepts any mediatype.

File:
1 edited

Legend:

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

    r366 r368  
    4747CMPCDemux::CMPCDemux(LPUNKNOWN pUnk, HRESULT *phr) :
    4848        CBaseFilter(_T("MPC Splitter"), pUnk, &lock_filter, CLSID_MusepackDemuxer, phr),
     49        CAMThread(),
    4950        reader(NULL),
    5051        file(NULL),
    51         wnd_prop(NULL)
     52        wnd_prop(NULL),
     53        rtCurrent(0),
     54        rtStop(0xFFFFFFFFFFFFFF),
     55        rate(1.0),
     56        ev_abort(TRUE)
    5257{
    5358        input = new CMPCInputPin(NAME("MPC Input Pin"), this, phr, L"In");
    5459        output.RemoveAll();
    5560        retired.RemoveAll();
     61
     62        ev_abort.Reset();
    5663}
    5764
     
    8289        if (riid == IID_IMusepackSplitter) {
    8390                return GetInterface((IMusepackSplitter*)this, ppv);
    84         } else{
    85         /*
     91        } else
    8692    if (riid == IID_IMediaSeeking) {
    87         return GetInterface((IMediaSeeking *)this, ppv);
    88     } else
    89         */
    90 
     93        return GetInterface((IMediaSeeking*)this, ppv);
     94        } else {
    9195                return CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
    9296        }
     
    185189                }
    186190
     191                HRESULT                 hr = NOERROR;
     192                CMPCOutputPin   *opin = new CMPCOutputPin(_T("Outpin"), this, &hr, L"Out", 5);
     193                ConfigureMediaType(opin);
     194                AddOutputPin(opin);
     195
    187196                // refresh property page if there is any
    188197                if (IsWindow(wnd_prop)) {
     
    215224
    216225
     226HRESULT CMPCDemux::ConfigureMediaType(CMPCOutputPin *pin)
     227{
     228        CMediaType              mt;
     229        mt.majortype = MEDIATYPE_Audio;
     230        mt.subtype = MEDIASUBTYPE_MusepackPacket;
     231        mt.formattype = FORMAT_WaveFormatEx;
     232        mt.lSampleSize = 128*1024;                              // should be way enough
     233
     234        ASSERT(file);
     235        int             extrasize = file->extradata_size;
     236
     237        // let us fill the waveformatex structure
     238        WAVEFORMATEX *wfx = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX) + extrasize);
     239        memset(wfx, 0, sizeof(*wfx));
     240        wfx->cbSize = extrasize;
     241        wfx->wBitsPerSample = 0;
     242        wfx->nChannels = file->channels;
     243        wfx->nSamplesPerSec = file->sample_rate;
     244        wfx->nBlockAlign = 1;
     245        wfx->nAvgBytesPerSec = 0;
     246        wfx->wFormatTag = 0;
     247
     248        // Extradata - Stream header + other stuff
     249        uint8   *extra = ((uint8*)wfx) + sizeof(WAVEFORMATEX);
     250        memcpy(extra, file->extradata, extrasize);
     251
     252        // the one and only type
     253        pin->mt_types.Add(mt);
     254        return NOERROR;
     255}
     256
    217257HRESULT CMPCDemux::BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller)
    218258{
     
    221261        if (Dir == PINDIR_INPUT) {
    222262                // let's disconnect the output pins
    223                 //ev_abort.Set();
     263                ev_abort.Set();
    224264                //ev_ready.Set();
    225265
     
    238278                }
    239279
    240                 //ev_abort.Reset();
     280                ev_abort.Reset();
    241281        } else
    242282        if (Dir == PINDIR_OUTPUT) {
     
    271311}
    272312
    273 
    274 
    275 
     313DWORD CMPCDemux::ThreadProc()
     314{
     315        DWORD   cmd, cmd2;
     316        while (true) {
     317                cmd = GetRequest();
     318                switch (cmd) {
     319                case CMD_EXIT:  Reply(NOERROR); return 0;
     320                case CMD_STOP:  Reply(NOERROR); break;
     321                case CMD_RUN:
     322                        {
     323                                Reply(NOERROR);
     324                                if (!file) break;
     325
     326                                CMPCPacket              packet;
     327                                int32                   ret=0;
     328                                bool                    eos=false;
     329                                HRESULT                 hr;
     330                                int64                   current_sample;
     331
     332                                /*
     333                                        With a more complex demultiplexer we would need a mechanism
     334                                        to identify streams. Now we have only one output stream
     335                                        so it's easy.
     336                                */
     337
     338                                if (output.GetCount() <= 0) break;
     339                                if (output[0]->IsConnected() == FALSE) break;
     340
     341                                do {
     342
     343                                        // are we supposed to abort ?
     344                                        if (ev_abort.Check()) {
     345                                                ret = 0;
     346                                                break;
     347                                        }
     348
     349                                        ret = file->ReadAudioPacket(&packet, &current_sample);
     350                                        if (ret < 0) {
     351                                                // end of stream
     352                                                break;
     353                                        } else {
     354                                                // compute time stamp
     355                                                REFERENCE_TIME  tStart = (current_sample * 10000000) / file->sample_rate;
     356                                                REFERENCE_TIME  tStop  = ((current_sample + 1152*file->audio_block_frames) * 10000000) / file->sample_rate;
     357                                                packet.tStart = tStart;
     358                                                packet.tStop  = tStop;
     359
     360                                                // deliver packet
     361                                                output[0]->DeliverPacket(packet);
     362                                        }
     363
     364                                } while (!CheckRequest(&cmd2));
     365
     366                                // end of stream
     367                                if (ret == -1) {
     368                                        output[0]->DoEndOfStream();
     369                                }
     370
     371                        }
     372                        break;
     373                default:
     374                        Reply(E_UNEXPECTED);
     375                        break;
     376                }
     377        }
     378        return 0;
     379}
     380
     381
     382// IMediaSeeking
     383
     384STDMETHODIMP CMPCDemux::GetCapabilities(DWORD* pCapabilities)
     385{
     386        return pCapabilities ? *pCapabilities =
     387                        AM_SEEKING_CanGetStopPos|AM_SEEKING_CanGetDuration|AM_SEEKING_CanSeekAbsolute|AM_SEEKING_CanSeekForwards|AM_SEEKING_CanSeekBackwards,
     388                        S_OK : E_POINTER;
     389}
     390STDMETHODIMP CMPCDemux::CheckCapabilities(DWORD* pCapabilities)
     391{
     392        CheckPointer(pCapabilities, E_POINTER);
     393        if (*pCapabilities == 0) return S_OK;
     394        DWORD caps;
     395        GetCapabilities(&caps);
     396        if ((caps&*pCapabilities) == 0) return E_FAIL;
     397        if (caps == *pCapabilities) return S_OK;
     398        return S_FALSE;
     399}
     400STDMETHODIMP CMPCDemux::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
     401STDMETHODIMP CMPCDemux::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
     402STDMETHODIMP CMPCDemux::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
     403STDMETHODIMP CMPCDemux::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
     404STDMETHODIMP CMPCDemux::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
     405STDMETHODIMP CMPCDemux::GetStopPosition(LONGLONG* pStop) {return this->rtStop; }
     406STDMETHODIMP CMPCDemux::GetCurrentPosition(LONGLONG* pCurrent) {return E_NOTIMPL;}
     407STDMETHODIMP CMPCDemux::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
     408
     409STDMETHODIMP CMPCDemux::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
     410{
     411        return SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
     412}
     413
     414STDMETHODIMP CMPCDemux::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop)
     415{
     416        if(pCurrent) *pCurrent = rtCurrent;
     417        if(pStop) *pStop = rtStop;
     418        return S_OK;
     419}
     420STDMETHODIMP CMPCDemux::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest)
     421{
     422        if(pEarliest) *pEarliest = 0;
     423        return GetDuration(pLatest);
     424}
     425STDMETHODIMP CMPCDemux::SetRate(double dRate) {return dRate > 0 ? rate = dRate, S_OK : E_INVALIDARG;}
     426STDMETHODIMP CMPCDemux::GetRate(double* pdRate) {return pdRate ? *pdRate = rate, S_OK : E_POINTER;}
     427STDMETHODIMP CMPCDemux::GetPreroll(LONGLONG* pllPreroll) {return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;}
     428
     429STDMETHODIMP CMPCDemux::GetDuration(LONGLONG* pDuration)
     430{       
     431        CheckPointer(pDuration, E_POINTER);
     432        *pDuration = 0;
     433
     434        if (file) {
     435                if (pDuration) *pDuration = file->duration_10mhz;
     436        }
     437        return S_OK;
     438}
     439
     440STDMETHODIMP CMPCDemux::SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
     441{
     442        // only our first pin can seek
     443        if (iD != 0) return NOERROR;
     444        CAutoLock cAutoLock(&lock_filter);
     445
     446        if (!pCurrent && !pStop || (dwCurrentFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning
     447                && (dwStopFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
     448                return S_OK;
     449
     450        REFERENCE_TIME rtCurrent = this->rtCurrent, rtStop = this->rtStop;
     451
     452        if (pCurrent) {
     453                switch(dwCurrentFlags&AM_SEEKING_PositioningBitsMask) {
     454                case AM_SEEKING_NoPositioning: break;
     455                case AM_SEEKING_AbsolutePositioning: rtCurrent = *pCurrent; break;
     456                case AM_SEEKING_RelativePositioning: rtCurrent = rtCurrent + *pCurrent; break;
     457                case AM_SEEKING_IncrementalPositioning: rtCurrent = rtCurrent + *pCurrent; break;
     458                }
     459        }
     460
     461        if (pStop) {
     462                switch(dwStopFlags&AM_SEEKING_PositioningBitsMask) {
     463                case AM_SEEKING_NoPositioning: break;
     464                case AM_SEEKING_AbsolutePositioning: rtStop = *pStop; break;
     465                case AM_SEEKING_RelativePositioning: rtStop += *pStop; break;
     466                case AM_SEEKING_IncrementalPositioning: rtStop = rtCurrent + *pStop; break;
     467                }
     468        }
     469
     470        if (this->rtCurrent == rtCurrent && this->rtStop == rtStop) return S_OK;
     471
     472        this->rtCurrent = rtCurrent;
     473        this->rtStop = rtStop;
     474
     475        // now there are new valid Current and Stop positions
     476        HRESULT hr = DoNewSeek();
     477        return hr;
     478}
     479
     480HRESULT CMPCDemux::DoNewSeek()
     481{
     482        // stop first
     483        ev_abort.Set();
     484        if (reader) reader->BeginFlush();
     485
     486        for (int i=0; i<output.GetCount(); i++) {
     487                CMPCOutputPin   *pin = output[i];
     488                if (pin->IsConnected()) {
     489                        // abort
     490                        if (m_State != State_Stopped) {
     491                                if (pin->ThreadExists()) {
     492                                        pin->ev_abort.Set();
     493                                        pin->DeliverBeginFlush();
     494                                        pin->CallWorker(CMD_STOP);
     495                                        pin->FlushQueue();
     496                                }
     497                        }
     498                }
     499        }
     500
     501        for (int i=0; i<output.GetCount(); i++) {
     502                CMPCOutputPin   *pin = output[i];
     503                if (pin->IsConnected()) {
     504                        if (m_State != State_Stopped) {
     505                                if (pin->ThreadExists()) {
     506                                        pin->ev_abort.Reset();
     507                                        pin->DeliverEndFlush();
     508                                }
     509                        }
     510                        pin->DoNewSegment(rtCurrent, rtStop, rate);
     511                }
     512        }
     513
     514        if (ThreadExists()) {
     515                CallWorker(CMD_STOP);
     516        }
     517        if (reader) reader->EndFlush();
     518
     519        // seek the file
     520        if (file) {
     521                int64 sample_pos = rtCurrent * file->sample_rate / 10000000;
     522                file->Seek(sample_pos);
     523        }
     524
     525        ev_abort.Reset();
     526        if (ThreadExists()) {
     527                CallWorker(CMD_RUN);
     528        }
     529
     530        for (int i=0; i<output.GetCount(); i++) {
     531                CMPCOutputPin   *pin = output[i];
     532
     533                // we only care about connected pins
     534                if (pin->IsConnected()) {
     535                        if (m_State != State_Stopped) {
     536                                // spustime aj jeho thread
     537                                if (pin->ThreadExists()) {
     538                                        pin->CallWorker(CMD_RUN);
     539                                }
     540                        }
     541                }
     542        }
     543
     544        return NOERROR;
     545}
     546
     547
     548STDMETHODIMP CMPCDemux::Pause()
     549{
     550        CAutoLock       lck(&lock_filter);
     551
     552        if (m_State == State_Stopped) {
     553
     554                ev_abort.Reset();
     555
     556                // activate pins
     557                for (int i=0; i<output.GetCount(); i++) output[i]->Active();
     558                if (input) input->Active();
     559
     560                // seekneme na danu poziciu
     561                DoNewSeek();
     562
     563                // pustime parser thread
     564                if (!ThreadExists()) {
     565                        Create();
     566                        CallWorker(CMD_RUN);
     567                }
     568        }
     569
     570        m_State = State_Paused;
     571        return NOERROR;
     572}
     573
     574STDMETHODIMP CMPCDemux::Stop()
     575{
     576        CAutoLock       lock(&lock_filter);
     577        HRESULT         hr = NOERROR;
     578
     579        if (m_State != State_Stopped) {
     580
     581                // set abort
     582                ev_abort.Set();
     583                if (reader) reader->BeginFlush();
     584
     585                // deaktivujeme piny
     586                if (input) input->Inactive();
     587                for (int i=0; i<output.GetCount(); i++) output[i]->Inactive();
     588
     589                // zrusime parser thread
     590                if (ThreadExists()) {
     591                        CallWorker(CMD_EXIT);
     592                        Close();
     593                }
     594
     595                if (reader) reader->EndFlush();
     596        }
     597
     598
     599        m_State = State_Stopped;
     600        return hr;
     601}
Note: See TracChangeset for help on using the changeset viewer.