Changeset 368 for dsfilters/demux_mpc/src/mpc_filter.cpp
- Timestamp:
- 12/14/07 00:22:01 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
dsfilters/demux_mpc/src/mpc_filter.cpp
r366 r368 47 47 CMPCDemux::CMPCDemux(LPUNKNOWN pUnk, HRESULT *phr) : 48 48 CBaseFilter(_T("MPC Splitter"), pUnk, &lock_filter, CLSID_MusepackDemuxer, phr), 49 CAMThread(), 49 50 reader(NULL), 50 51 file(NULL), 51 wnd_prop(NULL) 52 wnd_prop(NULL), 53 rtCurrent(0), 54 rtStop(0xFFFFFFFFFFFFFF), 55 rate(1.0), 56 ev_abort(TRUE) 52 57 { 53 58 input = new CMPCInputPin(NAME("MPC Input Pin"), this, phr, L"In"); 54 59 output.RemoveAll(); 55 60 retired.RemoveAll(); 61 62 ev_abort.Reset(); 56 63 } 57 64 … … 82 89 if (riid == IID_IMusepackSplitter) { 83 90 return GetInterface((IMusepackSplitter*)this, ppv); 84 } else{ 85 /* 91 } else 86 92 if (riid == IID_IMediaSeeking) { 87 return GetInterface((IMediaSeeking *)this, ppv); 88 } else 89 */ 90 93 return GetInterface((IMediaSeeking*)this, ppv); 94 } else { 91 95 return CBaseFilter::NonDelegatingQueryInterface(riid,ppv); 92 96 } … … 185 189 } 186 190 191 HRESULT hr = NOERROR; 192 CMPCOutputPin *opin = new CMPCOutputPin(_T("Outpin"), this, &hr, L"Out", 5); 193 ConfigureMediaType(opin); 194 AddOutputPin(opin); 195 187 196 // refresh property page if there is any 188 197 if (IsWindow(wnd_prop)) { … … 215 224 216 225 226 HRESULT 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 217 257 HRESULT CMPCDemux::BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller) 218 258 { … … 221 261 if (Dir == PINDIR_INPUT) { 222 262 // let's disconnect the output pins 223 //ev_abort.Set();263 ev_abort.Set(); 224 264 //ev_ready.Set(); 225 265 … … 238 278 } 239 279 240 //ev_abort.Reset();280 ev_abort.Reset(); 241 281 } else 242 282 if (Dir == PINDIR_OUTPUT) { … … 271 311 } 272 312 273 274 275 313 DWORD 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, ¤t_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 384 STDMETHODIMP 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 } 390 STDMETHODIMP 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 } 400 STDMETHODIMP CMPCDemux::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;} 401 STDMETHODIMP CMPCDemux::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);} 402 STDMETHODIMP CMPCDemux::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;} 403 STDMETHODIMP CMPCDemux::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);} 404 STDMETHODIMP CMPCDemux::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;} 405 STDMETHODIMP CMPCDemux::GetStopPosition(LONGLONG* pStop) {return this->rtStop; } 406 STDMETHODIMP CMPCDemux::GetCurrentPosition(LONGLONG* pCurrent) {return E_NOTIMPL;} 407 STDMETHODIMP CMPCDemux::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;} 408 409 STDMETHODIMP CMPCDemux::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags) 410 { 411 return SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags); 412 } 413 414 STDMETHODIMP CMPCDemux::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) 415 { 416 if(pCurrent) *pCurrent = rtCurrent; 417 if(pStop) *pStop = rtStop; 418 return S_OK; 419 } 420 STDMETHODIMP CMPCDemux::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) 421 { 422 if(pEarliest) *pEarliest = 0; 423 return GetDuration(pLatest); 424 } 425 STDMETHODIMP CMPCDemux::SetRate(double dRate) {return dRate > 0 ? rate = dRate, S_OK : E_INVALIDARG;} 426 STDMETHODIMP CMPCDemux::GetRate(double* pdRate) {return pdRate ? *pdRate = rate, S_OK : E_POINTER;} 427 STDMETHODIMP CMPCDemux::GetPreroll(LONGLONG* pllPreroll) {return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;} 428 429 STDMETHODIMP 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 440 STDMETHODIMP 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 480 HRESULT 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 548 STDMETHODIMP 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 574 STDMETHODIMP 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.