Ignore:
Timestamp:
12/15/07 14:49:14 (16 years ago)
Author:
radscorpion
Message:

Decoder now can decode and play SV8 streams. It can be used along with old RadLight filter, which will take care of SV7 files.

File:
1 edited

Legend:

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

    r370 r371  
    4242CUnknown *CMPCDecoder::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
    4343{
     44        if (phr) *phr = NOERROR;
     45
    4446        return new CMPCDecoder(pUnk, phr);
    4547}
    4648
    4749CMPCDecoder::CMPCDecoder(LPUNKNOWN pUnk, HRESULT *phr) :
    48         CTransformFilter(_T("MPC Decoder"), pUnk, CLSID_MusepackDecoder)
    49 {
     50        CTransformFilter(_T("MPC Decoder"), pUnk, CLSID_MusepackDecoder),
     51        demux(NULL),
     52        decoder_specific(NULL),
     53        decoder_specific_size(0)
     54{
     55        if (phr) *phr = NOERROR;
     56
    5057        m_pInput = new CTransformInputPin(NAME("Input"), this, phr, L"Input");
    5158        m_pOutput = new CTransformOutputPin(NAME("Output"), this, phr, L"Output");
     
    108115                if (pmt->formattype != FORMAT_WaveFormatEx) return E_FAIL;
    109116
    110                 WAVEFORMATEX *wfx = (WAVEFORMATEX*)pmt->pbFormat;
     117                // keep a local copy so our decoder specific info doesn't go away
     118                mtIn = *pmt;
     119
     120                WAVEFORMATEX *wfx = (WAVEFORMATEX*)mtIn.pbFormat;
    111121
    112122                // we assemble output format
     
    116126                wfOut.wFormatTag = WAVE_FORMAT_PCM;
    117127                wfOut.wBitsPerSample = 16;                              // currently only 16-bit
     128
     129                // get hold of decoder specific info
     130                decoder_specific = ((BYTE*)wfx) + sizeof(WAVEFORMATEX);
     131                decoder_specific_size = wfx->cbSize;
     132
     133                mpc_demux       *dmx;
     134
     135                int ret = OpenDemux(&dmx, &stream_info);
     136                if (ret < 0) {
     137                        mpc_demux_exit(dmx);
     138                        return E_FAIL;
     139                }
     140
     141                // if the stream_info says something different...
     142                if (stream_info.sample_freq != wfx->nSamplesPerSec ||
     143                        stream_info.channels != wfx->nChannels
     144                        ) {
     145
     146                        // update values
     147                        wfOut.nChannels = stream_info.channels;
     148                        wfOut.nSamplesPerSec = stream_info.sample_freq;
     149                }
     150
    118151                wfOut.nBlockAlign = (wfOut.wBitsPerSample * wfOut.nChannels) >> 3;
    119152                wfOut.nAvgBytesPerSec = wfOut.nBlockAlign * wfOut.nSamplesPerSec;
    120153
     154                // done with the demuxer
     155                mpc_demux_exit(dmx);
    121156        }
    122157        return NOERROR;
     
    133168                        m_pOutput->Disconnect();
    134169                }
     170
     171                // cancel out decoder specific info
     172                decoder_specific = NULL;
     173                decoder_specific_size = 0;
    135174        }
    136175        return __super::BreakConnect(dir);
     
    195234        HRESULT hr = __super::StartStreaming();
    196235        if (FAILED(hr)) return hr;
     236
     237        ASSERT(!demux);
     238
     239        // now let's open the demuxer
     240        int ret = OpenDemux(&demux, &stream_info);
     241        if (ret < 0) return E_FAIL;
     242
    197243        return hr;
    198244}
     
    202248        HRESULT hr = __super::StopStreaming();
    203249        if (FAILED(hr)) return hr;
     250
     251        // done with demuxer
     252        mpc_demux_exit(demux);
     253        demux = NULL;
     254
    204255        return hr;
    205256}
    206257
     258#define FLOAT_CLIP(x)           (x < -1.0 ? -1.0 : x > 1.0 ? 1.0 : x)
     259
     260static void convert_float_to_int16_c(float *src, short *dst, int count)
     261{
     262        count -= 8;
     263        while (count > 0) {
     264                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     265                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     266                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     267                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     268                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     269                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     270                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     271                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     272                count -= 8;
     273        }
     274        count += 8;
     275
     276        // last few must be done one-by-one
     277        while (count > 0) {
     278                *dst++ = (short)(FLOAT_CLIP(*src) * 16380);     src++;
     279                count --;
     280        }
     281}
     282
    207283HRESULT CMPCDecoder::Receive(IMediaSample *pSample)
    208284{
    209285        if (!m_pOutput->IsConnected()) return NOERROR;
    210286
    211         // todo:
    212         return NOERROR;
    213 }
    214 
    215 
    216 
     287        // we receive whole AP packets so just decode the frames :D
     288        BYTE *pdata = NULL;
     289        long lsize  = 0;
     290        pSample->GetPointer(&pdata);
     291        lsize = pSample->GetActualDataLength();
     292
     293        // set the reader
     294        reader.SetData(pdata, lsize);
     295        reader.AppendSE();
     296
     297        // manually clear the buffer for demuxer
     298        demux->bytes_total = 0;
     299        demux->bits_reader.buff = demux->buffer;
     300        demux->bits_reader.count = 8;
     301        demux->block_bits = 0;
     302        demux->block_frames = 0;
     303
     304        // TODO: use some more clever way of doing this.
     305        MPC_SAMPLE_FORMAT       samples[1152 * 8];
     306        int                                     dec_samples;
     307
     308        // handling timestamps
     309        REFERENCE_TIME          rtStart, rtStop;
     310        __int64                         current_sample = 0;
     311        __int64                         samples_to_skip = 0;
     312        bool                            has_timestamp = false;
     313
     314        if (pSample->GetTime(&rtStart, &rtStop) == NOERROR) {
     315                has_timestamp = true;
     316                // calculate relative sample_time
     317                current_sample = (rtStart * stream_info.sample_freq) / 10000000;
     318
     319                if (current_sample < 0) {
     320                        samples_to_skip = -current_sample;
     321                }
     322        }
     323
     324        // now scan through the frames
     325        while (true) {
     326
     327                //---------------------------------------------------------------------
     328                //      Decoding Part
     329                //---------------------------------------------------------------------
     330
     331                mpc_frame_info  frame;
     332                mpc_status              err;
     333
     334                frame.buffer = (MPC_SAMPLE_FORMAT*)samples;
     335
     336                // decode one frame
     337                err = mpc_demux_decode(demux, &frame);
     338                if (err != MPC_STATUS_OK) break;
     339                if (frame.bits == -1) break;                            // done.
     340
     341                //---------------------------------------------------------------------
     342                //      Skipping samples...
     343                //---------------------------------------------------------------------
     344
     345                MPC_SAMPLE_FORMAT       *src_samples = frame.buffer;
     346                int                                     decoded_time_samples = frame.samples;
     347
     348                if (has_timestamp) {
     349                        if (samples_to_skip > 0) {
     350
     351                                // skip sample counters
     352                                __int64 to_skip = min(frame.samples, samples_to_skip);
     353                                decoded_time_samples -= to_skip;
     354                                current_sample           += to_skip;
     355                                src_samples                      += (to_skip * stream_info.channels);
     356                        }
     357                }
     358
     359                // if there's nothing left, continue
     360                if (decoded_time_samples <= 0) continue;
     361
     362                // total number of decoded samples
     363                dec_samples = decoded_time_samples * stream_info.channels;
     364
     365                //---------------------------------------------------------------------
     366                //      Convert and deliver
     367                //---------------------------------------------------------------------
     368
     369                // deliver decoded data
     370                IMediaSample    *sample;
     371                HRESULT                 hr;
     372                hr = GetDeliveryBuffer(&sample);
     373                if (FAILED(hr)) break;                          // perhaps allocator is decommited
     374
     375                BYTE *outp;
     376                sample->GetPointer(&outp);
     377
     378                // this should definitely be true
     379                ASSERT(sample->GetSize() >= (dec_samples * sizeof(short)));
     380
     381                // do format conversion
     382#ifdef MPC_FIXED_POINT
     383                // TODO: find ranges in headers somewhere
     384#else
     385                convert_float_to_int16_c((float*)src_samples, (short*)outp, dec_samples);
     386                sample->SetActualDataLength(dec_samples * sizeof(short));
     387#endif
     388
     389                // IMediaSample properties
     390                if (has_timestamp) {
     391                        REFERENCE_TIME  tstart, tstop;
     392                        tstart = (current_sample * 10000000) / stream_info.sample_freq;
     393                        tstop  = ((current_sample+decoded_time_samples) * 10000000) / stream_info.sample_freq;
     394                        sample->SetTime(&tstart, &tstop);
     395                }
     396                sample->SetSyncPoint(TRUE);
     397                sample->SetDiscontinuity(FALSE);
     398
     399                // advance time
     400                current_sample += decoded_time_samples;
     401
     402                hr = m_pOutput->Deliver(sample);
     403                sample->Release();
     404
     405                // something went wrong. stop decoding.
     406                if (FAILED(hr)) break;
     407        }
     408
     409        return NOERROR;
     410}
     411
     412int CMPCDecoder::OpenDemux(mpc_demux **dmx, mpc_streaminfo *si)
     413{
     414        // some data needed
     415        if (!decoder_specific || decoder_specific_size <= 0) return -1;
     416
     417        reader.SetData(decoder_specific, decoder_specific_size);
     418        (*dmx) = mpc_demux_init(&reader.rd);
     419        if (!(*dmx)) return -1;
     420
     421        mpc_demux_get_info((*dmx), si);
     422        return 0;
     423}
     424
     425
     426//-----------------------------------------------------------------------------
     427//
     428//      CMPCReader class
     429//
     430//-----------------------------------------------------------------------------
     431
     432static mpc_int32_t mpc_read_proc(mpc_reader *p_reader, void *ptr, mpc_int32_t size)
     433{
     434        CMPCReader *instance = (CMPCReader*)p_reader->data;
     435        ASSERT(instance);
     436        return instance->Read(ptr, size);
     437}
     438
     439static mpc_bool_t mpc_seek_proc(mpc_reader *p_reader, mpc_int32_t offset)
     440{
     441        CMPCReader *instance = (CMPCReader*)p_reader->data;
     442        ASSERT(instance);
     443        return instance->Seek(offset);
     444}
     445
     446static mpc_int32_t mpc_tell_proc(mpc_reader *p_reader)
     447{
     448        CMPCReader *instance = (CMPCReader*)p_reader->data;
     449        ASSERT(instance);
     450        return instance->Tell();
     451}
     452
     453static mpc_int32_t mpc_get_size_proc(mpc_reader *p_reader)
     454{
     455        CMPCReader *instance = (CMPCReader*)p_reader->data;
     456        ASSERT(instance);
     457        return instance->GetSize();
     458}
     459
     460static mpc_bool_t mpc_canseek_proc(mpc_reader *p_reader)
     461{
     462        CMPCReader *instance = (CMPCReader*)p_reader->data;
     463        ASSERT(instance);
     464        return instance->CanSeek();
     465}
     466
     467CMPCReader::CMPCReader()
     468{
     469        buf = (BYTE*)malloc(256*1024);          // 256 KB should be enough
     470        size = 0;
     471
     472        rd.data = (void*)this;
     473        rd.read = mpc_read_proc;
     474        rd.seek = mpc_seek_proc;
     475        rd.tell = mpc_tell_proc;
     476        rd.get_size = mpc_get_size_proc;
     477        rd.canseek = mpc_canseek_proc;
     478}
     479
     480CMPCReader::~CMPCReader()
     481{
     482        free(buf);
     483}
     484
     485int CMPCReader::Read(void *buf, int size)
     486{
     487        // return the number of bytes read
     488        int toread_max = min(this->size - this->pos, size);
     489        memcpy(buf, this->buf + this->pos, toread_max);
     490        this->pos += toread_max;
     491        return toread_max;
     492}
     493
     494bool CMPCReader::Seek(int offset)
     495{
     496        // sorry no seeking here
     497        return false;
     498}
     499
     500int CMPCReader::Tell()
     501{
     502        // that's where we are
     503        return pos;
     504}
     505
     506int CMPCReader::GetSize()
     507{
     508        // size of our supplied buffer
     509        return size;
     510}
     511
     512bool CMPCReader::CanSeek()
     513{
     514        // no. we are not seekable. upstream demuxer is.
     515        return false;
     516}
     517
     518void CMPCReader::SetData(BYTE *data, int size)
     519{
     520        ASSERT(size < 256*1024);
     521        memcpy(buf, data, size);
     522        this->size = size;
     523        this->pos = 0;
     524}
     525
     526void CMPCReader::AppendSE()
     527{
     528        BYTE *out = buf + size;
     529        out[0] = 'S';
     530        out[1] = 'E';
     531        out[2] = 0x03;
     532        size += 3;
     533}
     534
     535
     536
     537
     538
     539
     540
     541
Note: See TracChangeset for help on using the changeset viewer.